首先先介紹一下三子棋游戲,三子棋也就是井字棋,在一個(gè)9*9的方格里,兩人對(duì)弈,誰(shuí)先三點(diǎn)連成一線誰(shuí)就取得勝利。
“專(zhuān)業(yè)、務(wù)實(shí)、高效、創(chuàng)新、把客戶的事當(dāng)成自己的事”是我們每一個(gè)人一直以來(lái)堅(jiān)持追求的企業(yè)文化。 創(chuàng)新互聯(lián)是您可以信賴的網(wǎng)站建設(shè)服務(wù)商、專(zhuān)業(yè)的互聯(lián)網(wǎng)服務(wù)提供商! 專(zhuān)注于成都網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、軟件開(kāi)發(fā)、設(shè)計(jì)服務(wù)業(yè)務(wù)。我們始終堅(jiān)持以客戶需求為導(dǎo)向,結(jié)合用戶體驗(yàn)與視覺(jué)傳達(dá),提供有針對(duì)性的項(xiàng)目解決方案,提供專(zhuān)業(yè)性的建議,創(chuàng)新互聯(lián)建站將不斷地超越自我,追逐市場(chǎng),引領(lǐng)市場(chǎng)!整體代碼? 現(xiàn)在我們來(lái)看一下如何用C語(yǔ)言程序來(lái)實(shí)現(xiàn)這個(gè)游戲。
廢話不多說(shuō)了,先直接看完整的一套代碼圖:
我是用三個(gè)文件來(lái)分別書(shū)寫(xiě)的。
game.h頭文件:
//包含所用的庫(kù)函數(shù)的頭文件
#include#include#include//定義一些工程里要用到的常量
#define ROW 3
#define COL 3
//函數(shù)聲明
//初始化棋盤(pán)
void init(char arr1[ROW][COL], int row, int col);
//打印棋盤(pán)
void print(char arr1[ROW][COL], int row, int col);
//玩家下棋
void player_move(char arr1[ROW][COL], int row, int col);
//電腦下棋
void computer_move(char arr1[ROW][COL], int row, int col);
//判斷輸贏
char is_win(char arr1[ROW][COL], int row, int col);
game.c文件(存儲(chǔ)游戲的功能實(shí)現(xiàn)的函數(shù)):
#include"game.h"
//初始化棋盤(pán)
void init(char arr1[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i< row; i++)
{
int j = 0;
for (j = 0; j< col; j++)
{
arr1[i][j] = ' ';//將棋盤(pán)所有元素置為空格。
}
}
}
//打印棋盤(pán)
void print(char arr1[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 ", arr1[i][j]);
if (j< col - 1)
{
printf("|");//分割線
}
}
printf("\n");
for (j = 0; j< col; j++)
{
if (i< row - 1)
{
printf("---");//分割線
if (j< col - 1)
{
printf("|");//分割線
}
}
}
printf("\n");
}
}
//玩家下棋
void player_move(char arr1[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("請(qǐng)輸入坐標(biāo)(用空格分開(kāi)):");
scanf("%d %d", &x, &y);
//判斷坐標(biāo)的合法性
if (x >= 1 && x<= 3 && y >= 1 && y<= 3)
{
if (arr1[x-1][y-1] == ' ')
{
arr1[x-1][y-1] = '*';//將該位置改為 * ,表示玩家下。
break;
}
else
{
printf("坐標(biāo)被占用,請(qǐng)重新輸入\n");
}
}
else
{
printf("坐標(biāo)錯(cuò)誤,請(qǐng)重新輸入\n");
}
}
}
//電腦下棋
void computer_move(char arr1[ROW][COL], int row, int col)
{
printf("電腦下棋:\n");
while (1)
{
int x = rand() % 3;
int y = rand() % 3;
if (arr1[x][y] == ' ')
{
arr1[x][y] = '#';//將該位置改為 * ,表示電腦下。
break;
}
}
}
//判斷輸贏
char is_win(char arr1[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
//一行相等
for (i = 0; i< row; i++)
{
if (arr1[i][0] == arr1[i][1] && arr1[i][1] == arr1[i][2]&&arr1[i][0]!=' ')
{
return arr1[i][0];
}
}
//一列相等
for (j = 0; j< col; j++)
{
if (arr1[0][j] == arr1[1][j] && arr1[1][j] == arr1[2][j] && arr1[i][0] != ' ')
{
return arr1[0][j];
}
}
//對(duì)角線相等
if (arr1[0][0] == arr1[1][1] && arr1[1][1] == arr1[2][2] && arr1[0][0] != ' ')
{
return arr1[0][0];
}
if (arr1[2][0] == arr1[1][1] && arr1[1][1] == arr1[0][2] && arr1[2][0] != ' ')
{
return arr1[2][0];
}
//平局
int count = 0;
for (i = 0; i< row; i++)
{
for (j = 0; j< col; j++)
{
if (arr1[i][j] == ' ')
{
count++;
}
}
}
if (0 == count)
{
return 'Q';
}
return 'C';
}
?test.c文件(包含一些基礎(chǔ)的函數(shù)):
#include"game.h"
//菜單
void menu()
{
printf("******************\n");
printf("***** 1.game *****\n");
printf("***** 0.exit *****\n");
printf("******************\n");
}
//游戲
void game()
{
//定義一個(gè)棋盤(pán)
char arr1[ROW][COL] = {0};
//初始化棋盤(pán)
init(arr1, ROW, COL);
//打印棋盤(pán)
print(arr1, ROW, COL);
while (1)
{
char ret = 0;
//玩家下棋
player_move(arr1,ROW,COL);
//打印棋盤(pán)
print(arr1, ROW, COL);
//判斷輸贏
//1.返回*:玩家贏
//2.返回#:電腦贏
//3.返回'Q':平局
//4.返回'C':繼續(xù)
ret = is_win(arr1, ROW, COL);
if (ret == '*')
{
printf("玩家贏\n");
break;
}
else if (ret == '#')
{
printf("電腦贏\n");
break;
}
else if (ret == 'Q')
{
printf("平局\n");
break;
}
else if (ret == 'C')
{
;
}
//電腦下棋
computer_move(arr1, ROW, COL);
//打印棋盤(pán)
print(arr1, ROW, COL);
//判斷輸贏
ret = is_win(arr1, ROW, COL);
if (ret == '*')
{
printf("玩家贏\n");
break;
}
else if (ret == '#')
{
printf("電腦贏\n");
break;
}
else if (ret == 'Q')
{
printf("平局\n");
break;
}
else if (ret == 'C')
{
;
}
}
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("請(qǐng)選擇選項(xiàng):");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("游戲退出成功\n");
break;
default:
printf(" 選擇錯(cuò)誤,請(qǐng)重新選擇。\n");
break;
}
} while (input);
return 0;
}
看了完整的代碼后,下面進(jìn)行詳細(xì)的講解:
菜單函數(shù)??????第一步:我們最好給游戲者一個(gè)選擇菜單,讓他有玩游戲和退出游戲這兩個(gè)簡(jiǎn)單的選項(xiàng),游戲者選擇玩游戲,我們?cè)匍_(kāi)始這個(gè)游戲的運(yùn)行。選擇退出游戲,我們就將整個(gè)程序退出掉。
? 下面看代碼:
//菜單
void menu()
{
printf("******************\n");
printf("***** 1.game *****\n");
printf("***** 0.exit *****\n");
printf("******************\n");
}
我們?cè)谄聊簧洗蛴∪缟献謽?,讓用戶能夠進(jìn)行選擇,當(dāng)然現(xiàn)在還不可以進(jìn)行選擇,在這里我們就需要讓用戶輸入數(shù)值來(lái)進(jìn)行選擇,先看下面這段代碼:
int main()
{
srand((unsigned int)time(NULL));//此處是根據(jù)時(shí)間戳來(lái)提供隨機(jī)值,現(xiàn)在先無(wú)需理會(huì)。
int input = 0;//定義一個(gè)變量,讓用戶輸入。
do
{
menu();//調(diào)用我們之前寫(xiě)的菜單函數(shù)
printf("請(qǐng)選擇選項(xiàng):");
scanf("%d", &input);//用戶輸入選項(xiàng)的編號(hào)
switch (input)
{
case 1://選擇1進(jìn)入游戲
game();//編寫(xiě)的游戲函數(shù),目前還沒(méi)有實(shí)現(xiàn),先無(wú)需理會(huì)。
break;
case 0://選擇0退出游戲
printf("游戲退出成功\n");
break;
default://輸入其他值,讓其重新選擇。
printf(" 選擇錯(cuò)誤,請(qǐng)重新選擇。\n");
break;
}
} while (input);//利用輸入值判斷循環(huán)是否繼續(xù)。
return 0;
}
在這段代碼中,我們首先定義一個(gè)變量 名為:input? 讓用戶來(lái)為這個(gè)變量賦值,通過(guò)用戶輸入的值來(lái)判斷,是進(jìn)行游戲,還是退出游戲,或者用戶輸入輸錯(cuò)了輸入了其他的值,從而讓用戶重新輸入。我們發(fā)現(xiàn)這應(yīng)該是選擇語(yǔ)句,所以,用 switch 語(yǔ)句來(lái)實(shí)現(xiàn)選擇功能。然后我們發(fā)現(xiàn)如果用戶玩完一把游戲后還想繼續(xù)玩,直到他自己退出游戲,或者輸錯(cuò)了功能選項(xiàng),讓他繼續(xù)輸入直到輸對(duì)。這些都應(yīng)該是 循環(huán)才對(duì)。所以我們用 do while 語(yǔ)句來(lái)實(shí)現(xiàn)循環(huán)。我們將?input的值作為判斷條件,上來(lái)先讓用戶輸入數(shù)值,然后進(jìn)行一系列的功能的運(yùn)行,最后判斷此值的真假以此來(lái)判斷循環(huán)是否繼續(xù)。我們知道在計(jì)算機(jī)中0為假,非0為真。所以上面這段代碼,將0作為退出。
游戲?qū)崿F(xiàn)? 下面我們來(lái)實(shí)現(xiàn)一下game()函數(shù)。
首先我們要明白,要實(shí)現(xiàn)那些功能。我想:我們要有一個(gè)棋盤(pán),然后我們要把這個(gè)棋盤(pán)展現(xiàn)給玩家看,再者我們要讓玩家能夠下棋,然后我們想玩家不能一個(gè)人下啊,我們要讓電腦也能下棋和玩家對(duì)壘,最后既然是游戲,那就要有輸贏。我們還要判斷一下誰(shuí)輸誰(shuí)贏。
所以要實(shí)現(xiàn)以下功能(以下編號(hào)并不代表函數(shù)先后順序):
1:定義和初始化棋盤(pán)
2:打印棋盤(pán)
3:玩家下棋
4:電腦下棋
5:判斷輸贏
1:定義和初始化棋盤(pán)首先,我們應(yīng)該有一個(gè)9*9的棋盤(pán),在這棋盤(pán)上我們先進(jìn)行初始化,將每個(gè)位置初始化成空格。
請(qǐng)看下圖代碼:
ROW、COL是我們?cè)趃ame.h的頭文件當(dāng)中定義的常量分別代表行數(shù)和列數(shù),方便以后修改行列的數(shù)值。
2:打印棋盤(pán)我們?cè)趖est.c中調(diào)用了打印棋盤(pán)的函數(shù):
下面是詳細(xì)的實(shí)現(xiàn):
//打印棋盤(pán)
void print(char arr1[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 ", arr1[i][j]);
if (j< col - 1)
{
printf("|");//分割線
}
}
printf("\n");
for (j = 0; j< col; j++)
{
if (i< row - 1)
{
printf("---");//分割線
if (j< col - 1)
{
printf("|");//分割線
}
}
}
printf("\n");
}
}
其實(shí)很簡(jiǎn)單,就是通過(guò)遍歷這個(gè)棋盤(pán)數(shù)組來(lái)打印,但是由于一開(kāi)始打印的都是空格,打印出來(lái)會(huì)非常不明顯,所以在其中根據(jù)一些簡(jiǎn)單的循環(huán)邏輯打印一些分割線,來(lái)使空格更加明顯。
此函數(shù)運(yùn)行打印出來(lái)的棋盤(pán)如圖:
3:玩家下棋此功能如何實(shí)現(xiàn)呢?
思路:首先玩家應(yīng)該先輸入一個(gè)坐標(biāo),我們應(yīng)該首先要判斷這個(gè)坐標(biāo)的合法性(在不在我們創(chuàng)建的數(shù)組之中,要注意!數(shù)組的下標(biāo)是從0開(kāi)始的,而玩家不會(huì)了解這些,玩家所看到的第一行第一列的位置其實(shí)是二維數(shù)組中0行0列的位置,所以要對(duì)玩家輸入的坐標(biāo)進(jìn)行處理。),當(dāng)坐標(biāo)合法后,開(kāi)始下棋,我們用 * 字符標(biāo)記玩家下棋的位置(表示此處玩家下過(guò)一子),那么這里就會(huì)出現(xiàn)新的問(wèn)題,玩家此位置下過(guò)后,就不能再下了。所以我們要判斷一下,此處有沒(méi)有下過(guò)棋子。最后玩家成功下完后,我們跳出此函數(shù)。
下面是詳細(xì)代碼:
//玩家下棋
void player_move(char arr1[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("請(qǐng)輸入坐標(biāo)(用空格分開(kāi)):");
scanf("%d %d", &x, &y);
//判斷坐標(biāo)的合法性
if (x >= 1 && x<= 3 && y >= 1 && y<= 3)
{
if (arr1[x-1][y-1] == ' ')
{
arr1[x-1][y-1] = '*';//將該位置改為 * ,表示玩家下。
break;
}
else
{
printf("坐標(biāo)被占用,請(qǐng)重新輸入\n");
}
}
else
{
printf("坐標(biāo)錯(cuò)誤,請(qǐng)重新輸入\n");
}
}
}
在代碼中我們使用循環(huán)來(lái)寫(xiě),是為了玩家下棋不成功,就讓他一直下,直到下成為止。而不成功其實(shí)有兩種情況,剛才我們已經(jīng)分析過(guò)了,1:坐標(biāo)不存在,2:坐標(biāo)被占用。下成后我們將該位置元素改為 * 以此證明玩家在此處落子,然后就用break跳出循環(huán)。
4:電腦下棋請(qǐng)看代碼:
//電腦下棋
void computer_move(char arr1[ROW][COL], int row, int col)
{
printf("電腦下棋:\n");
while (1)
{
int x = rand() % 3;
int y = rand() % 3;
if (arr1[x][y] == ' ')
{
arr1[x][y] = '#';//將該位置改為 * ,表示電腦下。
break;
}
}
}
讓電腦下棋就簡(jiǎn)單多了,我們只需讓它在這九個(gè)位置中隨機(jī)下,直到下成為止。
5:判斷輸贏最后一個(gè)功能了,游戲輸贏其實(shí)有多種情況,比如:玩家贏,電腦贏,平局,繼續(xù)下。
不如直接寫(xiě)一個(gè)函數(shù),然后讓它根據(jù)不同的情況返回不同的值,來(lái)判斷一下哪種情況的發(fā)生。
比如:玩家贏返回 * ,電腦贏返回 # ,平局返回 Q ,繼續(xù)下返回 C 。(根據(jù)返回的字符的不同來(lái)區(qū)分)。
所以這個(gè)函數(shù)我們這樣寫(xiě),如圖:
接收返回值后,在游戲函數(shù)中進(jìn)行判斷,看函數(shù)要不要繼續(xù)執(zhí)行。
//判斷輸贏
//1.返回*:玩家贏
//2.返回#:電腦贏
//3.返回'Q':平局
//4.返回'C':繼續(xù)
ret = is_win(arr1, ROW, COL);
if (ret == '*')
{
printf("玩家贏\n");
break;
}
else if (ret == '#')
{
printf("電腦贏\n");
break;
}
else if (ret == 'Q')
{
printf("平局\n");
break;
}
else if (ret == 'C')
{
;
}
如此所有的基本功能就都實(shí)現(xiàn)了。
最后,我們要整理一下這些功能的順序,來(lái)使得游戲正常運(yùn)行。
功能順序整理首先,第一步:打印棋盤(pán)提供給玩家下棋,第二步:玩家下一子,然后緊接著判斷一下輸贏。
第三步:電腦下一子,然后緊接著也判斷一下輸贏。
我們發(fā)現(xiàn)玩家下一子判斷,電腦下一子也判斷,這個(gè)過(guò)程要重復(fù)多次,不如直接寫(xiě)一個(gè)循環(huán)套上,直到判斷出結(jié)果再跳出循環(huán)。這正是上面代碼中break的用處。(可在完整代碼中查看)
?????
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧