C語言三子棋游戲的簡單設(shè)計
本文實例為大家分享了C語言三子棋游戲簡單設(shè)計的具體代碼,供大家參考,具體內(nèi)容如下
題目思想:
用 3×3 的二維數(shù)組表示棋盤
每一個棋子的格子,也就是每個元素表示三種狀態(tài):分別是
1.未落子 ‘ '
2.玩家落子 ‘X'
3.電腦落子 ‘O'
玩家通過輸入數(shù)字作為落子位置的坐標(biāo)(輸入的行數(shù)與輸入的列數(shù))
直接上代碼解析
1.創(chuàng)建出棋盤
#define _CRT_SECURE_NO_WARNINGS //利用宏定義行和列 #define MAX_ROW 3 #define MAX_COL 3 #include <stdio.h> #include <stdlib.h> // 將初始化行和列的 '0' 變?yōu)榭崭?' ' void init(char board[MAX_ROW][MAX_COL]) { //行初始化,將數(shù)組 0-2輸出為' ' for(int row = 0; row < MAX_ROW; row++) { //列初始化 for (int col = 0; col < MAX_COL; col++) { board[row][col] = ' '; } } } // 打印棋盤,定義printBoard,以二維數(shù)組的方式進(jìn)行循環(huán)打印 void printBoard(char board[MAX_ROW][MAX_COL]) { for (int row = 0; row < MAX_ROW; row++) { for (int col = 0; col < MAX_COL; col++) { // 打印字符,使用 %c printf("%c", board[row][col]); } //每次打印完一行,進(jìn)行換行操作,變成3×3的數(shù)組形成的棋盤 printf("\n"); } } int main() { // 首先創(chuàng)建棋盤并初始化 // 這里不要用board[3][3],防止后面 3 與 3 搞混,可以利用宏定義 char board[MAX_ROW][MAX_COL] = { 0 }; // 使用 init 函數(shù) 初始化二維數(shù)組{0}應(yīng)當(dāng)變成空格 ' ' // 此處也可以將 init函數(shù)定義中的雙重 for 循環(huán)直接輸入 // 但將二維數(shù)組初始化為 ' ',表示了一個固定功能的邏輯,比較適合用函數(shù)定義的方法完成 init(board); // 使用while循環(huán),進(jìn)行輪流落子 while (1) { //1.先打印棋盤內(nèi)容 printBoard(board); //2.玩家落子 //3.電腦落子 //4.判定勝負(fù) } system("pause"); return 0; }
確實打印出來了,但是由于初始化將二維數(shù)組中的元素變?yōu)榱丝崭?‘ '
,所以輸出結(jié)果看不到。
2.修改棋盤,使之打印出的是 3×3 的帶有方格的棋盤
void printBoard(char board[MAX_ROW][MAX_COL]) { for (int row = 0; row < MAX_ROW; row++) { //在打印每一行之前加入橫線 printf("+--+--+--+\n"); for (int col = 0; col < MAX_COL; col++) { // 打印字符,使用 %c // 每打印一列,在打印之前加入| printf("| %c", board[row][col]); } //打印之后加入|,形成 3 列。 printf("|"); //每次打印完一行,進(jìn)行換行操作,變成3×3的數(shù)組形成的縱線棋盤 printf("\n"); }//打印完所有行之后在加入橫線,形成橫線棋盤 printf("+--+--+--+\n"); }
3.玩家落子
// 玩家落子 void playerMove(char board[MAX_ROW][MAX_COL]) { printf("輪到玩家落子!\n"); //加入while循環(huán),保證用戶輸入錯誤時返回重新輸入 while (1) { printf("請輸入落子位置的坐標(biāo)(row col):"); //添加屏幕輸入模塊,輸入行和列坐標(biāo) int row = 0; int col = 0; scanf("%d %d", &row, &col); //輸入完了之后,一定要驗證輸入的內(nèi)容,防止輸入例如(10,20)超過棋盤坐標(biāo) if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL) { printf("您輸入的坐標(biāo)有誤,請重新輸入!\n"); continue;//重新輸入,繼續(xù)循環(huán) } // 當(dāng)前位置不為 ' ' ,說明有子了,也需要重新輸入 if (board[row][col] != ' ') { printf("當(dāng)前位置有子,無法落子\n"); continue; } //玩家落子為 X ,結(jié)束當(dāng)前循環(huán) board[row][col] = 'X'; break; } }
4.電腦落子
// 電腦落子 void computerMove(char board[MAX_ROW][MAX_COL]) { printf("輪到電腦落子!\n"); while (1) { //電腦落子時,產(chǎn)生隨機(jī)位置,用到隨機(jī)數(shù)種子,使隨機(jī)數(shù)范圍在棋盤坐標(biāo)以內(nèi) int row = rand() % MAX_ROW; int col = rand() % MAX_COL; if (board[row][col] != ' '){ // 如果行列不是空格,說明有子了,就隨機(jī)生成隨機(jī)數(shù) continue; } board[row][col] = 'O'; break; } }
這里使用了清屏操作,讓每次輸入完后進(jìn)行一次清屏,具體代碼在總體代碼里附上
5.判定勝負(fù)
//判斷和棋的函數(shù) int isFull(char board[MAX_ROW][MAX_COL]) { //如果在棋盤中找不到 ' ' ,就說明棋盤滿了,只要找到 ' ' 說明沒滿 //約定滿了返回1,沒滿返回0 for (int row = 0; row < MAX_ROW; row++) { for (int col = 0; col < MAX_COL; col++) { if (board[row][col] == ' ') { //沒滿 return 0; } } }return 1; } // 判定勝負(fù),由于要返回勝負(fù),使用char定義 // 如果是玩家贏返回 X ,電腦贏返回 O,平局返回 P,勝負(fù)未分返回 ' ' char checkwinner(char board[MAX_ROW][MAX_COL]) { //1.檢測所有行 for (int row = 0; row < MAX_ROW; row++) { if (board[row][0] != ' ' && board[row][0] == board[row][1] && board[row][0] == board[row][2]) { return board[row][0]; } } //2.檢測所有列 for (int col = 0; col < MAX_ROW; col++) { if (board[0][col] != ' ' && board[0][col] == board[1][col] && board[0][col] == board[2][col]) { return board[0][col]; } } //3.檢測所有對角線 if (board[0][0] != ' ' && board[0][0] == board[1][1] && board[0][0] == board[2][2]) { return board[0][0]; } if (board[2][0] != ' ' && board[2][0] == board[1][1] && board[0][0] == board[0][2]) { return board[2][0]; } // 判定和棋 if (isFull(board)) { return 'p'; }return ' '; }
這個結(jié)果中很多人肯定看到了問題,玩家贏的同時還在顯示電腦落子,怎么改?
6.注意還有一個問題:
如圖,在主函數(shù)中先進(jìn)行玩家落子,后進(jìn)行電腦落子,在電腦落子之前玩家就贏了。修改程序如下:
int main() { // 首先創(chuàng)建棋盤并初始化 // 這里不要用board[3][3],防止后面 3 與 3 搞混,可以利用宏定義 char board[MAX_ROW][MAX_COL] = { 0 }; // 使用 init 函數(shù) 初始化二維數(shù)組{0}應(yīng)當(dāng)變成空格 ' ' // 此處也可以將 init函數(shù)定義中的雙重 for 循環(huán)直接輸入 // 但將二維數(shù)組初始化為 ' ',表示了一個固定功能的邏輯,比較適合用函數(shù)定義的方法完成 init(board); char winner = ' '; // 使用while循環(huán),進(jìn)行輪流落子 while (1) { //1.先打印棋盤內(nèi)容 printBoard(board); //2.玩家落子 playerMove(board); winner = checkwinner(board); if (winner != ' ') { //勝負(fù)已分,結(jié)束循環(huán) break; } //3.電腦落子 computerMove(board); //4.判定勝負(fù) winner = checkwinner(board); if (winner != ' ') { //勝負(fù)已分,結(jié)束循環(huán) break; } } if (winner = 'X') { printf("恭喜你,獲勝了!\n"); } else if (winner = 'O') { printf("很遺憾,你有點菜呀!\n"); } else { printf("你和電腦五五開!\n"); } system("pause"); return 0; }
全部函數(shù)
#define _CRT_SECURE_NO_WARNINGS //利用宏定義行和列 #define MAX_ROW 3 #define MAX_COL 3 #include <stdio.h> #include <stdlib.h> #include <time.h> // 將初始化行和列的 '0' 變?yōu)榭崭?' ' void init(char board[MAX_ROW][MAX_COL]) { //行初始化,將數(shù)組 0-2輸出為' ' for(int row = 0; row < MAX_ROW; row++) { //列初始化 for (int col = 0; col < MAX_COL; col++) { board[row][col] = ' '; } } //設(shè)置隨機(jī)數(shù)種子,為電腦落子 //只要程序啟動時,設(shè)置一次即可 srand((unsigned int)time(0)); } // 打印棋盤,定義printBoard,以二維數(shù)組的方式進(jìn)行循環(huán)打印 void printBoard(char board[MAX_ROW][MAX_COL]) { //每次打印之前先清屏 system("cls"); for (int row = 0; row < MAX_ROW; row++) { //在打印每一行之前加入橫線 printf("+--+--+--+\n"); for (int col = 0; col < MAX_COL; col++) { // 打印字符,使用 %c // 每打印一列,在打印之前加入| printf("| %c", board[row][col]); } //打印之后加入|,形成 3 列。 printf("|"); //每次打印完一行,進(jìn)行換行操作,變成3×3的數(shù)組形成的縱線棋盤 printf("\n"); }//打印完所有行之后在加入橫線,形成橫線棋盤 printf("+--+--+--+\n"); } // 玩家落子 void playerMove(char board[MAX_ROW][MAX_COL]) { printf("輪到玩家落子!\n"); //加入while循環(huán),保證用戶輸入錯誤時返回重新輸入 while (1) { printf("請輸入落子位置的坐標(biāo)(row col):"); //添加屏幕輸入模塊,輸入行和列坐標(biāo) int row = 0; int col = 0; scanf("%d %d", &row, &col); //輸入完了之后,一定要驗證輸入的內(nèi)容,防止輸入例如(10,20)超過棋盤坐標(biāo) if (row < 0 || row >= MAX_ROW || col < 0 || col >= MAX_COL) { printf("您輸入的坐標(biāo)有誤,請重新輸入!\n"); continue;//重新輸入,繼續(xù)循環(huán) } // 當(dāng)前位置不為 ' ' ,說明有子了,也需要重新輸入 if (board[row][col] != ' ') { printf("當(dāng)前位置有子,無法落子\n"); continue; } //玩家落子為 X ,結(jié)束當(dāng)前循環(huán) board[row][col] = 'X'; break; } } // 電腦落子 void computerMove(char board[MAX_ROW][MAX_COL]) { printf("輪到電腦落子!\n"); while (1) { //電腦落子時,產(chǎn)生隨機(jī)位置,用到隨機(jī)數(shù)種子,使隨機(jī)數(shù)范圍在棋盤坐標(biāo)以內(nèi) int row = rand() % MAX_ROW; int col = rand() % MAX_COL; if (board[row][col] != ' '){ // 如果行列不是空格,說明有子了,就隨機(jī)生成隨機(jī)數(shù) continue; } board[row][col] = 'O'; break; } } //判斷和棋的函數(shù) int isFull(char board[MAX_ROW][MAX_COL]) { //如果在棋盤中找不到 ' ' ,就說明棋盤滿了,只要找到 ' ' 說明沒滿 //約定滿了返回1,沒滿返回0 for (int row = 0; row < MAX_ROW; row++) { for (int col = 0; col < MAX_COL; col++) { if (board[row][col] == ' ') { //沒滿 return 0; } } }return 1; } // 判定勝負(fù),由于要返回勝負(fù),使用char定義 // 如果是玩家贏返回 X ,電腦贏返回 O,平局返回 P,勝負(fù)未分返回 ' ' char checkwinner(char board[MAX_ROW][MAX_COL]) { //1.檢測所有行 for (int row = 0; row < MAX_ROW; row++) { if (board[row][0] != ' ' && board[row][0] == board[row][1] && board[row][0] == board[row][2]) { return board[row][0]; } } //2.檢測所有列 for (int col = 0; col < MAX_ROW; col++) { if (board[0][col] != ' ' && board[0][col] == board[1][col] && board[0][col] == board[2][col]) { return board[0][col]; } } //3.檢測所有對角線 if (board[0][0] != ' ' && board[0][0] == board[1][1] && board[0][0] == board[2][2]) { return board[0][0]; } if (board[2][0] != ' ' && board[2][0] == board[1][1] && board[0][0] == board[0][2]) { return board[2][0]; } // 判定和棋 if (isFull(board)) { return 'p'; }return ' '; } int main() { // 首先創(chuàng)建棋盤并初始化 // 這里不要用board[3][3],防止后面 3 與 3 搞混,可以利用宏定義 char board[MAX_ROW][MAX_COL] = { 0 }; // 使用 init 函數(shù) 初始化二維數(shù)組{0}應(yīng)當(dāng)變成空格 ' ' // 此處也可以將 init函數(shù)定義中的雙重 for 循環(huán)直接輸入 // 但將二維數(shù)組初始化為 ' ',表示了一個固定功能的邏輯,比較適合用函數(shù)定義的方法完成 init(board); char winner = ' '; // 使用while循環(huán),進(jìn)行輪流落子 while (1) { //1.先打印棋盤內(nèi)容 printBoard(board); //2.玩家落子 playerMove(board); winner = checkwinner(board); if (winner != ' ') { //勝負(fù)已分,結(jié)束循環(huán) break; } //3.電腦落子 computerMove(board); //4.判定勝負(fù) winner = checkwinner(board); if (winner != ' ') { //勝負(fù)已分,結(jié)束循環(huán) break; } } if (winner = 'X') { printf("恭喜你,獲勝了!\n"); } else if (winner = 'O') { printf("很遺憾,你有點菜呀!\n"); } else { printf("你和電腦五五開!\n"); } system("pause"); return 0; }
結(jié)果如下
我們的三子棋棋盤小游戲就算結(jié)束啦!
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言中用于產(chǎn)生隨機(jī)數(shù)的函數(shù)使用方法總結(jié)
這篇文章主要介紹了C語言中用于產(chǎn)生隨機(jī)數(shù)的函數(shù)使用方法總結(jié),分別介紹了rand()函數(shù)和srand()函數(shù)以及封裝出的arc4random()函數(shù),需要的朋友可以參考下2016-05-05C語言數(shù)據(jù)結(jié)構(gòu)二叉樹之堆的實現(xiàn)和堆排序詳解
堆是計算機(jī)科學(xué)中一類特殊的數(shù)據(jù)結(jié)構(gòu)的統(tǒng)稱,通常是一個可以被看做一棵完全二叉樹的數(shù)組對象。而堆排序是利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計的一種排序算法。本文將詳細(xì)介紹堆的實現(xiàn)和堆排序,需要的可以參考一下2022-04-04詳解C++中賦值,關(guān)系,函數(shù)調(diào)用運(yùn)算符重載的實現(xiàn)
本文主要為大家講解一下三個C++中的運(yùn)算符重載,分別是賦值運(yùn)算符重載、關(guān)系運(yùn)算符重載和函數(shù)調(diào)用運(yùn)算符重載,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-06-06C語言創(chuàng)建鏈表錯誤之通過指針參數(shù)申請動態(tài)內(nèi)存實例分析
這篇文章主要介紹了C語言創(chuàng)建鏈表錯誤之通過指針參數(shù)申請動態(tài)內(nèi)存,是鏈表創(chuàng)建過程中非常常見的經(jīng)典錯誤。實例中做了較為詳盡的分析,需要的朋友可以參考下2014-09-09