一,游戲的基本框架
游戲中有人機,雙人兩種模式。五子棋作為一個平面游戲,很明顯用二維數(shù)組來寫最合適不過。為了讓代碼看起來更有條理,我們用三個.c文件,分別是:text.c 用來測試我們的游戲;game.c 游戲功能的實現(xiàn);is_win.c 判斷輸贏的版塊。另外,還有一個game.h 文件來放我們的函數(shù)聲明和頭文件。
二 、主函數(shù)的設(shè)計
主函數(shù)的主要邏輯我們用switch,case語句來實現(xiàn),為了能夠在選擇錯誤后重新選擇,我們在switch 語句外層又嵌套了do while語句來實現(xiàn)循環(huán),且循環(huán)終止條件就是游戲的退出的條件,代碼如下:
int main()
{
srand((unsigned int)time(NULL));
int input;
do
{
menu();
printf("請選擇>");
scanf("%d", &input);
switch (input)
{
case 1:
game1();
break;
case 2:
game2();
break;
case 0:
printf("退出\n");
break;
default:
printf("請重新輸入\n");
break;
}
} while (input);
return 0;
}
其中,game1()表示人機模式,game2()表示雙人模式。
三、重要功能設(shè)計
3.1 游戲界面的設(shè)計
代碼如下:
void menu()
{
printf("*************************\n");
printf("*****1.人機 2.雙人*****\n");
printf("******** 0.退出 ********\n");
printf("*************************\n");
}
3.2棋盤的初始化
上面我們提到“五子棋作為一個平面游戲,很明顯用二維數(shù)組來寫最合適不過”因此,我們定義一個行為ROW,列為COL的二維數(shù)組,并將其初始化為’ ',代碼如下:
void Init_board(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
代碼運行結(jié)果如圖:
3.3棋盤的設(shè)計
如圖,這是我們想要的棋盤設(shè)計結(jié)果
我們先打印“ %c ”,再打印“ | ”,利用for循環(huán)完成一行的打印,這里我們要注意的是:當(dāng)打印完每行最后一個“ %c”時,是不需要再次打印“ | ”的,因此在這里我們加一個if語句進(jìn)行判斷,當(dāng)j<col-1時才進(jìn)行“ | ”的打印。
代碼如下:
for (int j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
當(dāng)每打印完上述的一行后,我們進(jìn)行換行后,打印“—|”,再次利用for循環(huán)進(jìn)行一行的打印,在這里也要注意當(dāng)進(jìn)行一行的最后一次打印時我們只需要打印“—”,因此在這里我們需要加一個if,else 的判斷語句,代碼如下:
printf("\n");
for (int i = 0; i < col; i++)
{
if (i < col - 1)
{
printf("---|");
}
else
{
printf("---");
}
}
最后我們再用一個for循環(huán)進(jìn)行多行的打印,完整代碼如下:
void print_board(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
for (int i = 0; i < col; i++)
{
if (i < col - 1)
{
printf("---|");
}
else
{
printf("---");
}
}
printf("\n");
}
}
3.4 玩家下棋
玩家輸入坐標(biāo),在這里要注意的是玩家輸入的坐標(biāo)減一才是我們二維數(shù)組的下標(biāo)。
scanf("%d%d", &x, &y);
i = x - 1;
j = y - 1;
當(dāng)輸入坐標(biāo)后,我們要進(jìn)行坐標(biāo)的合理性判斷:1.所輸入坐標(biāo)是否超出棋盤范圍;2.所輸入坐標(biāo)是否已被占用。如果所輸入坐標(biāo)合理,則將坐標(biāo)位置賦予一定的字符(本游戲中,在人機對戰(zhàn)中,玩家所下為**‘’,在雙人對戰(zhàn)中,玩家一所下為‘’,玩家二為‘#’**);若坐標(biāo)不合理,則提示后重新輸入。
int player_board(char board[ROW][COL], int row, int col)
{
printf("玩家下:\n");
int i = 0;
int j = 0;
int x = 0;
int y = 0;
while (1)
{
scanf("%d%d", &x, &y);
i = x - 1;
j = y - 1;
if (x >= 1 && y >= 1 && x <= row && y <= col)
{
if (board[i][j] != ' ')
{
printf("此坐標(biāo)已經(jīng)被占用,請重新下:\n");
}
else
{
board[i][j] = '*';
int ret = is_win(board, ROW, COL, &i, &j, '*');
return ret;
}
}
else
{
printf("非法坐標(biāo),請重新下:\n");
}
}
}
運行結(jié)果:
3.5 電腦下棋
電腦下棋我們采用的是通過隨機數(shù)函數(shù)生成合理坐標(biāo),然后進(jìn)行下棋(電腦所下為**‘#’**)。這里要注意的就是隨機函數(shù)srand(),必須與srand()函數(shù),時間戳搭配使用,且srand()函數(shù)只能調(diào)用一次,我們在主函數(shù)中進(jìn)行調(diào)用。
int main()
{
srand((unsigned int)time(NULL))//srand()函數(shù)的調(diào)用;
//由于srand函數(shù)的參數(shù)為無符號數(shù),因此要將時間戳(time函數(shù))的返回值類型強轉(zhuǎn)化為無符號數(shù)。
int computer_board(char board[ROW][COL], int row, int col)
{
printf("電腦下:\n");
while (1)
{
int ret1 = rand() % row;
int ret2 = rand() % col;
if (board[ret1][ret2] == ' ')
{
board[ret1][ret2] = '#';
int ret = is_win(board, ROW, COL, &ret1, &ret2, '#');
return ret;
}
}
}
運行結(jié)果:
3.6 勝負(fù)判斷
3.6.1 行的判斷
我們通過所下的坐標(biāo)來找到當(dāng)前行的最左端,然后對這一行進(jìn)行遍歷,如果發(fā)現(xiàn)了有五個連續(xù)且一樣的字符,則獲勝。代碼如下:
int Col_win(char board[ROW][COL], int row, int col, int* ret1, char ret)
{
int count = 0;
for (int i = 0; i < col; i++)
{
if (board[*ret1][i] == ret)
{
count++;
}
if (count == renju)
{
break;
}
if (i + 1 <= col && board[*ret1][i + 1] != ret)
{
count = 0;
}
}
if (count == renju)
{
if (ret == '#')
{
return 1;
}
if (ret == '*')
{
return 2;
}
}
return 3;
}
3.6.2 列的判斷
與上述行的判斷一樣,我們通過所下的坐標(biāo)來找到當(dāng)前列的最上端,然后對這一行進(jìn)行遍歷,如果發(fā)現(xiàn)了有五個連續(xù)且一樣的字符,則獲勝。代碼如下:
int Row_win(char board[ROW][COL], int row, int col, int* ret2, char ret)
{
int count = 0;
for (int i = 0; i < row; i++)
{
if (board[i][*ret2] == ret)
{
count++;
}
if (count == renju)
{
break;
}
if (i + 1 <= row && board[i + 1][*ret2] != ret)
{
count = 0;
}
}
if (count == renju)
{
if (ret == '#')
{
return 1;
}
if (ret == '*')
{
return 2;
}
}
return 3;
}
3.6.3 對角的判斷
通過所下的坐標(biāo)來找到當(dāng)前對角的端點,對對角進(jìn)行遍歷,若有五個連續(xù)且相同的字符,則獲勝。
代碼如下;
int Dia1_win(char board[ROW][COL], int row, int col, int* ret1, int* ret2, char ret)
{
//下半角
int count1 = 0;
for (int i = 0; i < row && i < col; i++)
{
if (board[*ret1 - (*ret2 - i)][i] == ret)
{
count1++;
}
if (count1 == renju)
{
break;
}
if (i + 1 < col && board[*ret1 - (*ret2 - i - 1)][i + 1] != ret)
{
count1 = 0;
}
}
if (count1 == renju)
{
if (ret == '#')
{
return 1;
}
if (ret == '*')
{
return 2;
}
}
//上半角
int count2 = 0;
for (int i = col - 1; i >= 0; i--)
{
if (board[*ret1 + (i - *ret2)][i] == ret)
{
count2++;
}
if (count2 == renju)
{
break;
}
if (i - 1 > 0 && board[*ret1 + (i - *ret2)][i - 1] != ret)
{
count2 = 0;
}
}
if (count2 == renju)
{
if (ret == '#')
{
return 1;
}
if (ret == '*')
{
return 2;
}
}
return 3;
}
int Dia2_win(char board[ROW][COL], int row, int col, int* ret1, int* ret2, char ret)
{
//上半角
int count1 = 0;
for (int i = 0; i < row && i < col; i++)
{
if (board[*ret1 + *ret2 - i][i] == ret)
{
count1++;
}
if (count1 == renju)
{
break;
}
if (i + 1 < col && board[*ret1 + *ret2 - i - 1][i + 1] != ret)
{
count1 = 0;
}
}
if (count1 == renju)
{
if (ret == '#')
{
return 1;
}
if (ret == '*')
{
return 2;
}
}
//下半角
int count2 = 0;
for (int i = col - 1; i >= 0; i--)
{
if (*ret1 - (i - *ret2) >= 0 && board[*ret1 - (i - *ret2)][i] == ret)
{
count2++;
}
if (count2 == renju)
{
break;
}
if (i - 1 > 0 && board[*ret1 - (i - *ret2) + 1][i - 1] != ret)
{
count2 = 0;
}
}
if (count2 == renju)
{
if (ret == '#')
{
return 1;
}
if (ret == '*')
{
return 2;
}
}
return 3;
}
3.6.4 判斷平局
我們將整個二維數(shù)組遍歷一遍,在沒有獲勝的前提下,若沒有發(fā)現(xiàn)**‘ ’,則證明棋盤已下滿——平局;若發(fā)現(xiàn)了‘ ’**,則繼續(xù)游戲。代碼如下:文章來源:http://www.zghlxwxcb.cn/news/detail-487603.html
int is_full(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 4;
}
四.game.h文件
此文件里主要是一些函數(shù)聲明,頭文件和宏定義。文章來源地址http://www.zghlxwxcb.cn/news/detail-487603.html
#define ROW 7//定義行
#define COL 7//定義列
#define renju 5//定義幾子琪
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void Init_board(char board[ROW][COL], int row, int col);
void print_board(char board[ROW][COL], int row, int col);
int player_board(char board[ROW][COL], int row, int col);
int player_board1(char board[ROW][COL], int row, int col);
int player_board2(char board[ROW][COL], int row, int col);
int computer_board(char board[ROW][COL], int row, int col);
int is_full(char board[ROW][COL], int row, int col);
int is_win(char board[ROW][COL], int row, int col, int* ret1, int* ret2, char ret);
int is_win2(char board[ROW][COL], int row, int col, int* ret1, int* ret2, char ret);
五. 完整代碼
//text.c
#include"game.h"
void game1()
{
int flag = 0;
char board[ROW][COL] = { 0 };
Init_board(board, ROW, COL);
print_board(board, ROW, COL);
while (1)
{
int ret1 = player_board(board, ROW, COL);
if (ret1 == 1 || ret1 == 0)
{
print_board(board, ROW, COL);
break;
}
print_board(board, ROW, COL);
int ret2 = computer_board(board, ROW, COL);
if (ret2 == 1 || ret1 == 0)
{
print_board(board, ROW, COL);
break;
}
print_board(board, ROW, COL);
}
}
//雙人
void game2()
{
int flag = 0;
char board[ROW][COL] = { 0 };
Init_board(board, ROW, COL);
print_board(board, ROW, COL);
while (1)
{
int ret1 = player_board1(board, ROW, COL);
if (ret1 == 1 || ret1 == 0)
{
print_board(board, ROW, COL);
break;
}
print_board(board, ROW, COL);
int ret2 = player_board2(board, ROW, COL);
if (ret2 == 1 || ret1 == 0)
{
print_board(board, ROW, COL);
break;
}
print_board(board, ROW, COL);
}
}
void menu()
{
printf("*************************\n");
printf("*****1.人機 2.雙人*****\n");
printf("******** 0.退出 ********\n");
printf("*************************\n");
}
int main()
{
srand((unsigned int)time(NULL));
int input;
do
{
menu();
printf("請選擇>");
scanf("%d", &input);
switch (input)
{
case 1:
game1();
break;
case 2:
game2();
break;
case 0:
printf("退出\n");
break;
default:
printf("請重新輸入\n");
break;
}
} while (input);
return 0;
}
//game.h
#include"game.h"
void Init_board(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void print_board(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
for (int i = 0; i < col; i++)
{
if (i < col - 1)
{
printf("---|");
}
else
{
printf("---");
}
}
printf("\n");
}
}
int player_board(char board[ROW][COL], int row, int col)
{
printf("玩家下:\n");
int i = 0;
int j = 0;
int x = 0;
int y = 0;
while (1)
{
scanf("%d%d", &x, &y);
i = x - 1;
j = y - 1;
if (x >= 1 && y >= 1 && x <= row && y <= col)
{
if (board[i][j] != ' ')
{
printf("此坐標(biāo)已經(jīng)被占用,請重新下:\n");
}
else
{
board[i][j] = '*';
int ret = is_win(board, ROW, COL, &i, &j, '*');
return ret;
//break;
}
}
else
{
printf("非法坐標(biāo),請重新下:\n");
}
}
}
int computer_board(char board[ROW][COL], int row, int col)
{
printf("電腦下:\n");
while (1)
{
int ret1 = rand() % row;
int ret2 = rand() % col;
if (board[ret1][ret2] == ' ')
{
board[ret1][ret2] = '#';
int ret = is_win(board, ROW, COL, &ret1, &ret2, '#');
return ret;
//break;
}
}
}
//雙人
int player_board1(char board[ROW][COL], int row, int col)
{
printf("玩家下A:\n");
int i = 0;
int j = 0;
int x = 0;
int y = 0;
while (1)
{
scanf("%d%d", &x, &y);
i = x - 1;
j = y - 1;
if (x >= 1 && y >= 1 && x <= row && y <= col)
{
if (board[i][j] != ' ')
{
printf("此坐標(biāo)已經(jīng)被占用,請重新下:\n");
}
else
{
board[i][j] = '*';
int ret = is_win2(board, ROW, COL, &i, &j, '*');
return ret;
//break;
}
}
else
{
printf("非法坐標(biāo),請重新下:\n");
}
}
}
int player_board2(char board[ROW][COL], int row, int col)
{
printf("玩家下B:\n");
int i = 0;
int j = 0;
int x = 0;
int y = 0;
while (1)
{
scanf("%d%d", &x, &y);
i = x - 1;
j = y - 1;
if (x >= 1 && y >= 1 && x <= row && y <= col)
{
if (board[i][j] != ' ')
{
printf("此坐標(biāo)已經(jīng)被占用,請重新下:\n");
}
else
{
board[i][j] = '#';
int ret = is_win2(board, ROW, COL, &i, &j, '#');
return ret;
//break;
}
}
else
{
printf("非法坐標(biāo),請重新下:\n");
}
}
}
//is_win.c
#include"game.h"
//判斷行
int Col_win(char board[ROW][COL], int row, int col, int* ret1, char ret)
{
int count = 0;
for (int i = 0; i < col; i++)
{
if (board[*ret1][i] == ret)
{
count++;
}
if (count == renju)
{
break;
}
if (i + 1 <= col && board[*ret1][i + 1] != ret)
{
count = 0;
}
}
if (count == renju)
{
if (ret == '#')
{
//printf("電腦贏了");
return 1;
}
if (ret == '*')
{
//printf("你贏了");
return 2;
}
}
return 3;
}
//判斷列
int Row_win(char board[ROW][COL], int row, int col, int* ret2, char ret)
{
int count = 0;
for (int i = 0; i < row; i++)
{
if (board[i][*ret2] == ret)
{
count++;
}
if (count == renju)
{
break;
}
if (i + 1 <= row && board[i + 1][*ret2] != ret)
{
count = 0;
}
}
if (count == renju)
{
if (ret == '#')
{
//printf("電腦贏了");
return 1;
}
if (ret == '*')
{
//printf("你贏了");
return 2;
}
}
return 3;
}
//左
int Dia1_win(char board[ROW][COL], int row, int col, int* ret1, int* ret2, char ret)
{
//下半角
int count1 = 0;
for (int i = 0; i < row && i < col; i++)
{
if (board[*ret1 - (*ret2 - i)][i] == ret)
{
count1++;
}
if (count1 == renju)
{
break;
}
if (i + 1 < col && board[*ret1 - (*ret2 - i - 1)][i + 1] != ret)
{
count1 = 0;
}
}
if (count1 == renju)
{
if (ret == '#')
{
//printf("電腦贏了");
return 1;
}
if (ret == '*')
{
//printf("你贏了");
return 2;
}
}
//上半角
int count2 = 0;
for (int i = col - 1; i >= 0; i--)
{
if (board[*ret1 + (i - *ret2)][i] == ret)
{
count2++;
}
if (count2 == renju)
{
break;
}
if (i - 1 > 0 && board[*ret1 + (i - *ret2)][i - 1] != ret)
{
count2 = 0;
}
}
if (count2 == renju)
{
if (ret == '#')
{
//printf("電腦贏了");
return 1;
}
if (ret == '*')
{
//printf("你贏了");
return 2;
}
}
return 3;
}
int Dia2_win(char board[ROW][COL], int row, int col, int* ret1, int* ret2, char ret)
{
//上半角
int count1 = 0;
for (int i = 0; i < row && i < col; i++)
{
if (board[*ret1 + *ret2 - i][i] == ret)
{
count1++;
}
if (count1 == renju)
{
break;
}
if (i + 1 < col && board[*ret1 + *ret2 - i - 1][i + 1] != ret)
{
count1 = 0;
}
}
if (count1 == renju)
{
if (ret == '#')
{
//printf("電腦贏了");
return 1;
}
if (ret == '*')
{
//printf("你贏了");
return 2;
}
}
//下半角
int count2 = 0;
for (int i = col - 1; i >= 0; i--)
{
if (*ret1 - (i - *ret2) >= 0 && board[*ret1 - (i - *ret2)][i] == ret)
{
count2++;
}
if (count2 == renju)
{
break;
}
if (i - 1 > 0 && board[*ret1 - (i - *ret2) + 1][i - 1] != ret)
{
count2 = 0;
}
}
if (count2 == renju)
{
if (ret == '#')
{
//printf("電腦贏了");
return 1;
}
if (ret == '*')
{
//printf("你贏了");
return 2;
}
}
return 3;
}
int is_full(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 4;
}
int is_win(char board[ROW][COL], int row, int col, int* ret1, int* ret2, char ret)
{
int a = Col_win(board, row, col, ret1, ret);
int b = Row_win(board, row, col, ret2, ret);
int c = Dia1_win(board, row, col, ret1, ret2, ret);
int d = Dia2_win(board, row, col, ret1, ret2, ret);
int e = is_full(board, row, col);
if (e == 0)
{
if (a == 1 || b == 1 || c == 1 || d == 1)
{
printf("電腦贏了\n");
return 1;
}
else if (a == 2 || b == 2 || c == 2 || d == 2)
{
printf("你贏了\n");
return 1;
}
else
{
return 2;
}
}
else
{
printf("平局\n");
return 0;
}
}
//雙人
int is_win2(char board[ROW][COL], int row, int col, int* ret1, int* ret2, char ret)
{
int a = Col_win(board, row, col, ret1, ret);
int b = Row_win(board, row, col, ret2, ret);
int c = Dia1_win(board, row, col, ret1, ret2, ret);
int d = Dia2_win(board, row, col, ret1, ret2, ret);
int e = is_full(board, row, col);
if (e == 0)
{
if (a == 1 || b == 1 || c == 1 || d == 1)
{
printf("B贏了\n");
return 1;
}
else if (a == 2 || b == 2 || c == 2 || d == 2)
{
printf("A贏了\n");
return 1;
}
else
{
return 2;
}
}
else
{
printf("平局\n");
return 0;
}
}
到了這里,關(guān)于C語言實現(xiàn)五子棋小游戲(內(nèi)附源碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!