一,游戏的基本框架
游戏中有人机,双人两种模式。五子棋作为一个平面游戏,很明显用二维数组来写最合适不过。为了让代码看起来更有条理,我们用三个.c文件,分别是:text.c 用来测试我们的游戏;game.c 游戏功能的实现;is_win.c 判断输赢的版块。另外,还有一个game.h 文件来放我们的函数声明和头文件。
二 、主函数的设计
主函数的主要逻辑我们用switch,case语句来实现,为了能够在选择错误后重新选择,我们在switch 语句外层又嵌套了do while语句来实现循环,且循环终止条件就是游戏的退出的条件,代码如下:
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()表示双人模式。
三、重要功能设计
3.1 游戏界面的设计
代码如下:
void menu()
{
printf("*************************\n");
printf("*****1.人机 2.双人*****\n");
printf("******** 0.退出 ********\n");
printf("*************************\n");
}
3.2棋盘的初始化
上面我们提到“五子棋作为一个平面游戏,很明显用二维数组来写最合适不过”因此,我们定义一个行为ROW,列为COL的二维数组,并将其初始化为’ ',代码如下:
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] = ' ';
}
}
}
代码运行结果如图:
3.3棋盘的设计
如图,这是我们想要的棋盘设计结果
我们先打印“ %c ”,再打印“ | ”,利用for循环完成一行的打印,这里我们要注意的是:当打印完每行最后一个“ %c”时,是不需要再次打印“ | ”的,因此在这里我们加一个if语句进行判断,当j<col-1时才进行“ | ”的打印。
代码如下:
for (int j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
当每打印完上述的一行后,我们进行换行后,打印“—|”,再次利用for循环进行一行的打印,在这里也要注意当进行一行的最后一次打印时我们只需要打印“—”,因此在这里我们需要加一个if,else 的判断语句,代码如下:
printf("\n");
for (int i = 0; i < col; i++)
{
if (i < col - 1)
{
printf("---|");
}
else
{
printf("---");
}
}
最后我们再用一个for循环进行多行的打印,完整代码如下:
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 玩家下棋
玩家输入坐标,在这里要注意的是玩家输入的坐标减一才是我们二维数组的下标。
scanf("%d%d", &x, &y);
i = x - 1;
j = y - 1;
当输入坐标后,我们要进行坐标的合理性判断:1.所输入坐标是否超出棋盘范围;2.所输入坐标是否已被占用。如果所输入坐标合理,则将坐标位置赋予一定的字符(本游戏中,在人机对战中,玩家所下为**‘’,在双人对战中,玩家一所下为‘’,玩家二为‘#’**);若坐标不合理,则提示后重新输入。
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("此坐标已经被占用,请重新下:\n");
}
else
{
board[i][j] = '*';
int ret = is_win(board, ROW, COL, &i, &j, '*');
return ret;
}
}
else
{
printf("非法坐标,请重新下:\n");
}
}
}
运行结果:
3.5 电脑下棋
电脑下棋我们采用的是通过随机数函数生成合理坐标,然后进行下棋(电脑所下为**‘#’**)。这里要注意的就是随机函数srand(),必须与srand()函数,时间戳搭配使用,且srand()函数只能调用一次,我们在主函数中进行调用。
int main()
{
srand((unsigned int)time(NULL))//srand()函数的调用;
//由于srand函数的参数为无符号数,因此要将时间戳(time函数)的返回值类型强转化为无符号数。
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;
}
}
}
运行结果:
3.6 胜负判断
3.6.1 行的判断
我们通过所下的坐标来找到当前行的最左端,然后对这一行进行遍历,如果发现了有五个连续且一样的字符,则获胜。代码如下:
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 列的判断
与上述行的判断一样,我们通过所下的坐标来找到当前列的最上端,然后对这一行进行遍历,如果发现了有五个连续且一样的字符,则获胜。代码如下:
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 对角的判断
通过所下的坐标来找到当前对角的端点,对对角进行遍历,若有五个连续且相同的字符,则获胜。
代码如下;
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 判断平局
我们将整个二维数组遍历一遍,在没有获胜的前提下,若没有发现**‘ ’,则证明棋盘已下满——平局;若发现了‘ ’**,则继续游戏。代码如下:文章来源:https://www.toymoban.com/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文件
此文件里主要是一些函数声明,头文件和宏定义。文章来源地址https://www.toymoban.com/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("此坐标已经被占用,请重新下:\n");
}
else
{
board[i][j] = '*';
int ret = is_win(board, ROW, COL, &i, &j, '*');
return ret;
//break;
}
}
else
{
printf("非法坐标,请重新下:\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("此坐标已经被占用,请重新下:\n");
}
else
{
board[i][j] = '*';
int ret = is_win2(board, ROW, COL, &i, &j, '*');
return ret;
//break;
}
}
else
{
printf("非法坐标,请重新下:\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("此坐标已经被占用,请重新下:\n");
}
else
{
board[i][j] = '#';
int ret = is_win2(board, ROW, COL, &i, &j, '#');
return ret;
//break;
}
}
else
{
printf("非法坐标,请重新下:\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;
}
}
到了这里,关于C语言实现五子棋小游戏(内附源码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!