直入主題,為了實(shí)現(xiàn)一個(gè)三子棋小游戲,我們先來看一下三子棋是怎么玩的。
創(chuàng)新互聯(lián)公司是一家網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站建設(shè),提供網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),網(wǎng)站制作,建網(wǎng)站,專業(yè)公司,網(wǎng)站開發(fā)公司,從2013年創(chuàng)立是互聯(lián)行業(yè)建設(shè)者,服務(wù)者。以提升客戶品牌價(jià)值為核心業(yè)務(wù),全程參與項(xiàng)目的網(wǎng)站策劃設(shè)計(jì)制作,前端開發(fā),后臺(tái)程序制作以及后期項(xiàng)目運(yùn)營并提出專業(yè)建議和思路。《三子棋》是一款古老的民間傳統(tǒng)游戲,又被稱為黑白棋、圈圈叉叉棋、井字棋、一條龍、九宮棋等。游戲分為雙方對(duì)戰(zhàn),雙方依次在9宮格棋盤上擺放棋子,率先將自己的三個(gè)棋子連成一條線的一方則視為勝利者。
為了給讀者更直觀的感受,接下來我們?cè)賮砜匆豢从镁幊虒?shí)現(xiàn)三子棋的成品是怎么樣的。
接下來,我們將逐步實(shí)現(xiàn)三子棋這個(gè)小游戲,我會(huì)逐步細(xì)分到每一個(gè)函數(shù)保證讀者的觀感。
目錄
一.打印菜單
二.實(shí)現(xiàn)主菜單功能
三.游戲函數(shù)
1.初始化棋盤
2.打印棋盤
3.玩家下棋
4.電腦下棋
5.判斷輸贏
(1)第一種方法
5.判斷輸贏
(2)第二種方法
#includevoid menu()
{
printf("***********************************\n");
printf("********* 1.三子棋 *********\n");
printf("********* 0.退出游戲 *********\n");
printf("***********************************\n");
}
int main()
{
menu();
return 0;
}
我們定義了一個(gè)函數(shù)menu()函數(shù)
名字:menu
類型:?void(就如int類型返回整形,char類型返回字符類型,void類型就是無返回值)
返回值:無返回值
參數(shù):無參數(shù)
功能:打印菜單
此函數(shù)只是打印菜單,沒有需要說明的,讀者自然能看懂。
運(yùn)行截圖:
#includevoid menu()
{
printf("***********************************\n");
printf("********* 1.三子棋 *********\n");
printf("********* 0.退出游戲 *********\n");
printf("***********************************\n");
}
int main()
{
int input = 0;//定義變量input接收輸入值
do {
menu();
printf("請(qǐng)選擇->\n");
scanf("%d", &input);
//---------------------------------------------
switch (input)//通過switch讀取input的值判斷需要做什么
{
case 1:
//game();//實(shí)現(xiàn)游戲的函數(shù),暫時(shí)還沒寫
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("輸入有誤,請(qǐng)重新輸入\n");
break;
}
//---------------------------------------------
} while (input);//當(dāng)input為0(退出游戲)時(shí)就跳出循環(huán)結(jié)束游戲,非0為真,繼續(xù)循環(huán)
return 0;
}
這一步只是利用do while循環(huán)和switch函數(shù)來實(shí)現(xiàn)主菜單功能,讀者可以通過代碼中的注釋來讀懂該段代碼。
運(yùn)行截圖:(選擇1并沒有開始游戲是因?yàn)檫€沒有開始寫游戲本體代碼)
三子棋是一個(gè)3乘3的棋盤,所以很容易想到用一個(gè)存放字符的類型為char的二維數(shù)組來實(shí)現(xiàn),在游戲開始前,棋盤里應(yīng)該都是空格,所以我們應(yīng)該先創(chuàng)建一個(gè)char類型的二維數(shù)組并全部初始化為空格。
在此之前我們先定義一個(gè)game函數(shù)(類型為void),這個(gè)函數(shù)的功能是實(shí)現(xiàn)我們游戲本體的。
#define ROW 3
#define COL 3
void game()//定義游戲函數(shù)
{
char board[3][3];//創(chuàng)建char類型的3乘3的數(shù)組
InitBoard(board, ROW, COL);//這是初始化棋盤的函數(shù)
}
注意!這里我用了define來定義了ROW(行)和COL(列)均為3,這樣可以增加代碼的可讀性。之后我將不會(huì)再顯示這兩行代碼,也請(qǐng)讀者記好這兩行代碼,這將使你受益匪淺。
void InitBoard(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++)
{
board[i][j] = ' ';
}
}
}
這里的小寫row和col均是形參,值分別等于ROW和COL的
我們定義了一個(gè)函數(shù)Initboard()函數(shù)
名字:Initboard
類型:?void(就如int類型返回整形,char類型返回字符類型,void類型就是無返回值)
返回值:無返回值
參數(shù):3個(gè)參數(shù),char類型的二維數(shù)組board,int類型的row,int類型的col。
功能:初始化棋盤
我采用遍歷(對(duì)數(shù)組每一個(gè)元素都進(jìn)行訪問)的形式將數(shù)組每個(gè)元素都初始化為了空格。
這里我們也可以使用一個(gè)庫函數(shù)進(jìn)行初始化。?
memset函數(shù)(需要引入頭文件string.h)
功能:作用是將某一塊內(nèi)存中的內(nèi)容全部設(shè)置為指定的值, 這個(gè)函數(shù)通常為新申請(qǐng)的內(nèi)存做初始化工作。
memset(&board[0][0], ' ', row * col * sizeof(board[0][0]));
//第一個(gè)參數(shù)是一個(gè)地址,第二個(gè)參數(shù)是一個(gè)字符,也可以是一個(gè)值,第三個(gè)參數(shù)是字節(jié)數(shù)
棋盤初始化之后我們就要打印棋盤了,下面是棋盤的圖片。
可以看出棋盤是由一些 ‘-’ 和 ‘|’ 來打印的,下面我來為個(gè)位讀者仔細(xì)分析這個(gè)棋盤。
(畫圖技術(shù)不好還請(qǐng)讀者諒解)
我們可以將棋盤分為三組,每一組如圖所示,一組分為上半部分和下半部分。
void PrintBoard(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i< row; i++)//循環(huán)3次 { for (j = 0; j< col; j++)//這個(gè)for打印的是上半部分,循環(huán)3次 { printf(" %c |", board[i][j]);//結(jié)構(gòu)為(空格)(數(shù)組的空格)(空格)(|) } printf("\n"); for (j = 0; j< col; j++)//這個(gè)for打印的是下半部分,循環(huán)3次 { printf("---|");//結(jié)構(gòu)為(-)(-)(-)(|) } printf("\n"); } }
這里的小寫row和col均是形參,值分別等于ROW和COL的
我們定義了一個(gè)函數(shù)printboard()函數(shù)
名字:printboard
類型:?void(就如int類型返回整形,char類型返回字符類型,void類型就是無返回值)
返回值:無返回值
參數(shù):3個(gè)參數(shù),char類型的二維數(shù)組board,int類型的row,int類型的col。
功能:打印棋盤
這一段結(jié)合注釋也希望讀者能夠看懂,可以自己結(jié)合上面的圖畫圖分析。
運(yùn)行截圖:
很明顯,這個(gè)棋盤和最開始演示的棋盤有億些不同多了最右邊一列和最底部的一行。這里的解決辦法是加一個(gè)限制條件,打印每一行的最后一組時(shí)那一列不打印,打印最后一組時(shí)那一行也不打印。
void PrintBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i< row; i++)//循環(huán)3次
{
for (j = 0; j< col; j++)//這個(gè)for打印的是上半部分,循環(huán)3次
{
printf(" %c ", board[i][j]);//結(jié)構(gòu)為(空格)(數(shù)組的空格)(空格)
if (j + 1< col)//打印上半部分的最后一列時(shí)不打印(|)
printf("|");
}
printf("\n");
if (i + 1< row)//打印最后一組時(shí)不打印下半部分
{
for (j = 0; j< col; j++)//這個(gè)for打印的是下半部分,循環(huán)3次
{
printf("---");//結(jié)構(gòu)為(-)(-)(-)
if (j + 1< col)//打印下半部分的最后一列時(shí)不打印(|)
printf("|");
}
printf("\n");
}
}
}
運(yùn)行截圖:
這一塊就比較簡單了,我們需要接收玩家下達(dá)的指令,并且檢查玩家給出的坐標(biāo)是否超出棋盤或者該坐標(biāo)是否已經(jīng)有棋子了,判斷一個(gè)坐標(biāo)有無棋子就是判斷該坐標(biāo)是否為空格。
void Player(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋,請(qǐng)選擇你的坐標(biāo)\n");
while (1)//循環(huán),當(dāng)棋子正確落下時(shí)跳出循環(huán)結(jié)束玩家下棋階段
{
scanf("%d %d", &x, &y);//接收玩家下達(dá)的坐標(biāo)
if (x - 1 >= 0 && x - 1< row && y - 1 >= 0 && y - 1< col)//檢查是否超出棋盤
{
if (board[x - 1][y - 1] != ' ')//檢查該坐標(biāo)是否有棋子
{
printf("你選擇的地方已經(jīng)有棋子了,請(qǐng)重新選擇\n");
continue; //當(dāng)棋子沒有正常落下時(shí)繼續(xù)循環(huán),直到棋子正確落下
}
board[x - 1][y - 1] = '*';
break;//當(dāng)棋子正確落下時(shí)跳出循環(huán)結(jié)束玩家下棋階段
}
else
printf("你選擇的坐標(biāo)非法,請(qǐng)重新選擇\n");//當(dāng)棋子沒有正常落下時(shí)繼續(xù)循環(huán),直到棋子正確落下
}
printf("------------------------\n");
}
這里的小寫row和col均是形參,值分別等于ROW和COL的
我們定義了一個(gè)函數(shù)player()函數(shù)
名字:Player
類型:?void(就如int類型返回整形,char類型返回字符類型,void類型就是無返回值)
返回值:無返回值
參數(shù):3個(gè)參數(shù),char類型的二維數(shù)組board,int類型的row,int類型的col。
功能:玩家下棋
注意玩家下棋時(shí)的坐標(biāo)是從1開始,而數(shù)組的下標(biāo)是從零開始,所以我們需要將玩家輸入的坐標(biāo)減1。
運(yùn)行截圖:
電腦下棋我們可以使用rand函數(shù),通過取余ROW和COL來隨機(jī)出電腦下棋的坐標(biāo),因?yàn)槭侨∮嗟玫降淖鴺?biāo),所以我們不用擔(dān)心坐標(biāo)是否會(huì)超出棋盤,只需判斷該坐標(biāo)處是否有棋子就行。
這里需要介紹一下rand函數(shù)的使用方法,簡單來說就是首先需要一個(gè)srand函數(shù)來設(shè)置隨機(jī)數(shù)生成器,srand里面的參數(shù)需要隨時(shí)變化,這里我們可以讓srand函數(shù)調(diào)用時(shí)間戳,就實(shí)現(xiàn)了隨機(jī)數(shù)的生成。(rand函數(shù)生成的隨機(jī)數(shù)范圍是0-32767)
#include//rand和srand函數(shù)需要的頭文件
#include//time函數(shù)需要的頭文件
int main()
{
int input = 0;//定義變量input接收輸入值
srand((unsigned int)time(NULL));//設(shè)置隨機(jī)數(shù)生成器
do {
menu();
printf("請(qǐng)選擇->\n");
scanf("%d", &input);
//---------------------------------------------
switch (input)//通過switch讀取input的值判斷需要做什么
{
case 1:
game();//實(shí)現(xiàn)游戲的函數(shù)
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("輸入有誤,請(qǐng)重新輸入\n");
break;
}
//---------------------------------------------
} while (input);//當(dāng)input為0(退出游戲)時(shí)就跳出循環(huán)結(jié)束游戲,非0為真,繼續(xù)循環(huán)
return 0;
}
srand函數(shù)的參數(shù)是(unsigned int)所以就強(qiáng)制類型轉(zhuǎn)換 ,time函數(shù)參數(shù)是指針,我們可以傳一個(gè)空指針進(jìn)去NULL。
void Computer(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("電腦下棋->\n");
while (1)//循環(huán)和玩家下棋道理一樣
{
x = rand() % row;//隨機(jī)值取余row(3)得到 0 - 2的隨機(jī)值
y = rand() % col;//隨機(jī)值取余row(3)得到 0 - 2的隨機(jī)值
if (board[x][y] == ' ')//判斷該坐標(biāo)是否有棋子
{
board[x][y] = '#';
break;//成功下棋,跳出循環(huán)
}
}
}
這里的小寫row和col均是形參,值分別等于ROW和COL的
我們定義了一個(gè)函數(shù)Computer()函數(shù)
名字:Computer
類型:?void(就如int類型返回整形,char類型返回字符類型,void類型就是無返回值)
返回值:無返回值
參數(shù):3個(gè)參數(shù),char類型的二維數(shù)組board,int類型的row,int類型的col。
功能:電腦下棋
這里只需注意取余以及判斷是否有棋子。?
運(yùn)行截圖:?
三子棋輸贏規(guī)則:“率先將自己的三個(gè)棋子連成一條線(橫線、數(shù)線、斜線)的一方則視為勝利者?!?/p>
這里我有兩種方法,這里先介紹比較容易理解的方法一。
思路:通過判斷函數(shù)的返回值來確定是誰贏了,以及是否平局,或者是否還能繼續(xù)下棋。
無論是電腦還是玩家下完棋都應(yīng)該進(jìn)行一次判斷,下面是游戲函數(shù)的代碼。
我們定義:‘*’是玩家贏,‘#’是電腦贏,‘Q’是平局,‘C’是繼續(xù)下棋。
void game()//定義游戲函數(shù)
{
char board[3][3];//創(chuàng)建char類型的3乘3的數(shù)組
char ret = 0;//創(chuàng)建變量接收J(rèn)udge函數(shù)的返回值
InitBoard(board, ROW, COL);//這是初始化棋盤的函數(shù)
while (1)//每一輪是玩家下棋,判斷輸贏,電腦下棋,判斷輸贏。循環(huán)每一輪直到有一方贏或者平局
{
PrintBoard(board, ROW, COL);//打印棋盤函數(shù)
Player(board, ROW, COL);//玩家下棋函數(shù)
ret = Judge(board, ROW, COL);//接收J(rèn)udge函數(shù)的返回值
if (ret != 'C')//判斷還能不能繼續(xù)下棋
{
break;
}
Computer(board, ROW, COL);//電腦下棋函數(shù)
ret = Judge(board, ROW, COL);//接收J(rèn)udge函數(shù)的返回值
if (ret != 'C')//判斷還能不能繼續(xù)下棋
{
break;
}
}
if ('*' == ret)//根據(jù)Judge函數(shù)的返回值判斷結(jié)果
{
printf("玩家贏\n");
}
else if ('#' == ret)
{
printf("電腦贏\n");
}
else if ('Q' == ret)
{
printf("平局\n");
}
}
下面是判斷函數(shù)的代碼:
char Judge(char board[ROW][COL], int row, int col)
{
int i = 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] != ' ')//判斷對(duì)角線棋子是不是相同并且不是空格
{
return board[1][1];//返回的字符則代表著是玩家還是電腦
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')//判斷另一條對(duì)角線棋子是不是相同并且不是空格
{
return board[1][1];//返回的字符則代表著是玩家還是電腦
}
if (IsFull(board, row, col))//判斷是否平局(遍歷數(shù)組看是否還有空格)
{
return 'Q';
}
return 'C'; //游戲繼續(xù)
}
int IsFull(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] == ' ')//遍歷數(shù)組看是否還有空格
{
return 0;
}
}
}
return 1;
}
這里的小寫row和col均是形參,值分別等于ROW和COL的
我們定義了一個(gè)函數(shù)Judge()函數(shù)
名字:Judge
類型: char(就如int類型返回整形,char類型返回字符類型,void類型就是無返回值)
返回值:字符形
參數(shù):3個(gè)參數(shù),char類型的二維數(shù)組board,int類型的row,int類型的col。
功能:判斷輸贏
我們定義了一個(gè)函數(shù)IsFull()函數(shù)
名字:IsFull
類型: int(就如int類型返回整形,char類型返回字符類型,void類型就是無返回值)
返回值:整形
參數(shù):3個(gè)參數(shù),char類型的二維數(shù)組board,int類型的row,int類型的col。
功能:判斷是否平局
運(yùn)行截圖如下:
到這里三子棋基本就寫完了,下面是一些可以改進(jìn)的方法和判斷函數(shù)的第二種寫法。
有興趣的讀者可以繼續(xù)閱讀,非常感謝你能看到這里,有任何疑問或者有可以改進(jìn)的地方也可以在評(píng)論區(qū)指出,如果你對(duì)我的文章認(rèn)可的話也可以點(diǎn)個(gè)贊。
全部代碼:
#define _CRT_SECURE_NO_WARNINGS 1
#include#include#include#define ROW 3
#define COL 3
void menu()
{
printf("***********************************\n");
printf("********* 1.三子棋 *********\n");
printf("********* 0.退出游戲 *********\n");
printf("***********************************\n");
}
void InitBoard(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++)
{
board[i][j] = ' ';
}
}
}
void PrintBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i< row; i++)//循環(huán)3次
{
for (j = 0; j< col; j++)//這個(gè)for打印的是上半部分,循環(huán)3次
{
printf(" %c ", board[i][j]);//結(jié)構(gòu)為(空格)(數(shù)組的空格)(空格)
if (j + 1< col)//打印上半部分的最后一列時(shí)不打印(|)
printf("|");
}
printf("\n");
if (i + 1< row)//打印最后一組時(shí)不打印下半部分
{
for (j = 0; j< col; j++)//這個(gè)for打印的是下半部分,循環(huán)3次
{
printf("---");//結(jié)構(gòu)為(-)(-)(-)
if (j + 1< col)//打印下半部分的最后一列時(shí)不打印(|)
printf("|");
}
printf("\n");
}
}
}
void Player(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋,請(qǐng)選擇你的坐標(biāo)\n");
while (1)//循環(huán),當(dāng)棋子正確落下時(shí)跳出循環(huán)結(jié)束玩家下棋階段
{
scanf("%d %d", &x, &y);//接收玩家下達(dá)的坐標(biāo)
if (x - 1 >= 0 && x - 1< row && y - 1 >= 0 && y - 1< col)//檢查是否超出棋盤
{
if (board[x - 1][y - 1] != ' ')//檢查該坐標(biāo)是否有棋子
{
printf("你選擇的地方已經(jīng)有棋子了,請(qǐng)重新選擇\n");
continue; //當(dāng)棋子沒有正常落下時(shí)繼續(xù)循環(huán),直到棋子正確落下
}
board[x - 1][y - 1] = '*';
break;//當(dāng)棋子正確落下時(shí)跳出循環(huán)結(jié)束玩家下棋階段
}
else
printf("你選擇的坐標(biāo)非法,請(qǐng)重新選擇\n");//當(dāng)棋子沒有正常落下時(shí)繼續(xù)循環(huán),直到棋子正確落下
}
printf("------------------------\n");
}
void Computer(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("電腦下棋->\n");
while (1)//循環(huán)和玩家下棋道理一樣
{
x = rand() % row;//隨機(jī)值取余row(3)得到 0 - 2的隨機(jī)值
y = rand() % col;//隨機(jī)值取余row(3)得到 0 - 2的隨機(jī)值
if (board[x][y] == ' ')//判斷該坐標(biāo)是否有棋子
{
board[x][y] = '#';
break;//成功下棋,跳出循環(huán)
}
}
}
char Judge(char board[ROW][COL], int row, int col)
{
int i = 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] != ' ')//判斷對(duì)角線棋子是不是相同并且不是空格
{
return board[1][1];//返回的字符則代表著是玩家還是電腦
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')//判斷另一條對(duì)角線棋子是不是相同并且不是空格
{
return board[1][1];//返回的字符則代表著是玩家還是電腦
}
if (IsFull(board, row, col))//判斷是否平局(遍歷數(shù)組看是否還有空格)
{
return 'Q';
}
return 'C'; //游戲繼續(xù)
}
int IsFull(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] == ' ')//遍歷數(shù)組看是否還有空格
{
return 0;
}
}
}
return 1;
}
void game()//定義游戲函數(shù)
{
char board[3][3];//創(chuàng)建char類型的3乘3的數(shù)組
char ret = 0;//創(chuàng)建變量接收J(rèn)udge函數(shù)的返回值
InitBoard(board, ROW, COL);//這是初始化棋盤的函數(shù)
while (1)//每一輪是玩家下棋,判斷輸贏,電腦下棋,判斷輸贏。循環(huán)每一輪直到有一方贏或者平局
{
PrintBoard(board, ROW, COL);//打印棋盤函數(shù)
Player(board, ROW, COL);//玩家下棋函數(shù)
ret = Judge(board, ROW, COL);//接收J(rèn)udge函數(shù)的返回值
if (ret != 'C')//判斷還能不能繼續(xù)下棋
{
break;
}
Computer(board, ROW, COL);//電腦下棋函數(shù)
ret = Judge(board, ROW, COL);//接收J(rèn)udge函數(shù)的返回值
if (ret != 'C')//判斷還能不能繼續(xù)下棋
{
break;
}
}
if ('*' == ret)//根據(jù)Judge函數(shù)的返回值判斷結(jié)果
{
printf("玩家贏\n");
}
else if ('#' == ret)
{
printf("電腦贏\n");
}
else if ('Q' == ret)
{
printf("平局\n");
}
PrintBoard(board, ROW, COL);//打印棋盤函數(shù)
}
int main()
{
int input = 0;//定義變量input接收輸入值
srand((unsigned int)time(NULL));
do {
menu();
printf("請(qǐng)選擇->\n");
scanf("%d", &input);
//---------------------------------------------
switch (input)//通過switch讀取input的值判斷需要做什么
{
case 1:
game();//實(shí)現(xiàn)游戲的函數(shù)
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("輸入有誤,請(qǐng)重新輸入\n");
break;
}
//---------------------------------------------
} while (input);//當(dāng)input為0(退出游戲)時(shí)就跳出循環(huán)結(jié)束游戲,非0為真,繼續(xù)循環(huán)
return 0;
}
這種方法判斷行列時(shí)使用了兩個(gè)for
判斷對(duì)角線和棋盤上是否有空格和第一種方法類似。
與第一種代碼比較誰好誰壞這就靠讀者自己判斷了。
char judge(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
int flag = 0;//標(biāo)志,判斷三個(gè)棋子是否相同
for (i = 0; i< row; i++)
{
for (j = 0, flag = 1; j< col - 1; j++)//標(biāo)志初始化為1
{
if (board[i][j] != board[i][j + 1] || board[i][j] == ' ')//判斷每一行棋子是否相同并且不是空格
{
flag = 0;//當(dāng)滿足上述條件就意味著三個(gè)棋子不相同,flag為0
break;
}
}
if (flag)//flag為1時(shí)說明三個(gè)棋子相同,返回的字符則代表著是電腦贏還是玩家贏
return board[i][j];
}
for (j = 0; j< col; j++)
{
for (i = 0, flag = 1; i< row - 1; i++)//標(biāo)志初始化為1
{
if (board[i][j] != board[i + 1][j] || board[i][j] == ' ')//判斷每一列棋子是否相同并且不是空格
{
flag = 0;//當(dāng)滿足上述條件就意味著三個(gè)棋子不相同,flag為0
break;
}
}
if (flag)//flag為1時(shí)說明三個(gè)棋子相同,返回的字符則代表著是電腦贏還是玩家贏
return board[i][j];
}
for (i = 0, j = 0; i< row - 1; i++, j++)
{
if (board[i][j] == ' ' || board[i][j] != board[i + 1][j + 1])//判斷對(duì)角線棋子是否相同并且不是空格
break;
if (i == row - 2)//該條件滿足說明斜對(duì)角線三個(gè)棋子相同
return board[i][j];
}
for (i = 0, j = col - 1; i< row - 1; i++, j--)
{
if (board[i][j] == ' ' || board[i][j] != board[i + 1][j - 1])//判斷另一條對(duì)角線棋子是否相同并且不是空格
break;
if (i == row - 2)//該條件滿足說明斜對(duì)角線三個(gè)棋子相同
return board[i][j];
}
for (i = 0; i< row; i++)
{
for (j = 0; j< col; j++)
{
if (board[i][j] == ' ')//判斷棋盤上是否有空格沒有空格說明能繼續(xù)下棋
return 'C';
}
}
return 'E';//能走到這里說明前面判斷沒有任何人贏并且棋盤上沒有空格,平局
}
這里的小寫row和col均是形參,值分別等于ROW和COL的
我們定義了一個(gè)函數(shù)Judge()函數(shù)
名字:Judge
類型: char(就如int類型返回整形,char類型返回字符類型,void類型就是無返回值)
返回值:字符形
參數(shù):3個(gè)參數(shù),char類型的二維數(shù)組board,int類型的row,int類型的col。
功能:判斷輸贏
這種辦法稍微有點(diǎn)復(fù)雜,不過是基于第一種方法的另一個(gè)思路。
下面是游戲函數(shù):
void game()//定義游戲函數(shù)
{
char board[3][3];//創(chuàng)建char類型的3乘3的數(shù)組
char flag = 0;//創(chuàng)建變量接收J(rèn)udge函數(shù)的返回值
InitBoard(board, ROW, COL);//這是初始化棋盤的函數(shù)
while (1)//每一輪是玩家下棋,判斷輸贏,電腦下棋,判斷輸贏。循環(huán)每一輪直到有一方贏或者平局
{
PrintBoard(board, ROW, COL);//打印棋盤函數(shù)
Player(board, ROW, COL);//玩家下棋函數(shù)
flag = judge(board, ROW, COL);
if (flag != 'C')
break;
Computer(board, ROW, COL);//電腦下棋函數(shù)
flag = judge(board, ROW, COL);
if (flag != 'C')
break;
}
if (flag == '*')
printf("玩家勝利\n");
else if (flag == '#')
printf("電腦勝利\n");
else
printf("平局\n");
PrintBoard(board, ROW, COL);
}
到這里第二種方法也介紹完了。然后這樣所有代碼都在一個(gè)項(xiàng)目里難免有些亂,需要修改某些函數(shù)時(shí)也會(huì)比較麻煩,所以我們可以吧游戲函數(shù)里面的函數(shù)定義放在一個(gè)新的文件里,名叫g(shù)ame.c而為了這些函數(shù)能在我的主項(xiàng)目test.c文件里起作用,我還需要?jiǎng)?chuàng)建一個(gè)頭文件,名叫g(shù)ame.h。這樣分成模塊化的封裝函數(shù)不僅好修改代碼,而且可讀性也有了一定提升。
封裝好了之后的代碼如下:
test.c
#include"game.h"http://引用自己創(chuàng)建的頭文件,""是查找非標(biāo)準(zhǔn)庫里面的頭文件,<>是查找標(biāo)準(zhǔn)庫里面的頭文件
void game()
{
char board[ROW][COL] = {0};
int flag = 0;
InitBoard(board, ROW, COL);
while (1)
{
PrintBoard(board, ROW, COL);
printf("\n");
Player(board, ROW, COL);
flag = judge(board, ROW, COL);
if (flag != 'C')
break;
Computer(board, ROW, COL);
flag = judge(board, ROW, COL);
if (flag != 'C')
break;
}
if (flag == '*')
printf("玩家勝利\n");
else if (flag == '#')
printf("電腦勝利\n");
else
printf("平局\n");
PrintBoard(board, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do {
menu();
printf("請(qǐng)選擇->\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("輸入有誤,請(qǐng)重新輸入\n");
break;
}
} while (input);
return 0;
}
game.h
#include#include#include#include#define ROW 3
#define COL 3
//各個(gè)函數(shù)的聲明
void menu();
void InitBoard(char board[ROW][COL], int row, int col);
void PrintBoard(char board[ROW][COL], int row, int col);
void Player(char board[ROW][COL], int row, int col);
void Computer(char board[ROW][COL], int row, int col);
char judge(char board[ROW][COL], int row, int col);
game.c
#include"game.h"
void menu()
{
printf("***********************************\n");
printf("********* 1.三子棋 *********\n");
printf("********* 0.退出游戲 *********\n");
printf("***********************************\n");
}
void InitBoard(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++)
{
board[i][j] = ' ';
}
}
}
void PrintBoard(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++)
{
printf(" %c ", board[i][j]);
if (j + 1< col)
printf("|");
}
printf("\n");
if (i + 1< row)
{
for (j = 0; j< col; j++)
{
printf("---");
if (j + 1< col)
printf("|");
}
printf("\n");
}
}
}
void Player(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋,請(qǐng)選擇你的坐標(biāo)\n");
while (1)
{
scanf("%d %d", &x, &y);
if (x - 1 >= 0 && x - 1< row && y - 1 >= 0 && y - 1< col)
{
if (board[x - 1][y - 1] != ' ')
{
printf("你選擇的地方已經(jīng)有棋子了,請(qǐng)重新選擇\n");
continue;
}
board[x - 1][y - 1] = '*';
break;
}
else
printf("你選擇的坐標(biāo)非法,請(qǐng)重新選擇\n");
}
printf("------------------------\n");
}
void Computer(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("電腦下棋->\n");
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
char judge(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
int flag = 0;
for (i = 0; i< row; i++)
{
for (j = 0,flag = 1; j< col - 1; j++)
{
if (board[i][j] != board[i][j + 1] || board[i][j] == ' ')
{
flag = 0;
break;
}
}
if(flag)
return board[i][j];
}
for (j = 0; j< col; j++)
{
for (i = 0,flag = 1; i< row - 1; i++)
{
if (board[i][j] != board[i + 1][j] || board[i][j] == ' ')
{
flag = 0;
break;
}
}
if (flag)
return board[i][j];
}
for (i = 0, j = 0; i< row - 1; i++, j++)
{
if (board[i][j] == ' ' || board[i][j] != board[i + 1][j + 1])
break;
if (i == row - 2)
return board[i][j];
}
for (i = 0, j = col - 1; i< row - 1; i++, j--)
{
if (board[i][j] == ' ' || board[i][j] != board[i + 1][j - 1])
break;
if (i == row - 2)
return board[i][j];
}
for (i = 0; i< row; i++)
{
for (j = 0; j< col; j++)
{
if (board[i][j] == ' ')
return 'C';
}
}
return 'E';
}
本次的三子棋編寫就到這里,感謝各位讀者的觀看!
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧