实现三子棋游戏详细教学
三子棋游戲目錄
- 三子棋游戲
- 游戲選擇
- 初始化棋盤
- 棋盤打印
- 玩家下棋
- 電腦下棋
- 判定輸贏
- 完整代碼呈現
- 結尾
三子棋游戲
整個游戲分為游戲選擇、初始化棋盤、棋盤打印、玩家下棋、電腦下棋、判定輸贏共六個部分
在文章末尾會有代碼的完整呈現
游戲選擇
首先是游戲選擇部分,你可以在此選擇是否開始游戲
且每當結束一把對局,也會回到該界面,再次進行選擇
具體代碼實現:
void menu() {printf("*********************\n");printf("******* 1.play ******\n");printf("******* 0.exit ******\n");printf("*********************\n"); }int main() {int input = 0;srand((unsigned int)time(NULL));do{menu();printf("請輸入:");scanf("%d", &input);switch (input){case 0:printf("退出游戲\n");break;case 1:printf("開始游戲\n");game();break;default:printf("輸入錯誤,請重新輸入\n");break;}} while (input);return 0; }這里我們用do…while語句配合switch…case語句,實現游戲選擇的基本功能
如果對方輸入“1”,那么我們將開始游戲,但在此之前會初始化棋盤、并將其打印的
初始化棋盤
我們知道三子棋的棋盤是3×3大小的,那么我們就可以將這個棋盤看成一個三行三列的二維數組,那給這個數組初始化成什么就是一個問題了
我們先將這個二維數組初始化成’\0’,來看看打印的效果
代碼實現:
#define ROW 3 #define COL 3void init_board(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] = '\0';}} }打印結果展示:
我們會發現,打印的棋盤發生了錯位。這是因為’\0’是不會被打印出來的,所以為了棋盤的美觀,我們將數組全部初始化為’ '(單引號內為空格)
這是初始化為空格后打印出來的效果:
打印結果展示:
這樣打印出來的棋盤就十分美觀了
棋盤打印
在介紹了如何初始化棋盤后,我們再來介紹棋盤的打印
其實棋盤的打印這里沒有什么需要注意的點,無非就是為了棋盤的美觀而花些心思
代碼實現:
void display(char board[ROW][COL], int row, int col) {int i = 0;for (i = 0; i < row; i++){int j = 0;//先打印數組元素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 player(char board[ROW][COL], int row, int col) {printf("玩家下棋\n請輸入坐標:");int x = 0;int y = 0;while (1){scanf("%d %d", &x, &y);if (board[x - 1][y - 1] == ' '){board[x - 1][y - 1] = '*';break;}else{printf("此處不能下,請重新輸入坐標:");}} }這里我們將while的判斷語句設為恒成立,如果下的棋不符合要求將一直重新下,直至下到符合要求
這里對于玩家來說可能不清楚二維數組的下標,所以為了符合大部分人對于行數和列數的認知,玩家在輸入坐標時,第一行第一列就輸入“1 1”
當然在完成玩家下棋后,我們也需將棋盤進行打印
電腦下棋
在完成玩家下棋后,就輪到電腦下棋了
這里我們只要實現讓電腦隨機下到空著的位置即可,隨機也就說明了需要用到rand和srand,注意包含頭文件
我們提前在main函數中初始化一個隨機數發生器srand((unsigned int)time(NULL));,便于生成隨機數
代碼實現:
void computer(char board[ROW][COL], int row, int col) {printf("電腦下棋\n");while (1){int x = rand() % row;int y = rand() % col;if (board[x][y] == ' '){board[x][y] = '#';break;}} }電腦下的棋我們用’#'表示
這里的int x = rand() % row和int y = rand() % col是使x、y的范圍限制在0~2,防止超出棋盤大小
當然,電腦完成下棋后,也需要打印棋盤
判定輸贏
我們提前規定:
- 如果玩家贏返回’*’
- 如果電腦贏返回’#’
- 如果平局返回’Q’
- 上述三種情況都不是,則繼續游戲,返回’C’
為什么返回’*‘和’#',而不返回其他字符呢?
我們先來想一下贏的方式:一行三個,或一列三個,或斜著三個
那在判定輸贏時,是不是就是要判定上述三個坐標的棋子是不是都是’*‘或’#'呢?
但贏的情況共有四種,每種情況下又要寫兩種不同的字符對象進行判定,這是不是有些太繁瑣了呢?
我們想一下,贏的方式對于玩家或電腦來說都是一樣的,但是判定誰贏涉及的代碼是不一樣的,那我們不如將判定誰贏給抽離出來,不再函數內部判定,而是通過返回值,通過外部進行判定
代碼實現:
//關于平局的判斷 //判斷棋盤是否滿了,滿了返回1,沒滿返回0 int is_full(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 judge(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[1][j] == board[2][j] && board[0][j] != ' ')return board[0][j];}//這是兩個斜著的贏法if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')return board[0][0];if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != ' ')return board[2][0];//判斷平局if (is_full(board, row, col) == 1)return 'Q';//如果上面都沒有執行return,那么說明都沒有贏也沒有平局呢,那游戲繼續return 'C'; } void game() {char board[ROW][COL] = { 0 };init_board(board, ROW, COL);display(board,ROW,COL);char ret = ' ';while (1){player(board, ROW, COL);display(board, ROW, COL);ret = judge(board, ROW, COL);if (ret != 'C')break;computer(board, ROW, COL);display(board, ROW, COL);ret = judge(board, ROW, COL);if (ret != 'C')break;}if (ret == '*')printf("玩家獲勝\n");if (ret == '#')printf("電腦獲勝\n");if (ret == 'Q')printf("游戲平局\n");display(board, ROW, COL);}通過這種方式即完成了輸贏的判定,也不會使代碼冗余
完整代碼呈現
我寫這個游戲時是多文件工程,所以我也就分文件給大家呈現了
main.c
#include "game.h" //打印游戲菜單 void menu() {printf("*********************\n");printf("******* 1.play ******\n");printf("******* 0.exit ******\n");printf("*********************\n"); }//運行游戲 void game() {char board[ROW][COL] = { 0 };init_board(board, ROW, COL);display(board,ROW,COL);char ret = ' ';while (1){player(board, ROW, COL);display(board, ROW, COL);ret = judge(board, ROW, COL);if (ret != 'C')break;computer(board, ROW, COL);display(board, ROW, COL);ret = judge(board, ROW, COL);if (ret != 'C')break;}if (ret == '*')printf("玩家獲勝\n");if (ret == '#')printf("電腦獲勝\n");if (ret == 'Q')printf("游戲平局\n");display(board, ROW, COL);}int main() {int input = 0;srand((unsigned int)time(NULL));do{menu();printf("請輸入:");scanf("%d", &input);switch (input){case 0:printf("退出游戲\n");break;case 1:printf("開始游戲\n");game();break;default:printf("輸入錯誤,請重新輸入\n");break;}} while (input);return 0; }game.h
#include<stdio.h> //這兩個頭文件是為了產生隨機數而調用的 #include<stdlib.h> #include<time.h>#define ROW 3 #define COL 3//初始化數組 void init_board(char board[ROW][COL], int row, int col);//打印棋盤 void display(char board[ROW][COL], int row, int col);//玩家下棋 void player(char board[ROW][COL], int row, int col);//電腦下棋 void computer(char board[ROW][COL], int row, int col);//判斷輸贏 char judge(char board[ROW][COL], int row, int col);game.c
#include "game.h" //數組初始化 //這是當數組創建時初始化為全0后,發現棋盤打印效果不理想,從而需要再次初始化數組 void init_board(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 display(char board[ROW][COL], int row, int col) {int i = 0;for (i = 0; i < row; i++){int j = 0;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");} }//玩家下棋,其棋子為* //要求:1.不能下到棋盤以外的坐標 // 2.不能下到已經下過的坐標 void player(char board[ROW][COL], int row, int col) {printf("玩家下棋\n請輸入坐標:");int x = 0;int y = 0;while (1){scanf("%d %d", &x, &y);if (board[x - 1][y - 1] == ' '){board[x - 1][y - 1] = '*';break;}else{printf("此處不能下,請重新輸入坐標:");}}}//電腦下棋,其棋子為# //這里我們只要實現讓電腦隨機下到空著的位置即可 void computer(char board[ROW][COL], int row, int col) {printf("電腦下棋\n");while (1){int x = rand() % row;int y = rand() % col;if (board[x][y] == ' '){board[x][y] = '#';break;}} }//判斷棋盤是否滿了,滿了返回1,沒滿返回0 int is_full(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; }//判斷輸贏 //如果玩家贏返回'*' //如果電腦贏返回'#' //如果平局返回'Q'// 上述三種情況都不是,則繼續游戲返回'C' //贏的方式:一行三個,或一列三個,或斜著三個 //這里我們不需要提前判斷三個相同的是*還是#,我們直接將這里其中一個元素返回,到主文件的game函數中判斷 char judge(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[1][j] == board[2][j] && board[0][j] != ' ')return board[0][j];}//這是兩個斜著的贏法if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')return board[0][0];if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != ' ')return board[2][0];//判斷平局if (is_full(board, row, col) == 1)return 'Q';//如果上面都沒有執行return,那么說明都沒有贏也沒有平局呢,那游戲繼續return 'C'; }結尾
到這里,整個三子棋游戲就完整的實現了
若有寫的不對、不好、不嚴謹的地方歡迎各位指正
感謝各位的閱讀觀看,謝謝大家!
總結
以上是生活随笔為你收集整理的实现三子棋游戏详细教学的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 飞行常用英语词汇
- 下一篇: 如何运用绩效考评结果?