游戲規則
有如下圖的一個棋盤,一方下白子,一方下黑子,直到出現第一個三點一線,游戲結束!

創建棋盤
我們要設計這個游戲,首先就出現幾個問題,
如何設計棋盤呢? 創建一個3*3的二維陣列,每個元素是一個 char型別,
用‘x’表示黑子(玩家1),用‘o’表示白子(玩家2),用‘ ’(空格)表示空白,這樣,棋盤就設計好了,
游戲流程
1、創建棋盤,并且初始化~ 把所有的位置都設為空格~
做兩個回圈就可以啦,一個控制行,一個控制列
void init(char chess[MAX_ROW][MAX_COL])
{
for (int row = 0; row < MAX_ROW; row++)
{
for (int col = 0; col < MAX_COL; col++)
{
chess[row][col] = ' ';
}
} //注意這里MAX_ROW 和MAX_COL的值,雖然我們知道是三,但還是要進行宏定義,這樣可以避免重復的3的意義,提高代碼的可讀性
}
2、列印棋盤~
我們需要做一個列印函式;
一是要把chess[row][col]列印出來;
二是要把棋盤作美化;
void print(char chess[MAX_ROW][MAX_COL])
{
printf("+---+---+---+\n");
for (int row = 0; row < MAX_ROW; row++)
{
printf("|");
for (int col = 0; col < MAX_COL; col++)
{
printf(" %c |", chess[row][col]);
}
printf("\n+---+---+---+\n");
}
}
我們來看一下效果:

是不是很可觀呢?
3、玩家進行落子~ 我們創建的是二維陣列,就讓玩家輸入一組坐標(row,col)進行落子~
玩家進行落子,是不是玩家一次,電腦一次,玩家一次……這是一個回圈呀!
但這里我們還需要注意的問題是:玩家會不會胡亂輸入呀?有兩種情況:
1.輸入的位置超出chess陣列范圍,就是下到棋盤外面去了;
2.輸入的位置之前以及有子了;
這就需要我們進行合法性判定了;
那怎么落子啊? 輸入對應位置坐標,將該位置的棋盤初始化成‘*’就好了
void playerMove(char chessBoard[MAX_ROW][MAX_COL])
{
printf("玩家落子....\n");
while (1)
{
printf("請輸入坐標(row col): ");
int row = 0;
int col = 0;
scanf("%d %d", &row, &col);
// 進行合法性判定
//是否越界,合法繼續,不合法重新輸入
if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL)
{
printf("您輸入的坐標非法! 請重新輸入!\n");
continue;
}
//是否有子
if (chessBoard[row][col] != ' ')
{
printf("您輸入的位置已經有子了, 請重新輸入!\n");
continue;
}
// 進行落子~~
chessBoard[row][col] = 'x';
break;
}
}
4、判定獲勝~
判定勝負有三種情況,玩家勝,電腦勝,和棋!
1.勝負:遍歷所有行,所有列,還有對角線,有對應的三個數不為空格且相等就說明游戲結束了,我們回傳這條線上的任意一個文章,如果是‘x’,就說明玩家勝,如果是‘o’,就是電腦勝了
2.和棋:判定標準就是,只要棋盤滿了就和棋了,遍歷棋盤所有位置,不是空格就滿了,
這里我們分別設定一個函式來判斷!來看操作:
// 回傳 1 表示滿了, 回傳 0 表示沒滿
int isFull(char chessBoard[MAX_ROW][MAX_COL])
{
// 遍歷棋盤, 看看有沒有空格. 有空格就是沒滿~~
for (int row = 0; row < MAX_ROW; row++)
{
for (int col = 0; col < MAX_COL; col++)
{
if (chessBoard[row][col] == ' ')
{
return 0;
}
}
}
return 1;
}
// 此處約定,
// 如果回傳 x, 表示 玩家獲勝
// 如果回傳 o, 表示 電腦獲勝
// 如果回傳 ' ', 表示勝負未分, 還要繼續下棋
// 如果回傳 q, 表示和棋
char isGameOver(char chessBoard[MAX_ROW][MAX_COL])
{
// 掃描所有的行, 所有的列, 以及兩個對角線~~
for (int row = 0; row < MAX_ROW; row++)
{
if (chessBoard[row][0] != ' '
&& chessBoard[row][0] == chessBoard[row][1]
&& chessBoard[row][0] == chessBoard[row][2])
{
return chessBoard[row][0];
}
}
for (int col = 0; col < MAX_COL; col++)
{
if (chessBoard[0][col] != ' '
&& chessBoard[0][col] == chessBoard[1][col]
&& chessBoard[0][col] == chessBoard[2][col])
{
return chessBoard[0][col];
}
}
if (chessBoard[0][0] != ' '
&& chessBoard[0][0] == chessBoard[1][1]
&& chessBoard[0][0] == chessBoard[2][2])
{
return chessBoard[0][0];
}
if (chessBoard[0][2] != ' '
&& chessBoard[0][2] == chessBoard[1][1]
&& chessBoard[0][2] == chessBoard[2][0])
{
return chessBoard[0][2];
}
// 判定是否和棋
if (isFull(chessBoard))
{
return 'q';
}
// 勝負未分
return ' ';
}
5、電腦進行落子~(隨機落子)
電腦怎么進行落子呀?把某個位置(空位置)初始化成‘o’就好了
這里我們需要注意兩個關鍵詞: 隨機 空位置
看到空位置,我們就知道進行合法性判斷啦,不能落在以及有子的位置,那我們為什么不判斷落子的位置是否越界呢?
這就需要注意到隨機啦,上次的猜數字游戲中我們談到,使用rand()函式可以自定義亂數產生的范圍,還記得用法嗎? rand()%rand_max求0~rand_max的隨機值; rand()% (Y-X+1)+X;求 X~Y的隨機值
注意這樣產生的亂數是固定的,如果需要每次運行都產生不同的亂數,我們就需要借助時間戳了,引入亂數種子srand((unsigned int )time(NULL));即可
void computerMove(char chessBoard[MAX_ROW][MAX_COL])
{
while (1) {
int row = rand() % MAX_ROW;
int col = rand() % MAX_COL;
if (chessBoard[row][col] != ' ')
{
// 這個位置已經有子了
continue;
}
chessBoard[row][col] = 'o';
break;
}
}
6、判定獲勝~
代碼同上,邏輯上這一步存在的意義是:玩家落子完,判斷勝負;電腦落子完,判斷勝負;
完整實作
#define MAX_ROW 3
#define MAX_COL 3
void init(char chess[MAX_ROW][MAX_COL]) {
for (int row = 0; row < MAX_ROW; row++) {
for (int col = 0; col < MAX_COL; col++) {
chess[row][col] = ' ';
}
}
}
void print(char chess[MAX_ROW][MAX_COL]) {
printf("+---+---+---+\n");
for (int row = 0; row < MAX_ROW; row++) {
printf("|");
for (int col = 0; col < MAX_COL; col++) {
printf(" %c |", chess[row][col]);
}
printf("\n+---+---+---+\n");
}
}
void playerMove(char chessBoard[MAX_ROW][MAX_COL]) {
printf("玩家落子....\n");
while (1) {
printf("請輸入坐標(row col): ");
int row = 0;
int col = 0;
scanf("%d %d", &row, &col);
// 進行合法性校驗, 判定用戶輸入的內容是否是合法的
// 如果不合法, 就讓用戶重新輸入
if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL) {
// 就是不合法, 于是要讓用戶重新輸入
printf("您輸入的坐標非法! 請重新輸入!\n");
continue;
}
// 假設用戶輸入了1, 1, 但是 1 1 位置已經有子了~~
if (chessBoard[row][col] != ' ') {
// 該位置已經有子了
printf("您輸入的位置已經有子了, 請重新輸入!\n");
continue;
}
// 進行落子~~
chessBoard[row][col] = 'x';
break;
}
}
void computerMove(char chessBoard[MAX_ROW][MAX_COL]) {
while (1) {
int row = rand() % MAX_ROW;
int col = rand() % MAX_COL;
if (chessBoard[row][col] != ' ') {
// 這個位置已經有子了
continue;
}
chessBoard[row][col] = 'o';
break;
}
}
// 回傳 1 表示滿了, 回傳 0 表示沒滿
int isFull(char chessBoard[MAX_ROW][MAX_COL]) {
// 遍歷棋盤, 看看有沒有空格. 有空格就是沒滿~~
for (int row = 0; row < MAX_ROW; row++) {
for (int col = 0; col < MAX_COL; col++) {
if (chessBoard[row][col] == ' ') {
return 0;
}
}
}
return 1;
}
// 此處約定,
// 如果回傳 x, 表示 玩家獲勝
// 如果回傳 o, 表示 電腦獲勝
// 如果回傳 ' ', 表示勝負未分, 還要繼續下棋
// 如果回傳 q, 表示和棋
char isGameOver(char chessBoard[MAX_ROW][MAX_COL]) {
// 掃描所有的行, 所有的列, 以及兩個對角線~~
for (int row = 0; row < MAX_ROW; row++) {
if (chessBoard[row][0] != ' '
&& chessBoard[row][0] == chessBoard[row][1]
&& chessBoard[row][0] == chessBoard[row][2]) {
return chessBoard[row][0];
}
}
for (int col = 0; col < MAX_COL; col++) {
if (chessBoard[0][col] != ' '
&& chessBoard[0][col] == chessBoard[1][col]
&& chessBoard[0][col] == chessBoard[2][col]) {
return chessBoard[0][col];
}
}
if (chessBoard[0][0] != ' '
&& chessBoard[0][0] == chessBoard[1][1]
&& chessBoard[0][0] == chessBoard[2][2]) {
return chessBoard[0][0];
}
if (chessBoard[0][2] != ' '
&& chessBoard[0][2] == chessBoard[1][1]
&& chessBoard[0][2] == chessBoard[2][0]) {
return chessBoard[0][2];
}
// 判定是否和棋
if (isFull(chessBoard)) {
return 'q';
}
// 勝負未分
return ' ';
}
int main()
{
// 不建議使用全局變數
// 搜索樹
char chessBoard[MAX_ROW][MAX_COL];
// 1. 對棋盤進行初始化
init(chessBoard);
char winner = ' ';
while (1) {
// 2. 列印棋盤
print(chessBoard);
// 3. 玩家落子
playerMove(chessBoard);
// 4. 判定勝負
winner = isGameOver(chessBoard);
if (winner != ' ') {
// 游戲結束
break;
}
// 5. 電腦落子
computerMove(chessBoard);
// 6. 判定勝負
winner = isGameOver(chessBoard);
if (winner != ' ') {
// 游戲結束
break;
}
}
if (winner == 'x') {
printf("恭喜你贏了!\n");
}
else if (winner == 'o') {
printf("你咋連人工智障都下不過!\n");
}
else {
printf("你和人工智障五五開!\n");
}
system("pause");
return 0;
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/280977.html
標籤:其他
上一篇:機器人編程趣味實踐01-簡要介紹
