用C語言實現三子棋
阿新 • • 發佈:2021-02-09
技術標籤:c語言
前言
首先我們需要建立兩個原始檔分別為test.c與game.c前者為遊戲的測試,後者為遊戲相關函式的定義,同時建立相應的名為game.h的原始檔宣告相關函式。
遊戲框架
接下來可以開始搭建主函式框架了,因為不管如何,都會至少進入一次遊戲,由玩家確定退出或繼續,因此,筆者在該處運用do-while迴圈實現基本框架。
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
Menu();
printf("請選擇:>");
scanf("%d" ,&input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出遊戲。\n");
break;
default:
printf("選擇錯誤,請重新選擇:>\n");
break;
}
} while (input);
return 0;
}
棋盤奧祕
當玩家選擇進入遊戲後,通過game函式完成遊戲過程,首先需要建立一個二維陣列模擬棋盤,通過陣列元素的改變實現人機對下。顯然,棋盤最初無子,通過棋盤初始化函式實現陣列空白棋盤,但是隻是簡單的空格打印出來玩家必定一頭霧水,因此我們還需設計一個合理且美觀的棋盤,如下:
![在這裡插入圖片描述](https://img.796t.com/res/2021/02-09/17/fe431215313575aafa22230582381e9b.png)
以三行三列為例,將該棋盤的列印分為三組,除最後一組外,每一組包括兩行列印,一行為落子行,一行為分割行(最後一組無),而落子行又可分為3小組,除最後一小組外,每一小組又包括“ 字元 |”的列印,同理分割行亦可分組。由此我們建立兩個迴圈變數分別控制行和列並於迴圈中判斷是否為尾行或尾列,最後不要忘記換行。該函式具體實現如下:
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++ )
board[i][j] = ' ';
}
}
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\n");
}
}
void Menu()
{
printf("***********************\n");
printf("**** 1.Play ****\n");
printf("**** 0.Exit ****\n");
printf("***********************\n");
}
落子實現
完成對棋盤的列印後,接下來就可以落子了,以玩家方為 ‘*’ ,電腦方為 ‘#’ 為例,由玩家輸入兩個有效座標將棋盤對應位置的元素賦值 ,此時須注意座標的合法性(是否越界)與合理性(是否被佔用)。由於筆者愚鈍,遂只用生成隨機數的方式實現電腦落子,需注意的是在rand()呼叫前還需於主函式呼叫一次srand()函式,引數用強制型別轉換後的時間戳(引數為空指標)。由於需判斷座標的合理性與合法性,二者都可以採用while迴圈實現,當座標正確時break跳出迴圈。具體實現如下:
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋\n");
while (1)
{
printf("請輸入座標: > \n");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row&&y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("該位置已被佔用,請重新輸入!\n");
}
else
printf("位置非法,請重新輸入!\n");
}
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("電腦下棋\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
判斷輸贏
落子成功後除了列印棋盤外就是判斷遊戲輸贏了,不難想到,每下完一步棋,總有四種狀態,分別是:玩家贏,電腦贏,平局,繼續。而除繼續外其它狀態都直接結束遊戲,由此可整個下棋過程置於迴圈中,建立函式判斷狀態,除繼續外都直接break跳出迴圈。而輸贏判斷則是判斷行,列,斜的元素是否相同且不等於空格,直接返回相應字元判斷即可。若無未發現誰贏則還需判斷棋盤是否已滿,若滿了,則該局為平局。該過程具體實現如下:
static int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
char CheckWin(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
//行判斷
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
}
//列判斷
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[2][j] == board[1][j] && board[0][j] != ' ')
return board[0][j];
}
//對角線判斷
if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] != ' ')
return board[0][0];
if (board[2][0] == board[1][1] && board[0][2] == board[2][0] && board[1][1] != ' ')
return board[2][0];
//平局判斷
if (IsFull(board, row, col) == 1)
return 'Q';
else
return 'c';
}
結尾
感謝各位小夥伴看到最後,最後是三子棋遊戲實現的具體步驟
void game()
{
int ret = 0;
char board[ROW][COL] ;
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
while (1)
{
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = CheckWin(board, ROW, COL);
if (ret != 'c')
break;
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = CheckWin(board, ROW, COL);
if (ret != 'c')
break;
}
if (ret == '*')
printf("玩家贏了\n");
else if (ret == '#')
printf("電腦贏了\n");
else
printf("平局\n");
}