三子棋想必大家都不陌生,甚至和小伙伴玩了不知道多少遍,我也不例外,
特別是以前電子產品不普及的時候,那個時候那張紙,畫個井字,就可以和小伙伴玩了,
那么今天我將來介紹一下如何用C語言設計簡易的三子棋游戲,(我們規定玩家的棋子為’*’,電腦的棋子為’#’)
首先進入游戲,我們需要設計一個選單內容,大概是下面這個樣子:

用四個printf函式即可實作
void menu()
{
printf("#######################\n");
printf("#### 1.play ####\n");
printf("#### 0.exit ####\n");
printf("#######################\n");
}
然后對于選項我們需要做出相應的回應,即玩家選1時開始游戲,玩家選0時結束游戲,玩家輸入其他數字則提示玩家重新輸入,以保證代碼的健壯性,故我們可以用一個switch陳述句實作,設定一個input變數以接收玩家的輸入,而且為了讓玩家可以多次游玩,我們使用一個do while陳述句來保證游戲的重復,代碼實作如下:
int main()
{
int input = 0;
do
{
menu();//列印選單
printf("請選擇:\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("游戲結束,程式退出\n");
break;
default:
printf("選擇錯誤,請重新選擇:\n");
break;
}
} while (input);
return 0;
}
接下來就需要實作這里的game()函式了,首先我們要設計一個棋盤來進行游戲,如何構建一個棋盤呢,首先我們要知道棋盤的大致樣子:


從圖中我們可以看出三子棋的棋盤有五行組成,那么我們可以用回圈來列印出棋盤,這里我們用char型的二維陣列存放棋盤中的棋子,代碼如下:
//符號的定義,之后更改棋盤大小更加方便
#define ROW 3
#define COL 3
//設定棋盤--二維陣列
char board[ROW][COL];
//初始化棋盤
InitBroad(board, ROW, COL);
//列印棋盤
DisplayBroad(board, ROW, COL);
函式實作:
void InitBroad(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 DisplayBroad(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("--- ");
printf("\n");
}
}
注意這里的陣列初始化是必要的,否則陣列的列印可能是隨機的(如圖):

列印出棋盤后就需要實作玩家和電腦的互動了,首先來實作玩家走的部分:
//玩家走
PlayerMove(board, ROW, COL);
DisplayBroad(board, ROW, COL);//每次走完更新一次棋盤
由于陣列的下標是從0開始的,而玩家一般認為坐標是總1開始的,故在處理玩家輸入的坐標時要-1確保落子的正確性,同時要判斷玩家輸入的坐標的合法性,是否落在棋盤內且該處無棋子,那么代碼的實作就很明顯了:
void PlayerMove(char board[ROW][COL], int row, int col)
{
printf("玩家走:\n");
while (1)
{
printf("請輸入坐標:\n");
int x = 0;//接收坐標
int y = 0;
scanf("%d %d", &x, &y);
//判斷坐標的合法性
if (x >= 1 && x <= row && y >= 1 && y <= col && board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("坐標非法,請重新輸入:\n");
}
}
}
對于電腦,我們使用亂數來確定電腦的落子,則需要使用到rand()函式產生亂數,而電腦的落子是有我們設計的,故不需要判斷合法性,代碼實作與玩家略有不同:
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
srand((unsigned int)time(NULL));
printf("電腦走:\n");
while (1)
{
x = rand() % 3;//產生0-2的亂數字作為陣列下標
y = rand() % 3;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
最后也是最為關鍵的步驟就是判斷游戲行程,游戲每落下一次子就會產生四種狀態,即玩家贏,電腦贏,平局以及游戲繼續,不妨令這些狀態分別對應四個不同的字符,即玩家贏:回傳’*’,電腦贏,回傳’#’,平局,回傳’Q’,游戲繼續,回傳’C’,這里我們設計一個回傳型別為char型的Judgegame()函式來接收對應的游戲狀態,并將回傳值賦給ret變數,在每次的落子后判斷一下,
PlayerMove(board, ROW, COL);
DisplayBroad(board, ROW, COL);//每次走完更新一次棋盤
//判斷游戲狀態
ret = Judgegame(board, ROW, COL);
if (ret == '*')
{
printf("玩家贏\n");
break;
}
else if (ret == 'Q')
{
printf("平局\n");
break;
}
//電腦走
ComputerMove(board, ROW, COL);
DisplayBroad(board, ROW, COL);
ret = Judgegame(board, ROW, COL);
if (ret == '#')
{
printf("電腦贏\n");
break;
}
else if (ret == 'Q')
{
printf("平局\n");
break;
}
那么我們來實作一下Judgegame函式,直接上代碼:
char Judgegame(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 - 2; j++)
{
if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && board[i][j] != ' ')
{
return board[i][j];
}
}
}
//列相等
for (j = 0; j < col; j++)
{
for (i = 0; i < row - 2; i++)
{
if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i][j] != ' ')
return board[i][j];
}
}
//主對角線相等
for (i = 0; i < row - 2; i++)
{
for (j = 0; j < col - 2; j++)
{
if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i][j] != ' ')
return board[i][j];
}
}
//副對角線相等
for (i = 0; i < row - 2; i++)
{
for (j = col - 1; j > 1; j--)
{
if (board[i][j] == board[i + 1][j - 1] && board[i + 1][j - 1] == board[i + 2][j - 2] && board[i][j] != ' ')
return board[i][j];
}
}
if (IsFull(board, row, col))//判斷棋盤是否滿,滿則平局,不滿則游戲繼續
return 'Q';
else
return 'C';
}
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;
}
由于三子棋的規則是有三個子連成一條線則判斷勝利,故我們窮舉出所有的勝利條件,而回傳的*和#剛好是我們的棋子,故這里的設計是十分巧妙的,并且為了不把代碼寫死,我們將判斷變為遍歷整個棋盤去找出是否有三子連成直線,以便棋盤擴大后的實作,
至此,我們的三子棋游戲已經大致設計完畢了,我們先來一把看看效果:

由于電腦的落子是由亂數產生的,故電腦想要贏是比較難的,只能通過放水來讓電腦贏:

最后再來看一下平局:

由于是簡易版的三子棋設計,因此就游戲性而言肯定是設計的不夠好的,在之后更深入的學習之后,還可以實作電腦的走法更加的完善,而非隨機走,
那么這就是這次簡易三子棋的C語言程式設計了,
完整的代碼
希望大家能夠點個贊~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/279896.html
標籤:其他
上一篇:關于汽車電子測驗工程師
