一. 三子棋簡單概述
相信大部分人都玩過五子棋,也知道五子棋的規則與玩法。而今天的三子棋就是簡易版的五子棋。
首先,在一張3*3的棋盤上,雙方先後落子,誰先形成三個相同且相連的棋,誰就贏得了比賽。可以是一排或者一列三個相同,也可以是兩個對角線上的三個棋子相同。如下圖所示,綠方獲勝。
從上方的簡單描述中,我們也可以大體知道,c語言實現這樣一個單機版的三子棋是什麼樣的。接下來我們就整體說一下思路。
二. c 語言實現三子棋的總體思路
- 首先,我們需要一個菜單界面,來提示用戶進行遊戲或者退出。
- 主函數裏分爲開始遊戲(game()函數)和退出,並且不同的情況調用他們各自的函數來實現功能。
- 在game()函數函數裏, 首先需要一個3*3的二維數組當作棋盤,並且需要對棋盤初始化,因爲雙方沒落子之前棋盤是空的,所以我們需要將棋盤的每個位置初始化爲空格字符( InitBoard()函數 )。遊戲一旦開始,我們需要將初始化後的棋盤顯示( ShowBoard()函數 )在用戶面前。接下來讓用戶輸入自己所要落子的位置,並且判斷該位置是否合法。用戶落子之後,需要判斷當前棋盤是否已滿,或者是否有人已經贏得比賽( Judge()函數 )。同樣,在用戶落子之後,電腦通過生成隨機數來落子。
- 最後,通過循環來依次落子。
三. 採取分文件來實現該項目
如上圖所示,就是今天分文件項目的三大部分。下面就每個文件裏邊的內容以及函數的具體實現一一說明。
1.main.c文件
此文件主要是來實現三子棋的總體框架,調用封裝好的各個接口。
#include"Game.h"
int main()
{
int quit = 0;
int select = 0;
while (!quit)
{
menu();
printf("\nPlease enter your choice:");
scanf("%d", &select);
switch (select)
{
case 1:
game();
break;
case 2:
quit = 1;
break;
default:
printf("\nInput Error,please enter your choice again:");
break;
}
}
system("pause");
return 0;
}
#include"Game.h"就是我們聲明瞭各大接口函數,以及宏定義、頭文件的聲明。quit是用來用戶是否要退出遊戲的一個標誌,用戶選擇2,則quit置爲1,!quit就是0,即條件不成立退出循環。
2.Game.h頭文件
此文件聲明瞭各大接口函數,以及宏定義、頭文件的聲明。
#ifndef _GAME_H_
#define _GAME_H_
#include<stdio.h>
#include<Windows.h>
#include<time.h>
#pragma warning(disable:4996)
#define COL 3
#define ROW 3
#define PLAYER 'X' //用戶落子用X字符顯示
#define COMPUTER 'O' //電腦落子用O字符顯示
#define N '1'
#define F '2'
//菜單函數
void menu();
//遊戲函數
void game();
//初始化棋盤的函數
void InitBoard(char board[][ROW], int row, int col);
//打印棋盤的函數
void ShowBoard(char board[][ROW], int row, int col);
//電腦落子函數
void ComputerPlay(char board[][ROW], int row, int col);
//判斷棋盤是否滿 或者此時是否有人贏得比賽
char Judge(char board[][ROW], int row, int col);
#endif
代碼裏聲明的每個函數的功能我都一一標註過~~~。
2.Game.c文件
大頭來了!!
首先說一下game()函數,此函數可是整個遊戲的中心,能否快樂下棋,就看此成敗!
void game()
{
char result ;
//中隨機數種子(爲後面電腦隨機生成座標種下隨機數種子)
srand((unsigned)time(NULL));
//定義3*3的棋盤
char board[ROW][COL];
//初始化錶盤
InitBoard(board, ROW, COL);
//通過循環落子
do{
//給用戶顯示錶盤
ShowBoard(board, ROW, COL);
printf("\n");
printf("請落子:");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
printf("\n");
//判斷落子座標是否合法
if (x<1 || x>3 || y<1 || y>3)
{
printf("您輸入的位置有誤,請重新輸入!\n");
continue;
}
if (board[x - 1][y - 1] !=' ')
{
printf("該位置已經被佔用,請重新輸入!\n");
continue;
}
//用戶落子(修改棋盤界面,讓用戶看到下棋的過程)
board[x - 1][y - 1] = PLAYER;
//判斷棋盤是否下滿或者有人是否贏了
result = Judge(board, ROW, COL);
if (result != 'N')//棋盤滿了或者贏了
{
ShowBoard(board, ROW, COL);
printf("\n");
break;
}
//電腦落子
ComputerPlay(board, ROW, COL);
result = Judge(board, ROW, COL);
if (result != 'N')
{
ShowBoard(board, ROW, COL);
printf("\n");
break;
}
} while (1);
if (result == PLAYER)
{
printf("\t恭喜你!,你贏了!\n\n");
}
else if (result == COMPUTER){
printf("\t不好意思,電腦贏了!\n\n");
}
else {
printf("\t玩的不錯,平局!\n\n");
}
printf("你玩的不錯要不要再來一把!!!~~~~~\n");
}
思路我在第二部分也說了,具體到每行代碼的註釋已經標註~~
菜單函數menu()
void menu()
{
printf("\n\n");
printf("\t\t#######################################################\n");
printf("\t\t#######################################################\n");
printf("\t\t####### ########\n");
printf("\t\t####### Welcome to three-and-crosses world! ########\n");
printf("\t\t####### ########\n");
printf("\t\t####### ########\n");
printf("\t\t####### 1.PLAY 2.EXIT ########\n");
printf("\t\t####### ########\n");
printf("\t\t#######################################################\n");
printf("\t\t#######################################################\n\n");
}
運行結果:
初始化棋盤函數InitBoard()
也就是將九個位置初始化爲空格
void InitBoard(char p[][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
p[i][j] = ' ';
}
}
}
打印棋盤函數 ShowBoard()
void ShowBoard(char board[][ROW], int row, int col)
{
int i = 0;
//printf("%d", row);
printf(" 1 2 3\n");
printf(" ---------------\n");
for (; i < row; i++)
{
printf(" %d |", i + 1);
for (int j = 0; j < col; j++)
{
printf(" %c | ", board[i][j]);
}
printf("\n ---------------\n");
}
}
運行結果:
電腦落子函數ComputerPlay()
//電腦下棋
void ComputerPlay(char board[][ROW], int row, int col)
{
while (1)
{
//產生1-2的隨機數
int random_x = rand() % row;
int random_y = rand() % col;
//判斷此處是否已落子
if (board[random_x][random_y] == ' ')
{
board[random_x][random_y] = COMPUTER;
break;
}
}
}
判斷是此時棋盤是否放滿Judge()函數
//判斷是此時棋盤是否放滿(N-->沒滿,繼續走,F--->滿了退出)
char Judge(char board[][ROW], int row, int col)
{
int i = 0;
for (; i < row; i++)
{
//判斷每行
if (board[i][1] != ' '&& board[i][1] == board[i][0] && board[i][0] == board[i][2])
{
return board[i][1];
}
//判斷每列
if (board[1][i] != ' ' && board[1][i] == board[0][i] && board[0][i] == board[2][i])
{
return board[1][i];
}
}
//判斷對角線
if ((board[1][1] != ' ' && board[1][1] == board[0][0] && board[0][0] == board[2][2]) || \
(board[1][1] != ' ' &&board[1][1] == board[2][0] && board[2][0] == board[2][2]))
{
return board[1][1];
}
//棋盤全部下滿 返回F ;沒滿 返回N
if (board[1][1] != ' '&& board[0][0] != ' '&& board[2][2] != ' '&& board[1][2] != ' '&& \
board[0][2] != ' '&& board[1][0] != ' '&&board[2][0] != ' '&&board[2][1] != ' '&&board[0][1] != ' ')
{
return 'F';
}
return 'N';
}
運行結果