我可能寫的有些啰嗦,見諒,但我會很詳細的講解每一個步驟,
分析步驟
- 游戲框架的構造(游戲結構的設計)
- 代碼布局設計
- 對游戲布局,初始選項的思考
- 將上述游戲設計實作
- 判斷棋盤的局面
- char ifdraw(char board[ROW][COL])
- 計算機堵截玩家的演算法設計:思路
- 主函式界面
- game.c
- game.h
游戲框架的構造(游戲結構的設計)
1,游戲需要選單
2,需要選項(進入游戲或退出)
3,三子棋需要一個3*3的棋盤
4,需要將棋盤表現(列印出來)
5,玩家要開始下棋(輸入坐標)
6,每次落子后都要判斷輸贏或平局
7,列印目前棋盤的狀況
8,電腦開始落子
9,每次落子后都要判斷輸贏或平局
10,列印目前棋盤的狀況
11.判斷游戲目前的局面(輸或贏,繼續落子或者平局)
代碼布局設計
由于,代碼量過大,并且各個函式的設計及作用,并且考慮N子棋的可能,我們需要分模塊,分檔案來寫,
對游戲布局,初始選項的思考
游戲選單-進入游戲或者退出—分支陳述句(switch)
還要列印游戲選單,使用函式,
為了多次play游戲,也包括多次選項輸入,考慮do{}while();回圈,可以至少進入一次回圈,
void option(int input)
{
switch (input)//分支陳述句
{
case 1:
game();//進入游戲
break;
case 0:
printf("Logon out the game\n");
break;
default:
printf("Input error,please input again\n");
break;
}
}
void menu(void)
{
printf("Welcome to game\n");
printf("\n");
printf("****************\n");
printf("*----1.play----*\n");
printf("*----0.exit----*\n");
printf("****************\n");
}
int main(void)
{
int input;
//srand((unsigned int)time(NULL));時間戳,為電腦落子設定亂數
do
{
menu();//列印游戲選單
printf("please input option(1/0):>");
scanf("%d", &input);
option(input);//選項判斷
} while (input);
return 0;
}
我們要求輸入數字1或0,如果輸入其他值,就會default結束,并進入while判斷,為,int型,再次回圈,
game函式的實作
- 游戲框架的構造(游戲結構的設計)
- 代碼布局設計
- 對游戲布局,初始選項的思考
- 將上述游戲設計實作
- 判斷棋盤的局面
- char ifdraw(char board[ROW][COL])
- 計算機堵截玩家的演算法設計:思路
- 主函式界面
- game.c
- game.h
將上述游戲設計實作
1,三子棋需要一個3*3的棋盤
2,需要將棋盤表現(列印出來)
3.玩家要開始下棋(輸入坐標)
4.每次落子后都要判斷輸贏或平局
5,列印目前棋盤的狀況
6,電腦開始落子
7,每次落子后都要判斷輸贏或平局
8,列印目前棋盤的狀況
void game(void)
{
char ret;
char board[ROW][COL];//創建二維陣列
setboard(board, ROW, COL);//制作棋盤
while (1)
{
player(board);//玩家開始下棋
ret=judgewinner(board);//判斷輸贏
if (ret != 'C')
break;
computer(board);//電腦開始下棋
ret=judgewinner(board);//判斷輸贏
if (ret != 'C')
break;
}
if (ret == '*')
printf("The winner is player\n");
else if (ret == '#')
printf("The winner is computer\n");
else if (ret == 'D')
printf("Player and computer draw\n");
}
1,三子棋需要一個3*3的棋盤
畢竟是個3 * 3的棋盤,可以使用二維陣列,
char board[3][3]//這兩個行列可以使用宏定義常量,方便延申N子棋,
#define ROW 3
#define COL 3
char board[ROW][COL]
2, 列印三子棋棋盤
大概是這樣的

二維陣列的元素也要被定義為空格,在后面玩家或電腦輸入后可以被重新定義為*號或#號,
void setboard(char board[ROW][COL], int row, int col)//制作第一個棋盤
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';//元素被定義為空格
}
}
showboard(board,ROW, COL);//列印棋盤的函式
}
void showboard(char board[ROW][COL], int row, int col)//列印棋盤
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col)
printf("|");
}
if (i < row)
printf("\n---|---|---|\n");
}
}
3,玩家落子
就是輸入坐標
void player(char board[ROW][COL])//玩家下棋
{
int x, y;
while (1)
{
printf("please input the coordinate:>");
scanf("%d %d", &x, &y);//輸入要落子的坐標
if (x>=1&&x<=ROW&&y>=1&&y<=COL)//判斷該坐標處,是否未被輸入過
{
if (board[x - 1][y - 1] != ' ')
printf("Coordinates occupied,please input again\n");
else
{
board[x - 1][y - 1] = '*';
break;
}
}
else
printf("Coordinate is illegal,please input again\n");//被使用過,重新輸入
}
//printf("*******************\n");
printf("Player\n");
showboard(board, ROW, COL);//列印每次下棋后的棋盤
}
由于玩家并不是程式員不認為,起點是0,所以賦值時要x-1,y-1.,
并且這是多次輸入,要保證輸入那個坐標處不能已經輸入過,就是說要保證該陣列元素只能為空格,同時還要保證輸入坐標要有效,必須在33的棋盤內,如果兩個問題有一個存在,必須要重新輸入,所以放入回圈內,直到輸入正確,才會跳出回圈,
4,先不考慮判斷輸贏,先列印當前棋盤,就是呼叫showboard(board, ROW, COL);函式,回圈列印,
先保證電腦和玩家的棋盤輸入輸出正確再來判斷輸贏,
6,電腦開始落子,列印棋盤
暫時先使用隨機落子的演算法,下次我再寫堵截玩家落子的演算法
void computer(char board[ROW][COL])//電腦落子
{
while (1)
{
int x = rand() % ROW;
int y = rand() % COL;
if (board[x][y] == ' ')//判斷該坐標處,是否未被輸入過
{
board[x][y] = '#';
break;
}
}
printf("Computer\n");
//printf("*******************\n");
showboard(board, ROW, COL);//列印每次下棋后的棋盤
}
前面已經使用srand();,保證了亂數
int x = rand() % ROW;
int y = rand() % COL;
X y,為亂數除以排或列的余數,也就是說xy的值必定小于排,列的值,也就保證了xy,為 0,1,2
這也同樣保證了由三子棋走向N子棋的條件,
同樣得保證電腦落子的坐標處不能已經使用過,必須得保證坐標元素處為空格,才能輸入#,并且呼叫函式列印當前棋盤,
判斷棋盤的局面
呼叫char judgewinner(char board[ROW][COL])函式
char ifdraw(char board[ROW][COL])
{
int i;
for (i = 0; i < ROW; i++)
{
int j;
for (j = 0; j < COL; j++)
{
if (board[i][j] == ' ')
return 'C';
}
}
return 'D';
}
char judgewinner(char board[ROW][COL])
{
int count;
//判斷一行贏
for (int i = 0; i < ROW; i++)
{
int j,count=0;
for (j = 0; j < COL-1; j++)
{
if (board[i][j] != board[i][j + 1])
break;
else if (board[i][j] == board[i][j + 1])
count++;
}
if (count == COL - 1)
{
if (board[i][j] == '*')
return '*';//玩家贏
else if (board[i][j] == '#')
return '#';//電腦贏
}
if ((count != COL - 1) && (i == ROW - 1))
return ifdraw(board);//平局
}
//判斷列贏
for (int i = 0; i < COL; i++)
{
int j, count = 0;
for (j = 0; j < ROW - 1; j++)
{
if (board[i][j] != board[i][j + 1])
break;
else if (board[i][j] == board[i][j + 1])
count++;
}
if (count == ROW - 1)
{
if (board[i][j] == '*')
return '*';//玩家贏
else if (board[i][j] == '#')
return '#';//電腦贏
}
if ((count != ROW - 1) && i == COL - 1)
return ifdraw(board);//平局
}
//判斷對角線\贏
count = 0;
int i = 0;
int j;
while ((count != COL - 1) && (i <ROW-1))
{
j = i;
if (board[i][j] == board[i + 1][j + 1])
count++;
else if (board[i][j] != board[i + 1][j + 1])
break;
i++;
if (count == ROW - 1)
{
if (board[i][j] == '*')
return '*';//玩家贏
else if (board[i][j] == '#')
return '#';//電腦贏
}
}
return ifdraw(board);//平局}
//對角線/
count=0;
i = ROW - 1;
while (i>0)
{
j=ROW-i-1;
if (board[i][j] == board[i - 1][j + 1])
count++;
else if (board[i][j] = board[i - 1][j + 1])
break;
i--;
if (count == COL - 1)
{
if (board[i][j] == '*')
return '*';//玩家贏
else if (board[i][j] == '#')
return '#';//電腦贏
}
}
return ifdraw(board);//平局
}
判斷一行或者一列的棋子都相等的情況下,我們使用l兩個for回圈,我們同時定義一個控制變數,外回圈,保證每一個行或每列都能覆寫,內回圈來確定每一行或每一列上的元素,相鄰之間是否相等?如果相等,count加一,不相等就可以確定,不存在決定當前棋局的條件,直接跳出,同樣支持N子棋的判斷,
對于左斜線以及右斜線上的三指相的條件,這個就比較簡單,,不需要一遍遍的遍歷,只需要找到特定的三個元素去判斷是否相等即可得出條件,
用這些回圈條件來判斷,只能得出是否是玩家贏還是電腦贏,但是還需要添加一個函式來判斷是否是平局或者棋局未滿,可以繼續落子,
char ifdraw(char board[ROW][COL])
判斷平局或繼續落子,
用兩個for回圈去遍歷陣列只要判斷出有一個元素是空格隔那么就回傳c就可以直接得出可以繼續落子,就需要回傳來D來決定已經平局無法再落子,
因為一旦進入這卡數就表明已經判斷出無法決定誰勝或者誰負,只能繼續走兩條路一就是平局,二就是繼續落子,
同時,設定了ret來接受judgewinner(char board[ROW][COL])函式的回傳值,來判斷是否可以繼續回圈落子,
計算機堵截玩家的演算法設計:思路
游戲的規則是行列斜線,三種情況下,只要有一種情況,該線上都歸屬于三個同樣的旗子,即可判斷輸贏
我們可以考慮回圈遍歷
依靠回圈進入每行每列,每個斜線,進行每個元素的遍歷,如果該行該列或該斜線上有兩個相同的元素,立馬在第三個元素上進行,若無論是否與自己相同.
該思路目前只適用于三字棋,也可延伸到四子棋,4則是兩個起步,如果該列該行或該切線上有兩個以上的相同元素,就立馬在第三或第四個元素中進行落子
以下便是為拆開講解的全部代碼,
三子棋
- 游戲框架的構造(游戲結構的設計)
- 代碼布局設計
- 對游戲布局,初始選項的思考
- 將上述游戲設計實作
- 判斷棋盤的局面
- char ifdraw(char board[ROW][COL])
- 計算機堵截玩家的演算法設計:思路
- 主函式界面
- game.c
- game.h
主函式界面
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "game.h"
#define ROW 3
#define COL 3
//回傳值
//*
//#
//C-繼續
//D-平局
void game(void)
{
char ret;
char board[ROW][COL];//創建二維陣列
setboard(board, ROW, COL);//制作棋盤
while (1)
{
player(board);//玩家開始下棋
ret=judgewinner(board);//判斷輸贏
if (ret != 'C')
break;
computer(board);//電腦開始下棋
ret=judgewinner(board);//判斷輸贏
if (ret != 'C')
break;
}
if (ret == '*')
printf("The winner is player\n");
else if (ret == '#')
printf("The winner is computer\n");
else if (ret == 'D')
printf("Player and computer draw\n");
}
void option(int input)
{
switch (input)//分支陳述句
{
case 1:
game();
break;
case 0:
printf("Logon out the game\n");
break;
default:
printf("Input error,please input again\n");
break;
}
}
void menu(void)
{
printf("Welcome to game\n");
printf("\n");
printf("****************\n");
printf("*----1.play----*\n");
printf("*----0.exit----*\n");
printf("****************\n");
}
int main(void)
{
int input;
srand((unsigned int)time(NULL));
do
{
menu();//列印游戲選單
printf("please input option(1/0):>");
scanf("%d", &input);
option(input);//選項判斷
} while (input);
}
game.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include "game.h"
//void game(void)
//{
// char board[ROW][COL];//創建二維陣列
// setboard(board, ROW, COL);//制作棋盤
// player(board);//玩家開始下棋
//
// computer(board);//電腦開始下棋
//
//}
void setboard(char board[ROW][COL], int row, int col)//制作第一個棋盤
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
showboard(board,ROW, COL);
}
void showboard(char board[ROW][COL], int row, int col)//列印棋盤
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col)
printf("|");
}
if (i < row)
printf("\n---|---|---|\n");
}
}
void player(char board[ROW][COL])//玩家下棋
{
int x, y;
while (1)
{
printf("please input the coordinate:>");
scanf("%d %d", &x, &y);//輸入要落子的坐標
if (x>=1&&x<=ROW&&y>=1&&y<=COL)//判斷該坐標處,是否未被輸入過
{
if (board[x - 1][y - 1] != ' ')
printf("Coordinates occupied,please input again\n");
else
{
board[x - 1][y - 1] = '*';
break;
}
}
else
printf("Coordinate is illegal,please input again\n");//被使用過,重新輸入
}
//printf("*******************\n");
printf("Player\n");
showboard(board, ROW, COL);//列印每次下棋后的棋盤
}
void computer(char board[ROW][COL])//電腦落子
{
while (1)
{
int x = rand() % ROW;
int y = rand() % COL;
if (board[x][y] == ' ')//判斷該坐標處,是否未被輸入過
{
board[x][y] = '#';
break;
}
}
printf("Computer\n");
//printf("*******************\n");
showboard(board, ROW, COL);//列印每次下棋后的棋盤
}
char ifdraw(char board[ROW][COL])
{
int i;
for (i = 0; i < ROW; i++)
{
int j;
for (j = 0; j < COL; j++)
{
if (board[i][j] == ' ')
return 'C';
}
}
return 'D';
}
char judgewinner(char board[ROW][COL])
{
int count;
//判斷一行贏
for (int i = 0; i < ROW; i++)
{
int j,count=0;
for (j = 0; j < COL-1; j++)
{
if (board[i][j] != board[i][j + 1])
break;
else if (board[i][j] == board[i][j + 1])
count++;
}
if (count == COL - 1)
{
if (board[i][j] == '*')
return '*';//玩家贏
else if (board[i][j] == '#')
return '#';//電腦贏
}
if ((count != COL - 1) && (i == ROW - 1))
return ifdraw(board);//平局
}
//判斷列贏
for (int i = 0; i < COL; i++)
{
int j, count = 0;
for (j = 0; j < ROW - 1; j++)
{
if (board[i][j] != board[i][j + 1])
break;
else if (board[i][j] == board[i][j + 1])
count++;
}
if (count == ROW - 1)
{
if (board[i][j] == '*')
return '*';//玩家贏
else if (board[i][j] == '#')
return '#';//電腦贏
}
if ((count != ROW - 1) && i == COL - 1)
return ifdraw(board);//平局
}
//判斷對角線\贏
count = 0;
int i = 0;
int j;
while ((count != COL - 1) && (i <ROW-1))
{
j = i;
if (board[i][j] == board[i + 1][j + 1])
count++;
else if (board[i][j] != board[i + 1][j + 1])
break;
i++;
if (count == ROW - 1)
{
if (board[i][j] == '*')
return '*';//玩家贏
else if (board[i][j] == '#')
return '#';//電腦贏
}
}
return ifdraw(board);//平局}
//對角線/
count=0;
i = ROW - 1;
while (i>0)
{
j=ROW-i-1;
if (board[i][j] == board[i - 1][j + 1])
count++;
else if (board[i][j] = board[i - 1][j + 1])
break;
i--;
if (count == COL - 1)
{
if (board[i][j] == '*')
return '*';//玩家贏
else if (board[i][j] == '#')
return '#';//電腦贏
}
}
return ifdraw(board);//平局
}
game.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
void game(void);//三子棋游戲
void setboard(char board[ROW][COL], int row, int col);//創建棋盤
void showboard(char board[ROW][COL], int row, int col);//列印、展示棋盤
void player(char board[ROW][COL]);//玩家落子
void computer(char board[ROW][COL]);//電腦落子
char judgewinner(char board[ROW][COL]);//判斷輸贏
char ifdraw(char board[ROW][COL]);//判斷是否平局
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/252218.html
標籤:其他
上一篇:如何用代碼寫一個三子棋游戲
下一篇:C語言編程>第二十周 ③ 請補充fun函式,該函式的功能是:把字串s中的字符按字符的ASCII碼升序排列,處理后的字串仍然保存在原串中,字串及其長度作為函式引數傳入。
