C++實(shí)現(xiàn)和電腦對戰(zhàn)三子棋實(shí)例
前言
前兩天在牛客網(wǎng)寫了一道題,關(guān)于KiKi和BoBo玩 “井”字棋,請根據(jù)棋盤狀態(tài),判斷當(dāng)前輸贏。也就是說系統(tǒng)給你一個已經(jīng)下好的棋,讓你來判斷誰輸誰贏還是平局。寫完這道題也不禁讓我有點(diǎn)想法,能不能寫一個代碼來實(shí)現(xiàn)我和電腦對峙三子棋,邊下棋系統(tǒng)邊判斷是否輸贏或者平局,否則繼續(xù)下棋。經(jīng)過一天查閱資料,觀看視頻,自己實(shí)踐,終于實(shí)現(xiàn)了我當(dāng)初的想法,現(xiàn)在來分享給大家我自己的思路。
一.準(zhǔn)備需要的函數(shù)
1.棋盤
①構(gòu)建
三子棋的棋盤肯定是必不可少,我們可以利用void函數(shù)來實(shí)現(xiàn)一個空的棋盤,讓他為九宮格然后每一個格子都是空
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開始的,因此我們輸入的時候應(yīng)該給玩家輸入的實(shí)際坐標(biāo)減一,假如玩家輸出超出范圍或者輸入的值被電腦搶先輸入程序會反饋重新輸入,這邊使用while循環(huán)也成功實(shí)現(xiàn)了這一點(diǎn),直到找到break才可以跳出這個循環(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("請輸入你想要下的坐標(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("超出范圍,請重新輸入!\n");
}
}②電腦下棋
電腦這邊有一個難點(diǎn)就在于如何讓電腦隨機(jī)輸入數(shù)值,我是利用rand()來實(shí)現(xiàn)關(guān)于隨機(jī)的范圍我選擇了除余來解決,讓電腦輸入有了隨機(jī)性,同時也利用了while函數(shù),只有輸入了正確的位置才會跳出循環(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)于井字棋我們只要行、列,或者任意對角線上面出現(xiàn)三個連續(xù)相同的棋子,就能獲勝。因此我們可以用if語句來判斷是否滿足以上任一條件如果滿足則返回對于數(shù)值的字符,關(guān)于平局時在沒有決出勝負(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)
對于菜單沒有什么說的直接就簡單粗暴的打印就好
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("請輸入你的選擇(1/0):\n");
scanf_s("%d", &input);
if (input == 1)
{
printf("三子棋游戲開始!\n");
play();
}
else if (input == 0)
{
printf("結(jié)束游戲,感謝游玩\n");
}
else printf("請你重新選擇qaq\n");
} while (input);//假如input=0也就是input為假的時候結(jié)束循環(huán):
}2.游戲本體的構(gòu)建
關(guān)于游戲的邏輯,首先我們得構(gòu)建一個數(shù)組來實(shí)現(xiàn)因此構(gòu)建一個數(shù)組是必不可少的,然后利用函數(shù)對數(shù)組重置并且美化,然后實(shí)現(xiàn)玩家互相下棋然后顯示棋盤,判斷是否輸贏或者平局,這里我們繼續(xù)用了while循環(huán)來實(shí)現(xiàn)只有有了結(jié)果我們才會跳出循環(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");
}就這樣一個游戲就成功完成!
總結(jié)
這個游戲其實(shí)過于簡單,因?yàn)槿悠迮袛噍斱A比較簡單,也不麻煩,重點(diǎn)在于需要判斷每一步是否輸贏或者平局和對于while的理解,何時跳出循環(huán),何時繼續(xù)循環(huán),而且要細(xì)心,就比如我在寫的時候好多次把自己定義函數(shù)名字打錯導(dǎo)致編譯器錯誤找了好久才發(fā)現(xiàn),還是得細(xì)心才行。
關(guān)于這個代碼源碼頭文件什么的我都上傳到gitee上去了如果感興趣可以去看看
CSDN writings/三子棋 · banbanni/banni - 碼云 - 開源中國 (gitee.com)
到此這篇關(guān)于C++實(shí)現(xiàn)和電腦對戰(zhàn)三子棋實(shí)例的文章就介紹到這了,更多相關(guān)C++三子棋內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言數(shù)據(jù)結(jié)構(gòu)之圖的遍歷實(shí)例詳解
這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)之圖的遍歷實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-07-07
C++類重載函數(shù)的function和bind使用示例
這篇文章主要介紹了C++類重載函數(shù)的function和bind使用示例,幫助大家更好的理解和使用c++,感興趣的朋友可以了解下2021-01-01
C++ 遞歸遍歷文件并計(jì)算MD5的實(shí)例代碼
在本篇文章里小編給大家整理的是一篇關(guān)于C++ 遞歸遍歷文件并計(jì)算MD5的實(shí)例代碼,有興趣的朋友們可以學(xué)習(xí)參考下。2021-07-07
C語言實(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

