<C语言>代码实现与自己创造的“人工智障”进行三子棋对弈,并且艰难的让电脑赢!
目錄
文章目錄
前言
一、創建文件項目
二、具體實現步驟
1.呈現菜單,并實現玩家可一直游玩游戲
2.選擇進入游戲后,打印棋盤
?2.1初始化棋盤
?2.2打印棋盤
3.打印棋盤后,玩家和電腦開始輪番下棋
3.1 實現玩家下棋,棋子為 *
3.2 電腦下棋,棋子為 #
4.判斷輸贏
5.整理代碼
總結
前言
????????注意看,這個男人叫小帥,現在,他正在敲代碼實現和機器人下三子棋,終于小帥敲好了代碼,他當即與機器人下了一局,然而小帥發現,這機器人竟然是......
一、創建文件項目
? ? ? ? 時間回到小帥寫代碼時的第一步,小帥首先創建項目以text.c為核心源文件,通過調用game.c和game.h內的函數實現三子棋的所有功能。
二、三子棋具體實現步驟
1.呈現菜單,并實現玩家可一直玩游戲
小帥竟然想設置沒有登出建的游戲,由于沒有防沉迷不符合國家規范,那晚,他連夜扛著火車跑路了!
1:代表進入游戲
0:代表退出游戲
? ? ? ? 菜單函數的代碼如下(示例):
//text.c源文件 #include<stdio.h> void menu()//定義菜單函數 {printf("*****************************\n");printf("************1.play***********\n");printf("************0.exit***********\n");printf("*****************************\n"); } void test() {int input = 0;do//該循環實現玩家可以一直游玩三子棋{menu();//調用菜單函數printf("請選擇:>");scanf("%d", &input);//請玩家選擇進入游戲or退出游戲switch (input) //采用switch語句較為便捷{case 1:printf("三子棋\n");break;case 0:printf("退出游戲\n");break;default:printf("選擇錯誤,請重新選擇:\n");break;}} while (input);//0為假,非0為真,即進入游戲輸入1,1作為判斷條件為真,游戲繼續 } int main() {test();return 0; }? ? ? ? 效果:?
2.選擇進入游戲后,打印棋盤
小帥的目標:打印九宮格簡易棋盤,并且能夠在每個指定格子內存放棋子(即數據)
?2.1初始化棋盤
? ? ? ? 小帥的“頭腦風暴”1:?要在九宮格內存放棋子還要打印在屏幕上,我應該用3*3大小的二維數組?,將每個數組元素發在九宮格的每個格子中間,但是呢,要注意,如果我只將棋盤的形狀打印屏幕上,后續玩家在指定下棋時棋子是不能覆蓋原先屏幕上的符號的,所以我在打印棋盤時就應該保留各個棋子應存放的空間,并存放空格來等待玩家或電腦下的棋子。emm,就是這樣!
????????為了使后續棋盤大小不局限于 3行3列 大小,小帥宏定義ROW 、?COL,如果后續想要改動棋盤大小僅需改變宏定義的ROW 、COL大小即可。宏定義名稱與值時替換關系。
? ? ? ?加上初始化函數的代碼如下(示例):
//game.h頭文件 #define ROW 3 #define COL 3 #include<stdio.h> void InitBoard(char board[ROW][COL], int row, int col); //game.c源文件 #define _CRT_SECURE_NO_WARNINGS #include "game.h"//調用自定義頭文件 void InitBoard(char board[ROW][COL], int row, int col)//定義初始化棋盤函數 {int i = 0, j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){board[i][j] = ' ';}} } //text.c源文件 #include "game.h"//調用自定義的頭文件void game()//定義game函數 {//初始化棋盤,用函數實現//傳入數組、行數、列數,以便初始化InitBoard(board, ROW, COL);//數組內全部空格 } void test() {do{menu();printf("請選擇:>");scanf("%d", &input);switch (input){case 1:printf("三子棋\n");game();//游戲的實現!break;case 0:printf("退出游戲\n");break;default:printf("選擇錯誤,請重新選擇:\n");break;}} while (input); } int main() {test();return 0; }2.2打印棋盤
??????? 小帥發現
棋盤第一行為:
?????????????空格 %c 空格 | 空格 %c 空格 | 空格 %c 空格
找最小重復單元,發現為:空格 %c 空格 |,要注意的是第三個 | 不需要打印,用if判斷即可
第二行為:
????????????????- - - |?- - - | - - -
找最小重復單元,發現為:- - - |,同樣的,要注意的是第三個 | 不需要打印,用條件控制一下即可
并且最后一行無需打印:? - - - |?- - - | - - -
將以上推斷結果封裝為打印函數
? ? ? ? 加上打印函數的代碼如下(示例):
//game.h頭文件 #define ROW 3 #define COL 3 #include<stdio.h> void InitBoard(char board[ROW][COL], int row, int col); void DisplayBoard(char board[ROW][COL], int row, int col); //game.c源文件 #define _CRT_SECURE_NO_WARNINGS #include "game.h" void InitBoard(char board[ROW][COL], int row, int col)//定義//初始化棋盤函數 {int i = 0, j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){board[i][j] = ' ';}} } void DisplayBoard(char board[ROW][COL], int row, int col)//定義打印棋盤函數 {int i = 0;int j = 0;for (i = 0; i < row; i++){//1.打印一行數據for (j = 0; j < col; j++){printf(" %c ", board[i][j]);//空格 棋子 空格if (j < col - 1)printf("|");}printf("\n");//2.打印分割行if (i < row - 1){for (j = 0; j < col; j++){printf("---");if(j<col-1)printf("|");}printf("\n");}} } //text.c源文件 #include "game.h"//調用自定義的頭文件 void game()//定義game函數 {//初始化棋盤,用函數實現 并傳入數組、行數、列數,以便初始化InitBoard(board, ROW, COL);//數組內全部空格//打印棋盤DisplayBoard(board, ROW, COL); } void test() {int input = 0;srand((unsigned int)time(NULL));do{menu();printf("請選擇:>");scanf("%d", &input);switch (input){case 1:printf("三子棋\n");game();//游戲的實現!break;case 0:printf("退出游戲\n");break;default:printf("選擇錯誤,請重新選擇:\n");break;}} while (input); } int main() {test();return 0; }最后每當玩家或電腦下棋后都要更新打印一次棋盤?
3.打印棋盤后,玩家和電腦開始輪番下棋
3.1 實現玩家下棋,棋子為 *
小帥的“頭腦風暴”2:
下棋實質上是為二維數組賦值,而我們賦值時就有了諸多限制:
?
?無所謂,小帥會出手!
所以,我們要解決以上問題
? ? ? ? 玩家下棋函數的代碼如下(示例):
void PlayerMove(char board[ROW][COL], int row, int col) {int x = 0, y = 0;printf("玩家走:>\n");while (1){printf("請輸入要下的坐標:>");scanf("%d%d", &x, &y);//判斷xy坐標的合法性if (x >= 1 && x <= row && y >= 1 && y <= col){if (board[x - 1][y - 1] == ' '){board[x - 1][y - 1] = '*';break;}else{printf("該坐標被占用\n");}}else{printf("坐標非法,請重新輸入!\n");}} }將玩家下棋函數聲明、函數調用、函數定義分別放至game.h、test.c中的game()函數中、game.c中即可。這里為了避免篇幅過長將最后展現全部代碼。?
3.2 電腦下棋,棋子為 #
小帥讓電腦隨機下棋,使用srand(time(NULL)),將rand()%row賦值給電腦下棋的行數,將rand()%col賦值給電腦下棋的列數。
? ? ? ? 電腦下棋函數的代碼如下(示例):
void ComputerMove(char board[ROW][COL], int row, int col) {int x = 0, y = 0;printf("電腦走:>\n");while (1){x = rand() % row;y = rand() % col;if (board[x][y] == ' '){board[x][y] = '#';break;}} }?將電腦下棋函數聲明、函數調用、函數定義分別放至game.h、test.c中的game()函數中、game.c中即可,將srand(time(NULL))放至test.c的test()函數中。這里為了避免篇幅過長將最后展現全部代碼。?
4.判斷輸贏
小帥的頭腦風暴3:
定義判斷輸贏函數,在玩家和電腦每次下棋后都要判斷一次輸贏
玩家或電腦贏需要滿足三個棋子相同并且連成一條線,注意排除空格情況:
平局情況只需要判斷棋盤是否還剩有空格即可
? ? ? ?判斷輸贏函數代碼如下(示例):
//返回1表示棋盤滿了 //返回0表示棋盤沒滿 int IsFull(char board[ROW][COL], int row, int col) {int i = 0, j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){if (board[i][j] == ' ')return 0;}}return 1; }char Iswin(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 (i = 0; i < col; i++){if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' '){return board[0][i];}}//兩個對角線if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){return board[0][0];}if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' '){return board[1][1];}//判斷是否平局if (1 == IsFull(board, ROW, COL)){return 'Q';}elsereturn 'C'; }?將輸贏判斷函數聲明、函數調用、函數定義分別放至game.h、test.c中的game()函數中、game.c中即可。無所謂,小帥會繼續出手!
5.整理代碼
//game.h頭文件 #define ROW 3 #define COL 3 #include<stdio.h> #include<stdlib.h> #include<time.h> //聲明 void InitBoard(char board[ROW][COL], int row, int col); void DisplayBoard(char board[ROW][COL], int row, int col); void PlayerMove(char board[ROW][COL],int row,int col); void ComputerMove(char board[ROW][COL],int row,int col); //告訴我們四種狀態 //玩家贏--'* //電腦贏--'# //平局----'Q' //繼續----'C' char Iswin(char board[ROW][COL], int row, int col); //game.c源文件 #define _CRT_SECURE_NO_WARNINGS 1#include "game.h" void InitBoard(char board[ROW][COL], int row, int col) {int i = 0, j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){board[i][j] = ' ';}} } void DisplayBoard(char board[ROW][COL], int row, int col) {int i = 0;int j = 0;for (i = 0; i < row; i++){//1.打印一行數據for (j = 0; j < col; j++){printf(" %c ", board[i][j]);if (j < col - 1)printf("|");}printf("\n");//2.打印分割行if (i < row - 1){for (j = 0; j < col; j++){printf("---");if (j < col - 1)printf("|");}printf("\n");}} } void PlayerMove(char board[ROW][COL], int row, int col) {int x = 0, y = 0;printf("玩家走:>\n");while (1){printf("請輸入要下的坐標:>");scanf("%d%d", &x, &y);//判斷xy坐標的合法性if (x >= 1 && x <= row && y >= 1 && y <= col){if (board[x - 1][y - 1] == ' '){board[x - 1][y - 1] = '*';break;}else{printf("該坐標被占用\n");}}else{printf("坐標非法,請重新輸入!\n");}} } void ComputerMove(char board[ROW][COL], int row, int col) {int x = 0, y = 0;printf("電腦走:>\n");while (1){x = rand() % row;y = rand() % col;if (board[x][y] == ' '){board[x][y] = '#';break;}} } //返回1表示棋盤滿了 //返回0表示棋盤沒滿 int IsFull(char board[ROW][COL], int row, int col) {int i = 0, j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){if (board[i][j] == ' ')return 0;}}return 1; }char Iswin(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] == board[i][j+1] && board[i][j+1] == board[i][j+2] && board[i][j] != ' '){return board[i][j];}}}//豎三列for (i = 0; i < col; i++){for (j = 0; j < row; j++){if (board[j][i] == board[j+1][i] && board[j+1][i] == board[j+2][i] && board[j][i] != ' '){return board[j][i];}}}//兩個對角線if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){return board[0][0];}if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' '){return board[1][1];}//判斷是否平局if (1 == IsFull(board, ROW, COL)){return 'Q';}elsereturn 'C'; } //text.c源文件 #define _CRT_SECURE_NO_WARNINGS //測試三子棋游戲 #include "game.h" #include<stdio.h> void menu() {printf("*****************************\n");printf("************1.play***********\n");printf("************0.exit***********\n");printf("*****************************\n"); }//游戲的整個算法實現 void game() {char ret = 0;//數組-存放走出的棋盤信息char board[ROW][COL] = { ' ' };//數組內全部空格//初始化棋盤,用函數實現InitBoard(board, ROW, COL);//打印棋盤DisplayBoard(board, ROW, COL);//下棋while (1){//玩家下棋PlayerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//判斷玩家是否贏ret = Iswin(board, ROW, COL);if (ret != 'C'){break;}//電腦下棋ComputerMove(board, ROW, COL);DisplayBoard(board, ROW, COL);//判斷電腦是否贏ret = Iswin(board, ROW, COL);if (ret != 'C'){break;}}if (ret == '*'){printf("玩家贏\n");}else if (ret == '#'){printf("電腦贏\n");}else if (ret == 'Q'){printf("平局\n");} } void test() {int input = 0;srand((unsigned int)time(NULL));do{menu();printf("請選擇:>");scanf("%d", &input);switch (input){case 1:printf("三子棋\n");game();break;case 0:printf("退出游戲\n");break;default:printf("選擇錯誤,請重新選擇:\n");break;}} while (input); } int main() {test();return 0; }效果?
總結
????????小帥的代碼結束,發現自己實現的電腦竟然是個人工智障(給它機會它都不中用的那種),所以我們發現這里有諸多待優化的點,例如:
小帥把問題留給我們,這次...他騰不出手了
????????最后,如果小伙伴們有優化的方案,請在評論區留言(ps:抱大佬的腿),新手創作,實屬不易,如果滿意,還請給個免費的贊,三連也不是不可以(流口水幻想),嘿!那我們下期再見嘍,拜拜!
?
總結
以上是生活随笔為你收集整理的<C语言>代码实现与自己创造的“人工智障”进行三子棋对弈,并且艰难的让电脑赢!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 背单词-词根-上肢动作-破坏动作
- 下一篇: 58品牌公寓馆