C++實(shí)現(xiàn)和電腦對(duì)戰(zhàn)三子棋實(shí)例
前言
前兩天在??途W(wǎng)寫了一道題,關(guān)于KiKi和BoBo玩 “井”字棋,請(qǐng)根據(jù)棋盤狀態(tài),判斷當(dāng)前輸贏。也就是說系統(tǒng)給你一個(gè)已經(jīng)下好的棋,讓你來判斷誰輸誰贏還是平局。寫完這道題也不禁讓我有點(diǎn)想法,能不能寫一個(gè)代碼來實(shí)現(xiàn)我和電腦對(duì)峙三子棋,邊下棋系統(tǒng)邊判斷是否輸贏或者平局,否則繼續(xù)下棋。經(jīng)過一天查閱資料,觀看視頻,自己實(shí)踐,終于實(shí)現(xiàn)了我當(dāng)初的想法,現(xiàn)在來分享給大家我自己的思路。
一.準(zhǔn)備需要的函數(shù)
1.棋盤
①構(gòu)建
三子棋的棋盤肯定是必不可少,我們可以利用void函數(shù)來實(shí)現(xiàn)一個(gè)空的棋盤,讓他為九宮格然后每一個(gè)格子都是空
void intiboard(char arr[ROW][COL], int row, int col)//初始化棋盤 { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { arr[i][j] = ' '; } } }
②美化棋盤
棋盤肯定得有棋盤的樣子,我們得美化一下鍵盤,我的思路是在橫列上先打印'|'然后打印字符,在豎列上直接打印|---,然后循環(huán)。
void displayboard(char arr[ROW][COL], int row, int col)//打印棋盤 { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { printf("|"); printf(" %c ", arr[i][j]); } printf("\n"); { for (int k = 0; k < col; k++) { printf("|---"); } printf("\n"); } } }
最后實(shí)現(xiàn)是這樣的。
2.各自下棋
①玩家下棋
玩家這部分我們需要自己輸入橫豎坐標(biāo),但是實(shí)際上數(shù)組的是從0開始的,因此我們輸入的時(shí)候應(yīng)該給玩家輸入的實(shí)際坐標(biāo)減一,假如玩家輸出超出范圍或者輸入的值被電腦搶先輸入程序會(huì)反饋重新輸入,這邊使用while循環(huán)也成功實(shí)現(xiàn)了這一點(diǎn),直到找到break才可以跳出這個(gè)循環(huán)。
void playermove(char arr[][COL], int row, int col)//玩家回合 { int x = 0; int y = 0; printf("玩家回合\n"); while (1)//一直循環(huán)直到break { printf("請(qǐng)輸入你想要下的坐標(biāo)\n"); scanf_s("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col)//輸入合法 { if (arr[x-1][y-1] == ' ') { arr[x-1][y-1] = 'X'; break; } else printf("棋盤重復(fù),重新輸入\n"); } else printf("超出范圍,請(qǐng)重新輸入!\n"); } }
②電腦下棋
電腦這邊有一個(gè)難點(diǎn)就在于如何讓電腦隨機(jī)輸入數(shù)值,我是利用rand()來實(shí)現(xiàn)關(guān)于隨機(jī)的范圍我選擇了除余來解決,讓電腦輸入有了隨機(jī)性,同時(shí)也利用了while函數(shù),只有輸入了正確的位置才會(huì)跳出循環(huán)
void AImove(char arr[][COL], int row, int col)//電腦回合 { printf("AI回合\n"); while (1) { int x = rand() % row; int y = rand() % col; if (arr[x][y] == ' ') { arr[x][y] = 'O'; break; } } }
3.輸贏判斷
關(guān)于輸贏我選擇利用帶有返回值的函數(shù),方便日后判斷。關(guān)于井字棋我們只要行、列,或者任意對(duì)角線上面出現(xiàn)三個(gè)連續(xù)相同的棋子,就能獲勝。因此我們可以用if語句來判斷是否滿足以上任一條件如果滿足則返回對(duì)于數(shù)值的字符,關(guān)于平局時(shí)在沒有決出勝負(fù)的情況下棋盤下滿,因此我們需要構(gòu)建函數(shù)來判斷棋盤是否滿,不是則繼續(xù),是則暫停返回值。
int Full(char arr[][COL], int row, int col) { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { if (arr[i][j] == ' ') return 0;//返回0說明棋盤沒有滿 } } return 1;//棋盤滿了,平局 } char Winner(char arr[][COL], int row, int col)//判斷輸贏 { for (int i = 0; i < row; i++) { if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][0] != ' ') { return arr[i][0]; } else if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[0][i] != ' ') { return arr[0][i]; } if (arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[0][0] != ' ') { return arr[0][0]; } if (arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[1][1] != ' ') { return arr[1][1]; } } int x = Full; if (x == 0) { return 'Q'; } else return 'C'; }
因此我們準(zhǔn)備的函數(shù)就準(zhǔn)備完畢了。
二.游戲?qū)崿F(xiàn)
1.菜單的實(shí)現(xiàn)
對(duì)于菜單沒有什么說的直接就簡單粗暴的打印就好
void menu() { printf("---------------------------------------\n"); printf("============1.開始 2.結(jié)束=============\n"); printf("+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=\n"); printf("----------------------------------------\n"); }//游戲的主頁面;
然后菜單選項(xiàng)的實(shí)現(xiàn)我利用了do while函數(shù)來實(shí)現(xiàn),用while來判斷輸入值的真假,假如是真的判斷是否是一,要是一就開始游戲,否則提示輸入超綱,重新循環(huán),如果輸入是零的話,while語句為假跳出循環(huán),也就是結(jié)束游戲。
void test()//前端游戲頁面和選擇 { int input = 0; srand((unsigned int)time(NULL));//后面rand的使用 do { menu();//調(diào)用菜單的打印 printf("請(qǐng)輸入你的選擇(1/0):\n"); scanf_s("%d", &input); if (input == 1) { printf("三子棋游戲開始!\n"); play(); } else if (input == 0) { printf("結(jié)束游戲,感謝游玩\n"); } else printf("請(qǐng)你重新選擇qaq\n"); } while (input);//假如input=0也就是input為假的時(shí)候結(jié)束循環(huán): }
2.游戲本體的構(gòu)建
關(guān)于游戲的邏輯,首先我們得構(gòu)建一個(gè)數(shù)組來實(shí)現(xiàn)因此構(gòu)建一個(gè)數(shù)組是必不可少的,然后利用函數(shù)對(duì)數(shù)組重置并且美化,然后實(shí)現(xiàn)玩家互相下棋然后顯示棋盤,判斷是否輸贏或者平局,這里我們繼續(xù)用了while循環(huán)來實(shí)現(xiàn)只有有了結(jié)果我們才會(huì)跳出循環(huán)
void play() { char board[ROW][COL]; char ret = 0; intiboard(board, ROW, COL); displayboard(board, ROW, COL); while (1) { playermove(board, ROW, COL); displayboard(board, ROW, COL); ret=Winner(board, ROW, COL); if (ret != 'C')//棋盤滿了,或者決出勝負(fù)了! { break; } AImove(board, ROW, COL); displayboard(board, ROW, COL); ret = Winner(board, ROW, COL); if (ret != 'C')//棋盤滿了,或者決出勝負(fù)了! { break; } } if (ret == 'X') { printf("玩家獲勝!\n"); } else if (ret == 'O') { printf("電腦獲勝!\n"); } else if(ret=='Q') printf("平局.\n"); }
就這樣一個(gè)游戲就成功完成!
總結(jié)
這個(gè)游戲其實(shí)過于簡單,因?yàn)槿悠迮袛噍斱A比較簡單,也不麻煩,重點(diǎn)在于需要判斷每一步是否輸贏或者平局和對(duì)于while的理解,何時(shí)跳出循環(huán),何時(shí)繼續(xù)循環(huán),而且要細(xì)心,就比如我在寫的時(shí)候好多次把自己定義函數(shù)名字打錯(cuò)導(dǎo)致編譯器錯(cuò)誤找了好久才發(fā)現(xiàn),還是得細(xì)心才行。
關(guān)于這個(gè)代碼源碼頭文件什么的我都上傳到gitee上去了如果感興趣可以去看看
CSDN writings/三子棋 · banbanni/banni - 碼云 - 開源中國 (gitee.com)
到此這篇關(guān)于C++實(shí)現(xiàn)和電腦對(duì)戰(zhàn)三子棋實(shí)例的文章就介紹到這了,更多相關(guān)C++三子棋內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++實(shí)現(xiàn)掃雷小游戲(控制臺(tái)版)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)控制臺(tái)版的掃雷小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03C語言數(shù)據(jù)結(jié)構(gòu)之圖的遍歷實(shí)例詳解
這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)之圖的遍歷實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-07-07C++類重載函數(shù)的function和bind使用示例
這篇文章主要介紹了C++類重載函數(shù)的function和bind使用示例,幫助大家更好的理解和使用c++,感興趣的朋友可以了解下2021-01-01C++ 遞歸遍歷文件并計(jì)算MD5的實(shí)例代碼
在本篇文章里小編給大家整理的是一篇關(guān)于C++ 遞歸遍歷文件并計(jì)算MD5的實(shí)例代碼,有興趣的朋友們可以學(xué)習(xí)參考下。2021-07-07C語言實(shí)現(xiàn)大整數(shù)加減運(yùn)算詳解
大數(shù)運(yùn)算,顧名思義,就是很大的數(shù)值的數(shù)進(jìn)行一系列的運(yùn)算。本文通過實(shí)例演示如何進(jìn)行C語言中的大整數(shù)加減運(yùn)算,有需要的可以參考借鑒。2016-08-08