注:在最后面,完整源碼會(huì)以兩種形式展現(xiàn)。在講解時(shí),以三個(gè)源文件的形式。
前言:三子棋,顧名思義,就是三個(gè)子連在一起就可以勝出。在本節(jié)我們要介紹的三子棋模式是這樣子的:在鍵盤輸入坐標(biāo)(表示落子),和電腦對(duì)下(當(dāng)前電腦設(shè)計(jì)為隨機(jī)下)。
我們先看游戲執(zhí)行起來(lái)的樣子:
全局思路:下棋肯定需要一個(gè)棋盤,不然會(huì)顯得雜亂無(wú)章;當(dāng)有了棋盤之后,就需要落子,落子需要雙方,一個(gè)是我們自己(手動(dòng)下),另一個(gè)就是電腦(設(shè)置自動(dòng)下);當(dāng)每一次落子,都需要判斷是否輸贏,否則重復(fù)落子步驟(循環(huán));而判斷輸贏也作為一塊內(nèi)容。因?yàn)樽鳛樾∮螒?,肯定需要一個(gè)游戲菜單。
思路簡(jiǎn)圖:設(shè)置菜單------>設(shè)置棋盤------->(玩家落子--->電腦落子)------>判斷輸贏
三子棋流程圖:
上面是鋪墊,接下來(lái)才是重頭戲,該上強(qiáng)度了。
一、準(zhǔn)備工作和游戲菜單
在第一個(gè)源文件(test.c)和頭文件(game.h)中實(shí)現(xiàn)
1.準(zhǔn)備工作
(1)建立兩個(gè)源文件和一個(gè)頭文件
目的:方便觀察和日后的工作(不展開)?
(2)建立三個(gè)文件的聯(lián)系(大致雛形)
? ? ?上面的信息大致可以讓我們知道每個(gè)文件大致要存放的內(nèi)容,關(guān)于引用頭文件這些知識(shí)不是我們現(xiàn)階段需要明白的,只需記住這樣用就行。
2.游戲菜單
(1)菜單的模板
void menu()//菜單函數(shù)
{
printf("####################\n");
printf("###### 1.play ######\n");
printf("###### 0.exit ######\n");
printf("####################\n");
}
int main()
{
int input = 0;
do//循環(huán)菜單
{
menu();
printf("請(qǐng)選擇>:");
scanf("%d",&input);
} while (input);
return 0;
}
運(yùn)行結(jié)果:
1.我們把菜單封裝成一個(gè)函數(shù),放在第一個(gè)源文件中。
2.當(dāng)調(diào)用完菜單之后,會(huì)有兩個(gè)選擇,這個(gè)時(shí)候就需要輸入數(shù)據(jù),這就需要用到scanf函數(shù)。
3.因?yàn)楫?dāng)結(jié)束一局游戲后,會(huì)再次出現(xiàn)菜單讓我們選擇繼續(xù)與否,所以要用到do…while循環(huán),因?yàn)檫@樣至少會(huì)執(zhí)行一次菜單。
?(2)輸入數(shù)據(jù)后的選擇與判斷
? ? 當(dāng)我們用scanf函數(shù)輸入數(shù)據(jù)后,就需要根據(jù)輸入的數(shù)據(jù)選擇不同的路徑。
void menu()//菜單函數(shù)
{
printf("####################\n");
printf("###### 1.play ######\n");
printf("###### 0.exit ######\n");
printf("####################\n");
}
int main()
{
int input = 0;
do//循環(huán)菜單
{
menu();
printf("請(qǐng)選擇>:");
scanf("%d",&input);
switch (input)//用switch來(lái)判斷選擇
{
case 1:printf("你已選擇繼續(xù)游戲\n");
break;
case 0:printf("你已選擇退出游戲\n");
break;
default:printf("選擇錯(cuò)誤,重新選擇\n");//防止亂選
}
} while (input);
return 0;
}
運(yùn)行結(jié)果:
選擇1:
?選擇0:
?選擇其他:
?根據(jù)輸入數(shù)據(jù)的選擇,我們就需要用到switch函數(shù)來(lái)判斷。
?(3)繼續(xù)游戲后的選擇
?為了選擇1之后就直接可以進(jìn)入游戲,所以我們?cè)诤竺嬷苯痈蟝ame函數(shù),然后在game中函數(shù)調(diào)用各種函數(shù)接口。
void menu()//菜單函數(shù)
{
printf("####################\n");
printf("###### 1.play ######\n");
printf("###### 0.exit ######\n");
printf("####################\n");
}
void game()
{
char board[ROW][COL];
InitBoard(board,ROW,COL);//初始化棋盤
DisplayBoard(board,ROW,COL);//打印棋盤
//落子循環(huán)
}
int main()
{
int input = 0;
do//循環(huán)菜單
{
menu();
printf("請(qǐng)選擇>:");
scanf("%d",&input);
switch (input)
{
case 1:printf("你已選擇繼續(xù)游戲\n");
game();
break;
case 0:printf("你已選擇退出游戲\n");
break;
default:printf("選擇錯(cuò)誤,重新選擇\n");
}
} while (input);
return 0;
}
#include<stdio.h>
#define ROW 3
#define COL 3
//頭文件放函數(shù)聲明
//初始化函數(shù)
void InitBoard(char board[ROW][COL],int row,int col);
//打印函數(shù)
void DisplayBoard(char board[ROW][COL],int row,int col);
在我們的game函數(shù)內(nèi),放的是一些接口,功能暫未實(shí)現(xiàn)。
我們需要用到二維數(shù)組,然后它的行和列需要用到宏定義的常量。如果后續(xù)需要更改棋盤的大小也會(huì)很方便。
接下來(lái)我們?cè)僖灰粚?shí)現(xiàn)每個(gè)函數(shù)的功能吧
二、初始化和打印棋盤
在第二個(gè)源文件(game.c)中實(shí)現(xiàn)函數(shù)體內(nèi)部的功能。
1.初始化棋盤
//初始化函數(shù)
InitBoard(board,ROW,COL);
初始化,因?yàn)閯傞_始的棋盤是空的,只需要全部賦值成空格就好。
//初始化棋盤
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j=0;j<col;j++)
{
board[i][j] = ' ';//全部初始化成空格
}
}
}
我們可以通過(guò)調(diào)試窗口中的監(jiān)視觀察數(shù)組是否被成功賦值。
知識(shí)點(diǎn):二維數(shù)組賦值
2.打印棋盤
//打印棋盤函數(shù)
DisplayBoard(board,ROW,COL);
如果直接將初始化好的字符數(shù)組打印出來(lái),是看不見的,但是呢,我們可以先將空格換成其他可以看見的符號(hào),從而可以檢驗(yàn)我們的“打印棋盤函數(shù)”是否寫對(duì)了。
要想打印出下面的這個(gè)棋盤該怎么做呢?
?這是一個(gè)九宮格,其實(shí)這個(gè)棋盤有五行五列。第一行是空格和豎線組成,第二行是橫線和豎線組成組成,后面同理。
我們可以有很多種方式打印,我們列舉一種
1.我們可以一行一行的打印出來(lái),打印完一行就換行。
2.豎線有兩行,橫線也只有兩行,他們只能打印兩次。
3.數(shù)組打印三行三列,橫線打印兩行,豎線打印兩行。
打印棋盤函數(shù):
//打印棋盤
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i=0;i<row;i++)//控制行的個(gè)數(shù)
{
//打印數(shù)組和豎線
int j = 0;
for (j=0;j<col;j++)//控制列的個(gè)數(shù)
{
printf(" %c ",board[i][j]);
if (j<col-1)
printf("|");
}
printf("\n");//打印完換行
//打印橫線(用減號(hào)代替)和豎線
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\n");
}
}
運(yùn)行結(jié)果:
? ? 第一層循環(huán),控制行;那不是五行嗎?為什么這里只循環(huán)三次,因?yàn)橛械诙友h(huán)的控制。
總結(jié):第一次循環(huán)(第一層):打印三次空格和兩個(gè)豎線(第二層循環(huán)),第二層循環(huán)沒(méi)有結(jié)束,繼續(xù)換行打印橫線和豎線;這里需要注意:每一行需要打印三次橫線(第二次循環(huán)必須循環(huán)三次),但是只打印兩橫(第一層循環(huán)只能打印兩次);而每一行只打印兩次豎線,并且只打印兩行。
三、玩家與電腦的落子
1.玩家落子(*)
因?yàn)槲覀兯斎氲淖鴺?biāo)是從1開始,而數(shù)組的下標(biāo)是從0開始,所以需要區(qū)別
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("請(qǐng)輸入要落子的位置:\n");
while (1)
{
printf("玩家下>:");
scanf("%d%d", &x, &y);//輸入下棋的坐標(biāo)
//判斷落子位置是否合法
if (x >= 1 && x <= 3 && y >= 1 && y <= 3)
{
//判斷落子位置是否被占用
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("該位置已被占用,請(qǐng)重新輸入\n");
}
else
printf("落子位置非法\n");
}
}
總結(jié):落子時(shí),考慮位置是否合法,坐標(biāo)是否被占,否則重新循環(huán),最后再落子,落子完成再退出循環(huán)。
知識(shí)點(diǎn):選擇語(yǔ)句的條件判斷與數(shù)字下標(biāo)的運(yùn)用
2.電腦落子(#)
電腦落子,則是需要隨機(jī)產(chǎn)生數(shù)字作為坐標(biāo)再落子,所以我們需要用到產(chǎn)生隨機(jī)數(shù)的知識(shí)點(diǎn)。
生成隨機(jī)數(shù):
#include<stdlib.h>//srand所需頭文件
#include<time.h>//time所需頭文件
srand((unsigned)time(NULL));
int x=rand();//此時(shí),x中的值就是隨機(jī)值
其中srand函數(shù)和rand函數(shù)是配合使用的。
srand函數(shù)只需要在主函數(shù)中提到一次,srand函數(shù)中的參數(shù)設(shè)為時(shí)間,返回一個(gè)NULL,并強(qiáng)制類型轉(zhuǎn)化。我們當(dāng)前只需要計(jì)熟這句話就行。
然后我們就可以使用rand函數(shù)來(lái)產(chǎn)生隨機(jī)數(shù)了,只需要用變量來(lái)接收即可。
當(dāng)前頭文件:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
//初始化函數(shù)
void InitBoard(char board[ROW][COL],int row,int col);
//打印函數(shù)
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);
當(dāng)前源文件(test.c):
#include"game.h"
void menu()//菜單函數(shù)
{
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);//打印棋盤
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);//打印棋盤
ComputerMove(board,ROW,COL);
DisplayBoard(board, ROW, COL);//打印棋盤
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do//循環(huán)菜單
{
menu();
printf("請(qǐng)選擇>:");
scanf("%d",&input);
switch (input)
{
case 1:printf("你已選擇繼續(xù)游戲\n");
game();
break;
case 0:printf("你已選擇退出游戲\n");
break;
default:printf("選擇錯(cuò)誤,重新選擇\n");
}
} while (input);
return 0;
}
電腦落子函數(shù):
//電腦落子
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("電腦落子:\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;
y = rand() % col;//范圍0-2
if (board[x][y] == ' ')
{
board[x][y] = '#';//滿足就落子,否則繼續(xù)循環(huán)
break;
}
}
}
上面的落子函數(shù)雖然已經(jīng)寫完,但是運(yùn)行起來(lái)還是很不完整的,接下來(lái)的判贏才是重頭戲。
四、判斷輸贏與循環(huán)落子
1.判贏
游戲的大致走向有四種:繼續(xù)游戲、玩家贏、電腦贏和平局。其中,繼續(xù)游戲就是循環(huán)落子的原因,知道出現(xiàn)一個(gè)結(jié)局。
判贏函數(shù):
char Iswin(char board[ROW][COL], int row, int col)
我們這里規(guī)定一下,根據(jù)該函數(shù)的返回值來(lái)決定四種結(jié)果:
//*--玩家贏 #----電腦贏 P----平局 C-----游戲繼續(xù)
判贏:
三子棋游戲勝利的結(jié)果就是三個(gè)子連成一條線。三子連成線的結(jié)果無(wú)非就是三種:橫、豎和斜的。
//*--玩家贏 #----電腦贏 P----平局 C-----繼續(xù)
char Iswin(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)//三列相等的
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
return board[0][i];
}
for (i = 0; i < col; i++)//三列相等的
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
}
//判斷\相等
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
return board[1][1];
//判斷/相等
if (board[2][2] == board[1][1] && board[1][1] == board[0][0] && board[1][1] != ' ')
return board[1][1];
return 'C';
}
1.前面兩個(gè)for循環(huán)判斷橫與列是否相等,如果相等就返回某一個(gè)坐標(biāo)的值。
2.后面兩個(gè)if語(yǔ)句同樣的效果,滿足條件就返回某個(gè)坐標(biāo)。
3.如果上面的都不滿足,則會(huì)返回'C',也就是游戲繼續(xù)
上面的代碼還差一種結(jié)局,那就是平局。平局的條件莫非就是棋盤滿了,但是還沒(méi)有分出勝負(fù),所以我們另外封裝一個(gè)判滿的函數(shù)即可。(在上面的代碼基礎(chǔ)上改進(jìn))
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] == ' ')
return 0;
}
}
return 1;
}
//*--玩家贏 #----電腦贏 P----平局 C-----繼續(xù)
char Iswin(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)//三列相等的
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
return board[0][i];
}
for (i = 0; i < col; i++)//三列相等的
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
}
//判斷\相等
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
return board[1][1];
//判斷/相等
if (board[2][2] == board[1][1] && board[1][1] == board[0][0] && board[1][1] != ' ')
return board[1][1];
//判斷平局
if (IsFull(board, row, col))
return 'P';
return 'C';
}
現(xiàn)在代碼完整了,只要不滿足輸贏或者平局,游戲就會(huì)繼續(xù)。
現(xiàn)在函數(shù)體的內(nèi)容都已經(jīng)完成,接下來(lái)需要在主函數(shù)實(shí)現(xiàn)接收其返回值并實(shí)現(xiàn)循環(huán)落子。
2.用循環(huán)實(shí)現(xiàn)游戲繼續(xù)
其實(shí)就是每下一次,就打印一次棋盤,并且判斷一次游戲是否繼續(xù)
char ret=0;
while (1)
{
//玩家下棋
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);//打印棋盤
//每走一步棋就判斷一次
ret = Iswin(board,ROW,COL);
if (ret != 'C')//C!=C為假,不會(huì)跳出循環(huán)
break;
//電腦下棋
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);//打印棋盤
//判斷電腦輸贏
ret = Iswin(board,ROW,COL);
if (ret != 'C')
break;
}
//跳出循環(huán),表示博弈結(jié)束,并判斷結(jié)局
if (ret == '*')
printf("恭喜玩家獲勝,再來(lái)一局吧\n");
if (ret == '#')
printf("電腦獲勝,再來(lái)一局吧\n");
if (ret == 'P')
printf("恭喜平局,誰(shuí)也沒(méi)有獲勝\n");
到這里每個(gè)階段的內(nèi)容就完成了,接下來(lái)是總體的代碼。
五、完整源碼
1.分裝成三個(gè)文件的源碼
(1)頭文件(game.h)
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
//初始化函數(shù)
void InitBoard(char board[ROW][COL],int row,int col);
//打印函數(shù)
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);
//判斷輸贏
char Iswin(char board[ROW][COL], int row, int col);
(2)源文件(game.c)
#include"game.h"
//初始化棋盤
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j=0;j<col;j++)
{
board[i][j] = ' ';//全部初始化成空格
}
}
}
//打印棋盤
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i=0;i<row;i++)//控制行的個(gè)數(shù)
{
//打印數(shù)組和豎線
int j = 0;
for (j=0;j<col;j++)//控制列的個(gè)數(shù)
{
printf(" %c ",board[i][j]);
if (j<col-1)
printf("|");
}
printf("\n");//打印完換行
//打印橫線(用減號(hào)代替)和豎線
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;
int y = 0;
printf("請(qǐng)輸入要落子的位置:\n");
while (1)
{
printf("玩家下>:");
scanf("%d%d", &x, &y);//輸入下棋的坐標(biāo)
//判斷落子位置是否合法
if (x >= 1 && x <= 3 && y >= 1 && y <= 3)
{
//判斷落子位置是否被占用
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("該位置已被占用,請(qǐng)重新輸入\n");
}
else
printf("落子位置非法\n");
}
}
//電腦落子
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("電腦落子:\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;
y = rand() % col;//范圍0-2
if (board[x][y] == ' ')
{
board[x][y] = '#';//滿足就落子,否則繼續(xù)循環(huán)
break;
}
}
}
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] == ' ')
return 0;
}
}
return 1;
}//*--玩家贏 #----電腦贏 P----平局 C-----繼續(xù)
char Iswin(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)//三列相等的
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
return board[0][i];
}
for (i = 0; i < col; i++)//三列相等的
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
}
//判斷\相等
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
return board[1][1];
//判斷/相等
if (board[2][2] == board[1][1] && board[1][1] == board[0][0] && board[1][1] != ' ')
return board[1][1];
//判斷平局
if (IsFull(board, row, col))
return 'P';
return 'C';
}
(3)源文件(test.c)
#include"game.h"
void menu()//菜單函數(shù)
{
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;
}
//跳出循環(huán),表示博弈結(jié)束,并判斷結(jié)局
if (ret == '*')
printf("恭喜玩家獲勝,再來(lái)一局吧\n");
if (ret == '#')
printf("電腦獲勝,再來(lái)一局吧\n");
if (ret == 'P')
printf("恭喜平局,誰(shuí)也沒(méi)有獲勝\n");
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do//循環(huán)菜單
{
menu();
printf("請(qǐng)選擇>:");
scanf("%d",&input);
switch (input)
{
case 1:printf("你已選擇繼續(xù)游戲\n");
game();
break;
case 0:printf("你已選擇退出游戲\n");
break;
default:printf("選擇錯(cuò)誤,重新選擇\n");
}
} while (input);
return 0;
}
2.一個(gè)文件的源碼
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3
//初始化函數(shù)
void InitBoard(char board[ROW][COL],int row,int col);
//打印函數(shù)
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);
//判斷輸贏
char Iswin(char board[ROW][COL], int row, int col);
//初始化棋盤
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j=0;j<col;j++)
{
board[i][j] = ' ';//全部初始化成空格
}
}
}
//打印棋盤
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i=0;i<row;i++)//控制行的個(gè)數(shù)
{
//打印數(shù)組和豎線
int j = 0;
for (j=0;j<col;j++)//控制列的個(gè)數(shù)
{
printf(" %c ",board[i][j]);
if (j<col-1)
printf("|");
}
printf("\n");//打印完換行
//打印橫線(用減號(hào)代替)和豎線
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;
int y = 0;
printf("請(qǐng)輸入要落子的位置:\n");
while (1)
{
printf("玩家下>:");
scanf("%d%d", &x, &y);//輸入下棋的坐標(biāo)
//判斷落子位置是否合法
if (x >= 1 && x <= 3 && y >= 1 && y <= 3)
{
//判斷落子位置是否被占用
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
printf("該位置已被占用,請(qǐng)重新輸入\n");
}
else
printf("落子位置非法\n");
}
}
//電腦落子
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("電腦落子:\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;
y = rand() % col;//范圍0-2
if (board[x][y] == ' ')
{
board[x][y] = '#';//滿足就落子,否則繼續(xù)循環(huán)
break;
}
}
}
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] == ' ')
return 0;
}
}
return 1;
}//*--玩家贏 #----電腦贏 P----平局 C-----繼續(xù)
char Iswin(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)//三列相等的
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
return board[0][i];
}
for (i = 0; i < col; i++)//三列相等的
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
return board[i][0];
}
//判斷\相等
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
return board[1][1];
//判斷/相等
if (board[2][2] == board[1][1] && board[1][1] == board[0][0] && board[1][1] != ' ')
return board[1][1];
//判斷平局
if (IsFull(board, row, col))
return 'P';
return 'C';
}
void menu()//菜單函數(shù)
{
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;
}
//跳出循環(huán),表示博弈結(jié)束,并判斷結(jié)局
if (ret == '*')
printf("恭喜玩家獲勝,再來(lái)一局吧\n");
if (ret == '#')
printf("電腦獲勝,再來(lái)一局吧\n");
if (ret == 'P')
printf("恭喜平局,誰(shuí)也沒(méi)有獲勝\n");
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do//循環(huán)菜單
{
menu();
printf("請(qǐng)選擇>:");
scanf("%d",&input);
switch (input)
{
case 1:printf("你已選擇繼續(xù)游戲\n");
game();
break;
case 0:printf("你已選擇退出游戲\n");
break;
default:printf("選擇錯(cuò)誤,重新選擇\n");
}
} while (input);
return 0;
}
六、總結(jié)
1.需要掌握產(chǎn)生隨機(jī)數(shù)的方法。
2.游戲總的是采用二維數(shù)組實(shí)現(xiàn),其中包括了二維數(shù)組的賦值和打印數(shù)據(jù)。
3.函數(shù)的返回值和各種循環(huán)結(jié)果、選擇結(jié)構(gòu)。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-635205.html
若上述源碼有bug,歡迎各位大佬留言。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-635205.html
到了這里,關(guān)于C語(yǔ)言三子棋小游戲--數(shù)組的應(yīng)用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!