本篇给大家带来两个玩家对战的五子棋,棋盘大小和玩家所下的棋子可以很容易的更改,读者如有更好的建议,可以在评论区留言
代码模块将分为3个部分,游戏页面逻辑书写写在 test.c 文件中,游戏所需要的声明书写在 game.h 文件中,实现游戏的函数写在 game.c 文件中
如果小伙伴不喜欢该游戏界面,可以自行更改菜单 mnue 函数中的内容
#include "game.h"; //需要用到 game.h 中的声明
void mnue()
{
printf("******************\n");
printf("*** 1.play ***\n");
printf("*** 0.exit ***\n");
printf("******************\n");
}
为了让玩家有更好的游戏体验,游戏玩了一次之后我们可以选择再来一把,或者退出游戏,这里采用 do while 循环
int main()
{
int input = 0;
do
{
//菜单
mnue();
printf("请输入:>");
scanf("%d", &input);
system("cls"); //将屏幕已经打印的内容清理掉,
//需要头文件是 stdlib.h
//用户选择
switch (input)
{
case 1: //用户选择 1 开始游戏,进入到 game 函数中
printf("欢迎来到五子棋,游戏开始\n");
game();
break;
case 0: //用户选择 0 退出游戏
printf("退出游戏\n");
break;
default : //如果选择的不是 1 则需要重新输入
printf("输入错误,请重新输入\n");
break;
}
} while (input); //选择 0 条件不成立会退出循环,已结束游戏
//选择 1 或输入了其他数字,判断为真
//进入循环,打印菜单,让用户重新选择
return 0;
}
用户选择 1 之后来到 game 函数
void game()
{
char ret = 0;
char board[ROW][COL]; //用于存储棋盘落子的信息
init_board(board, ROW, COL); //初始化棋盘落子的信息
//用' '表示还没有落子
print_board(board, ROW, COL); //打印棋盘
//提醒用户本游戏是如何落子
printf("********************\n");
printf("本游戏通过坐标来下棋\n");
printf("********************\n");
//玩家下棋是一个重复的过程
//这里将玩家下棋封装成函数,其中第四个参数用来代表不同的玩家
//每次落子之后,通过函数的返回值,来判断游戏是否结束
while(1)
{
printf("玩家1 请下棋:>");
ret = play_board(board, ROW, COL, PIECE_ONE);
if (ret != 'C')
break;
system("cls");
print_board(board, ROW, COL); //下棋之后,打印棋盘
printf("玩家2 请下棋:>");
ret = play_board(board, ROW, COL, PIECE_TWO);
if (ret != 'C')
break;
system("cls");
print_board(board, ROW, COL); //下棋之后,打印棋盘
}
//判断是谁赢了,以及是否平局
if (ret == PIECE_ONE)
{
printf("恭喜玩家1,获胜\n");
}
else if(ret == PIECE_TWO)
{
printf("恭喜玩家2,获胜\n");
}
else
{
printf("很遗憾,没有决出胜负\n");
}
Sleep(5000); //让输出结果停留 5s 需要的头文件是 windows.h
system("cls");
}
用来存放函数的声明,需要的头文件,以及棋盘的大小和棋子的字符,在该文件可以更改棋盘大小和棋子的符号
#define _CRT_SECURE_NO_WARNINGS 1 //在VS编译器用 scanf 等函数
//需要定义该符号
//需要的包含的头文件
#include
#include
#include
//需要更改棋盘的大小或棋子的符号,改这里就可以了
#define ROW 12 //棋盘的行数
#define COL 15 //棋盘的列数
#define PIECE_ONE '*' //玩家1 的棋子
#define PIECE_TWO '#' //玩家2 的棋子
//初始化
void init_board(int board[ROW][COL], int row, int col);
//打印棋盘
void print_board(char board[ROW][COL], int row, int col);
//玩家下棋,并判断游戏是否结束,用返回值带回判断的结果
//第四个参数通过传递玩家的棋子,用来代表不同的玩家
char play_board(char board[ROW][COL],
int row, int col,
char piece);
棋盘的格子采用空格字符空格的形式
根据棋盘格子的设计,棋盘最初是会打印字符的,为了可以达到视觉的效果,将数组全部初始化成空格
#include "game.h" //需要用到 game.h 中的声明
void init_board(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] = ' ';
}
print_board(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
//打印列号
printf(" "); //为了对齐,打印行号时,会占用两个空格
for (i = 1; i <= COL; i++)
printf(" %x ", i); //因为10以上的数字会占用两个位置
//这里采用十六进制的形式打印
printf("\n");
for (j = 0; j < row; j++)
{
//打印行号
printf("%x ", j + 1); //采用十六进制的形式打印
//打印 * | * | * (这里 * 号表示字符)
for (i = 0; i < col; i++)
{
printf(" %c ", board[j][i]);
//不打印最后一列的竖线
if (i < col - 1)
printf("|");
}
printf("\n");
//为了对齐
printf(" ");
//打印___|___|___ ,最后一行打印 | |
for (i = 0; i < col; i++)
{
//将最后一行的3个下划线换成3个空格
j == row - 1 ? printf(" ") : printf("___");
//不打印最后一列的竖线
if (i < col - 1)
printf("|");
}
printf("\n");
}
}
char play_board(char board[ROW][COL],
int row, int col,
char piece)
{
int x = 0;
int y = 0;
while (1)
{
scanf("%d %d", &x, &y);
//坐标合法
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//坐标是否被占用,玩家并不知道要从 0 开始,所以坐标应当 -1
if (board[x - 1][y - 1] != PIECE_ONE &&
board[x - 1][y - 1] != PIECE_TWO)
{
board[x - 1][y - 1] = piece;
//判断是否结束游戏,注意这里传参传的是调整好的坐标
//最后一个参数是用来代表玩家的
return is_win(board, row, col, x - 1, y - 1, piece);
}
else
{
printf("输入错误,请重新输入:>");
}
}
else
{
printf("坐标非法,请重新输入:>");
}
}
}
玩家在下当前这棵棋子时,如果游戏结束,只可能是包含这棵棋子的横线五颗,竖线五颗,主斜线五颗,以及副斜线五颗
应当注意:在传参时已经将坐标调整为是从 0 开始的
这里我们以横线五颗为例说明,其他只需要改变判断的坐标,其思路是类似的
static char is_win(char board[ROW][COL],
int row, int col,
int x, int y,
char piece)
{
int i = 0;
int j = 0;
int k = 0;
//记录当前棋盘的总棋子数
static int count = 0;
count++;
//判断竖线
for (i = x - 4; i <= x; i++)
{
//坐标越界
if (i < 0 || i + 4 >= row)
continue;
//判断是否有连续相等的五颗
for (j = 0; j < 5; j++)
{
if (board[i + j][y] != piece)
break;
}
//判断是否获胜
if (j == 5)
return piece;
}
//判断横线
for (i = y - 4; i <= y; i++)
{
//坐标越界
if (i < 0 || i + 4 >= col)
continue;
//判断是否有连续相等的五颗
for (j = 0; j < 5; j++)
{
if (board[x][i + j] != piece)
break;
}
//判断是否获胜
if (j == 5)
return piece;
}
//判断正斜线
for (i = x - 4, j = y - 4; i <= x; i++, j++)
{
//坐标越界
if (i < 0 || j < 0 || i + 4 >= row || j + 4 >= col)
continue;
//判断是否有连续相等的五颗
for (k = 0; k < 5; k++)
{
if (board[i + k][j + k] != piece)
break;
}
//判断是否获胜
if (k == 5)
return piece;
}
//判断副斜线
for (i = x + 4, j = y - 4; i <= x; i++)
{
//坐标越界
if (i >= row || j < 0 || i + 4 < 0 || j + 4 >= col)
continue;
//判断是否有连续相等的五颗
for (k = 0; k < 5; k++)
{
if (board[i - k][j + k] != piece)
break;
}
//判断是否获胜
if (k == 5)
return piece;
}
//判断是否平局
if (count == row * col)
return 'Q';
return 'C';
}
test.c 文件
#include "game.h";
void mnue()
{
printf("******************\n");
printf("*** 1.play ***\n");
printf("*** 0.exit ***\n");
printf("******************\n");
}
void game()
{
char ret = 0;
char board[ROW][COL];
init_board(board, ROW, COL); //初始化
print_board(board, ROW, COL); //打印棋盘
printf("********************\n");
printf("本游戏通过坐标来下棋\n");
printf("********************\n");
while(1)
{
printf("玩家1 请下棋:>");
ret = play_board(board, ROW, COL, PIECE_ONE);
if (ret != 'C')
break;
system("cls");
print_board(board, ROW, COL);
printf("玩家2 请下棋:>");
ret = play_board(board, ROW, COL, PIECE_TWO);
if (ret != 'C')
break;
system("cls");
print_board(board, ROW, COL);
}
if (ret == PIECE_ONE)
{
printf("恭喜玩家1,获胜\n");
}
else if(ret == PIECE_TWO)
{
printf("恭喜玩家2,获胜\n");
}
else
{
printf("很遗憾,没有决出胜负\n");
}
Sleep(5000);
system("cls");
}
int main()
{
int input = 0;
do
{
//菜单
mnue();
printf("请输入:>");
scanf("%d", &input);
system("cls");
//用户选择
switch (input)
{
case 1:
printf("欢迎来到五子棋,游戏开始\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default :
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
game.h 文件
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#define ROW 8
#define COL 8
#define PIECE_ONE '*'
#define PIECE_TWO '#'
//初始化
void init_board(int board[ROW][COL], int row, int col);
//打印棋盘
void print_board(char board[ROW][COL], int row, int col);
//玩家下棋,并判断游戏是否结束
char play_board(char board[ROW][COL], int row, int col, char piece);
game.c 文件
#include "game.h"
void init_board(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 print_board(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
//打印列号
printf(" "); //为了对齐
for (i = 1; i <= COL; i++)
printf(" %x ", i);
printf("\n");
for (j = 0; j < row; j++)
{
//打印行号
printf("%x ", j + 1);
//打印 * | * | *
for (i = 0; i < col; i++)
{
printf(" %c ", board[j][i]);
if (i < col - 1)
printf("|");
}
printf("\n");
//为了对齐
printf(" ");
//打印___|___|___ ,最后一行打印 | |
for (i = 0; i < col; i++)
{
j == row - 1 ? printf(" ") : printf("___");
if (i < col - 1)
printf("|");
}
printf("\n");
}
}
static char is_win(char board[ROW][COL], int row, int col, int x, int y, char piece)
{
int i = 0;
int j = 0;
int k = 0;
//记录当前棋盘的总棋子数
static int count = 0;
count++;
//判断竖线
for (i = x - 4; i <= x; i++)
{
if (i < 0 || i + 4 >= row)
continue;
for (j = 0; j < 5; j++)
{
if (board[i + j][y] != piece)
break;
}
//判断是否获胜
if (j == 5)
return piece;
}
//判断横线
for (i = y - 4; i <= y; i++)
{
if (i < 0 || i + 4 >= col)
continue;
for (j = 0; j < 5; j++)
{
if (board[x][i + j] != piece)
break;
}
//判断是否获胜
if (j == 5)
return piece;
}
//判断正斜线
for (i = x - 4, j = y - 4; i <= x; i++, j++)
{
if (i < 0 || j < 0 || i + 4 >= row || j + 4 >= col)
continue;
for (k = 0; k < 5; k++)
{
if (board[i + k][j + k] != piece)
break;
}
//判断是否获胜
if (k == 5)
return piece;
}
//判断副斜线
for (i = x + 4, j = y - 4; i <= x; i++)
{
if (i >= row || j < 0 || i + 4 < 0 || j + 4 >= col)
continue;
for (k = 0; k < 5; k++)
{
if (board[i - k][j + k] != piece)
break;
}
//判断是否获胜
if (k == 5)
return piece;
}
//判断是否平局
if (count == row * col)
return 'Q';
return 'C';
}
char play_board(char board[ROW][COL], int row, int col, char piece)
{
int x = 0;
int y = 0;
while (1)
{
scanf("%d %d", &x, &y);
//坐标合法
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//坐标是否被占用
if (board[x - 1][y - 1] != PIECE_ONE && board[x - 1][y - 1] != PIECE_TWO)
{
board[x - 1][y - 1] = piece;
return is_win(board, row, col, x - 1, y - 1, piece); //判断是否结束游戏
}
else
{
printf("输入错误,请重新输入:>");
}
}
else
{
printf("坐标非法,请重新输入:>");
}
}
}
本代码只提供了两个玩家对战的模式,读者有兴趣可以开发人机对战模式
代码亲测有效,如有建议,可以评论留言