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