重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线就视为胜利,而对方就算输了,但是三子棋在很多时候会出现和棋的局面。
相信大家都玩过三子棋,那既然学习了C语言,有没有想亲手写一个呢?自己写的可能也会更有趣吧,快付出行动吧,我们一起完成三子棋代码的书写。
先让我们看看完成的效果图,来确定我们的目标任务。
二、代码的整体框架我们完成一个程序前要建立一个框架,main函数放在test.c文件中并且对游戏需要的函数进行引用,实现游戏的各种功能的函数全部在game.c文件中完成。game.h文件中包含了程序所需的各种头文件并且包换对实现游戏功能的各种函数的声明。
在本次游戏设计中,为什么使用了3个文件难道不能放在一个文件中呢?
三子棋的实现需要多个模块的功能相互串联,多个文件可以分别处理各自模块的功能,能更好处理各个模块之间的逻辑并且便于后期调试,也使得代码的可读性提高。所以在写一个长的代码时,我们要提前建立一个框架,不仅是为了别人读懂,也是为了后面进行维护和更新提供便利,还可以培养我们对日常生活中一些事情的由繁化简的思维。希望大家都养成这种良好的习惯。
三、实现三子棋的各种功能和逻辑的串联 3.1创建初始界面(进行玩家选择)打印菜单并且对游戏进行难度选择
void menu1()
{printf("*********************************\n");
printf("****** 1. 开始游戏 *****\n");
printf("****** 0. 退出游戏 *****\n");
printf("*********************************\n");
}
void menu2()
{printf("**************************************\n");
printf("****** 1.玩家vs电脑(傻瓜版)********\n");
printf("****** 2.玩家vs玩家 ********\n");
printf("****** 3.玩家vs电脑(智能版)********\n");
printf("**************************************\n");
}
void game1()
{}
void game2()
{}
void game3()
{}
int main()
{int input1 = 0;
int input2 = 0;
srand((unsigned int)time(NULL));
do
{menu1();
printf("请选择:>");
scanf("%d", &input1);
menu2();
printf("请选择:>");
scanf("%d", &input2);
switch (input1)
{case 1:
if (1 == input2)
{ game1();
}
else if (2 == input2)
{ game2();
}
else if (3 == input2)
{ game3();
}
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (input1);
return 0;
}
3.2棋盘的初始化和棋盘的搭建运行效果图
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 DisplayBoard(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++)
{ printf(" %c ", board[i][j]);
if (j< col - 1)
printf("|");
}
printf("\n");
if (i< row - 1)
{ int j = 0;
for (j = 0; j< col; j++)
{ printf("---");
if (j< col - 1)
printf("|");
}
printf("\n");
}
}
}
void game1()
{//存储数据 - 二维数组
char board[ROW][COL];
//初始化棋盘 - 初始化空格
InitBoard(board, ROW, COL);
//打印一下棋盘 - 本质是打印数组的内容
DisplayBoard(board, ROW, COL);
}
void game2()
{//存储数据 - 二维数组
char board[ROW][COL];
//初始化棋盘 - 初始化空格
InitBoard(board, ROW, COL);
//打印一下棋盘 - 本质是打印数组的内容
DisplayBoard(board, ROW, COL);
}
void game3()
{//存储数据 - 二维数组
char board[ROW][COL];
//初始化棋盘 - 初始化空格
InitBoard(board, ROW, COL);
//打印一下棋盘 - 本质是打印数组的内容
DisplayBoard(board, ROW, COL);
}
3.3玩家下棋运行效果图
void PlayerMove1(char board[][COL], int row, int col)
{int x = 0;
int y = 0;
printf("玩家走:>\n");
while (1)
{printf("请输入下棋的坐标:>");
scanf("%d %d", &x, &y);
//判断坐标合法性
if (x >= 1 && x<= row && y >= 1 && y<= col)
{ //下棋
//坐标是否被占用
if (board[x - 1][y - 1] == ' ')
{ board[x - 1][y - 1] = '*';
break;
}
else
{ printf("坐标被占用, 请重新输入\n");
}
}
else
{ printf("坐标非法, 请重新输入\n");
}
}
}
3.4电脑下棋运行效果图
void ComputerMove1(char board[ROW][COL], int row, int col)
{printf("电脑走:>\n");
int x = 0;
int y = 0;
while (1)
{x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{ board[x][y] = '#';
break;
}
}
}
3.5电脑的智能下棋运行效果图
int IntelligentComputerMove(char board[ROW][COL], int row, int col, char ch)//ch为'#'进行下棋,ch为'*'进行堵截
{//检查电脑能否获得胜利/堵截玩家
int i = 0;
//电脑对行的智能堵截
for (i = 0; i< row; i++)
{int j = 0;
for (j = 0; j< col; j++)
{ if (board[i][0] == board[i][1] && board[i][0] == ch && board[i][2] == ' ')
{ board[i][2] = '#';
return 1;
}
if (board[i][0] == board[i][2] && board[i][0] == ch && board[i][1] == ' ')
{ board[i][1] = '#';
return 1;
}
if (board[i][1] == board[i][2] && board[i][1] == ch && board[i][0] == ' ')
{ board[i][0] = '#';
return 1;
}
}
}
//电脑对列的智能堵截
for (i = 0; i< row; i++)
{int j = 0;
for (j = 0; j< col; j++)
{ if (board[0][j] == board[1][j] && board[0][j] == ch && board[2][j] == ' ')
{ board[2][j] = '#';
return 1;
}
if (board[0][j] == board[2][j] && board[0][j] == ch && board[1][j] == ' ')
{ board[1][j] = '#';
return 1;
}
if (board[1][j] == board[2][j] && board[1][j] == ch && board[0][j] == ' ')
{ board[0][j] = '#';
return 1;
}
}
}
//电脑对主对角线的智能堵截
if (board[0][0] == board[1][1] && board[1][1] == ch && board[2][2] == ' ')
{board[2][2] = '#';
return 1;
}
if (board[0][0] == board[2][2] && board[0][0] == ch && board[1][1] == ' ')
{board[1][1] = '#';
return 1;
}
if (board[1][1] == board[2][2] && board[1][1] == ch && board[0][0] == ' ')
{board[0][0] = '#';
return 1;
}
//电脑对副对角线的智能堵截
if (board[0][2] == board[1][1] && board[0][2] == ch && board[2][0] == ' ')
{board[2][0] = '#';
return 1;
}
if (board[0][2] == board[2][0] && board[0][2] == ch && board[1][1] == ' ')
{board[1][1] = '#';
return 1;
}
if (board[1][1] == board[2][0] && board[1][1] == ch && board[0][2] == ' ')
{board[0][2] = '#';
return 1;
}
return 0;//若电脑无法赢棋或无法自动,则返回0
}
void ComputerMove2(char board[ROW][COL], int row, int col)
{printf("电脑走:>\n");
int flag1 = 0;
int flag2 = 0;
flag1 = IntelligentComputerMove(board, ROW, COL, '#');//电脑智能赢棋
if (flag1 == 0)//若电脑无法赢棋,则进行阻拦
{flag2 = IntelligentComputerMove(board, ROW, COL, '*');//电脑智能堵截
if (flag2 == 0)//若赢棋和自动都不满足,电脑自动下棋
{ int x = 0;
int y = 0;
while (1)
{ x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{board[x][y] = '#';
break;
}
}
}
}
}
3.6判断输赢并打印运行效果图
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;
//棋盘满了
}
char IsWin(char board[ROW][COL], int row, int col)//1. 玩家赢了 - *//2. 电脑赢了 - #//3. 平局 - Q//4. 游戏继续 - C
{int i = 0;
//判断三行
for (i = 0; i< row; i++)
{if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{ return board[i][1];
//
}
}
//判断三列
for (i = 0; i< col; i++)
{if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{ return board[1][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];
} //判断平局
//如果棋盘满了返回1, 不满返回0
int ret = IsFull(board, row, col);
if (ret == 1)
{return 'Q';
}
return 'C';
}
运行效果图
四、完整代码建议大家也像这样写完一个函数的功能运行一下,能及时发现程序是否可以完成我们的目的,别等到代码写完再找就难了。
game.h —— 包含了程序所需的各种头文件并且包换对实现游戏功能的各种函数的声明
//头文件的包含
#include#include#include//符号的定义
#define ROW 3
#define COL 3
//函数的声明
//初始化棋盘的
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘的函数
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerMove1(char board[ROW][COL], int row, int col);
void PlayerMove2(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove1(char board[ROW][COL], int row, int col);
void ComputerMove2(char board[ROW][COL], int row, int col);
智能电脑下棋
static int IntelligentComputerMove(char board[ROW][COL], int row, int col, char ch);
//判断游戏是否有输赢
char IsWin(char board[ROW][COL], int row, int col);
test.c —— 对游戏需要的函数进行引用
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu1()
{printf("*********************************\n");
printf("****** 1. 开始游戏 *****\n");
printf("****** 0. 退出游戏 *****\n");
printf("*********************************\n");
}
void menu2()
{printf("**************************************\n");
printf("****** 1.玩家vs电脑(傻瓜版)********\n");
printf("****** 2.玩家vs玩家 ********\n");
printf("****** 3.玩家vs电脑(智能版)********\n");
printf("**************************************\n");
}
void game1()
{//存储数据 - 二维数组
char board[ROW][COL];
//初始化棋盘 - 初始化空格
InitBoard(board, ROW, COL);
//打印一下棋盘 - 本质是打印数组的内容
DisplayBoard(board, ROW, COL);
char ret = 0;
//接受游戏状态
while (1)
{//玩家下棋
PlayerMove1(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断玩家是否赢得游戏
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
//电脑下棋
ComputerMove1(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断电脑是否赢得游戏
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
{printf("玩家赢了\n");
}
else if(ret == '#')
{printf("电脑赢了\n");
}
else
{printf("平局\n");
}
DisplayBoard(board, ROW, COL);
}
void game2()
{//存储数据 - 二维数组
char board[ROW][COL];
//初始化棋盘 - 初始化空格
InitBoard(board, ROW, COL);
//打印一下棋盘 - 本质是打印数组的内容
DisplayBoard(board, ROW, COL);
char ret = 0;
//接受游戏状态
while (1)
{//玩家下棋
PlayerMove1(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断玩家是否赢得游戏
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
//玩家2下棋
PlayerMove2(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断是否赢得游戏
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
{printf("玩家1赢了\n");
}
else if (ret == '#')
{printf("玩家2赢了\n");
}
else
{printf("平局\n");
}
DisplayBoard(board, ROW, COL);
}
void game3()
{//存储数据 - 二维数组
char board[ROW][COL];
//初始化棋盘 - 初始化空格
InitBoard(board, ROW, COL);
//打印一下棋盘 - 本质是打印数组的内容
DisplayBoard(board, ROW, COL);
char ret = 0;
//接受游戏状态
while (1)
{//玩家1下棋
PlayerMove1(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断玩家是否赢得游戏
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
//电脑下棋
ComputerMove2(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断电脑是否赢得游戏
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
{printf("玩家赢了\n");
}
else if (ret == '#')
{printf("电脑赢了\n");
}
else
{printf("平局\n");
}
DisplayBoard(board, ROW, COL);
}
int main()
{int input1 = 0;
int input2 = 0;
srand((unsigned int)time(NULL));
do
{menu1();
printf("请选择:>");
scanf("%d", &input1);
menu2();
printf("请选择:>");
scanf("%d", &input2);
switch (input1)
{case 1:
if (1 == input2)
{ game1();
}
else if(2 == input2)
{ game2();
}
else if (3 == input2)
{ game3();
}
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (input1);
return 0;
}
game.c —— 实现游戏的各种功能的函数
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
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 DisplayBoard(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++)
{ printf(" %c ", board[i][j]);
if(j int j = 0;
for (j = 0; j< col; j++)
{ printf("---");
if(jint x = 0;
int y = 0;
printf("玩家走:>\n");
while (1)
{printf("请输入下棋的坐标:>");
scanf("%d %d", &x, &y);
//判断坐标合法性
if (x >= 1 && x<= row && y >= 1 && y<= col)
{ //下棋
//坐标是否被占用
if (board[x - 1][y - 1] == ' ')
{ board[x - 1][y - 1] = '*';
break;
}
else
{ printf("坐标被占用, 请重新输入\n");
}
}
else
{ printf("坐标非法, 请重新输入\n");
}
}
}
void PlayerMove2(char board[][COL], int row, int col)
{int x = 0;
int y = 0;
printf("玩家2走:>\n");
while (1)
{printf("请输入下棋的坐标:>");
scanf("%d %d", &x, &y);
//判断坐标合法性
if (x >= 1 && x<= row && y >= 1 && y<= col)
{ //下棋
//坐标是否被占用
if (board[x - 1][y - 1] == ' ')
{ board[x - 1][y - 1] = '#';
break;
}
else
{ printf("坐标被占用, 请重新输入\n");
}
}
else
{ printf("坐标非法, 请重新输入\n");
}
}
}
void ComputerMove1(char board[ROW][COL], int row, int col)
{printf("电脑走:>\n");
int x = 0;
int y = 0;
while (1)
{x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{ board[x][y] = '#';
break;
}
}
}
int IntelligentComputerMove(char board[ROW][COL], int row, int col, char ch)//ch为'#'进行下棋,ch为'*'进行堵截
{//检查电脑能否获得胜利/堵截玩家
int i = 0;
//电脑对行的智能堵截
for (i = 0; i< row; i++)
{int j = 0;
for (j = 0; j< col; j++)
{ if (board[i][0] == board[i][1] && board[i][0] == ch && board[i][2] == ' ')
{ board[i][2] = '#';
return 1;
}
if (board[i][0] == board[i][2] && board[i][0] == ch && board[i][1] == ' ')
{ board[i][1] = '#';
return 1;
}
if (board[i][1] == board[i][2] && board[i][1] == ch && board[i][0] == ' ')
{ board[i][0] = '#';
return 1;
}
}
}
//电脑对列的智能堵截
for (i = 0; i< row; i++)
{int j = 0;
for (j = 0; j< col; j++)
{ if (board[0][j] == board[1][j] && board[0][j] == ch && board[2][j] == ' ')
{ board[2][j] = '#';
return 1;
}
if (board[0][j] == board[2][j] && board[0][j] == ch && board[1][j] == ' ')
{ board[1][j] = '#';
return 1;
}
if (board[1][j] == board[2][j] && board[1][j] == ch && board[0][j] == ' ')
{ board[0][j] = '#';
return 1;
}
}
}
//电脑对主对角线的智能堵截
if (board[0][0] == board[1][1] && board[1][1] == ch && board[2][2] == ' ')
{board[2][2] = '#';
return 1;
}
if (board[0][0] == board[2][2] && board[0][0] == ch && board[1][1] == ' ')
{board[1][1] = '#';
return 1;
}
if (board[1][1] == board[2][2] && board[1][1] == ch && board[0][0] == ' ')
{board[0][0] = '#';
return 1;
}
//电脑对副对角线的智能堵截
if (board[0][2] == board[1][1] && board[0][2] == ch && board[2][0] == ' ')
{board[2][0] = '#';
return 1;
}
if (board[0][2] == board[2][0] && board[0][2] == ch && board[1][1] == ' ')
{board[1][1] = '#';
return 1;
}
if (board[1][1] == board[2][0] && board[1][1] == ch && board[0][2] == ' ')
{board[0][2] = '#';
return 1;
}
return 0;//若电脑无法赢棋或无法自动,则返回0
}
void ComputerMove2(char board[ROW][COL], int row, int col)
{printf("电脑走:>\n");
int flag1 = 0;
int flag2 = 0;
flag1 = IntelligentComputerMove(board, ROW, COL, '#');//电脑智能赢棋
if (flag1 == 0)//若电脑无法赢棋,则进行阻拦
{flag2 = IntelligentComputerMove(board, ROW, COL, '*');//电脑智能堵截
if (flag2 == 0)//若赢棋和自动都不满足,电脑自动下棋
{ int x = 0;
int y = 0;
while (1)
{ x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{board[x][y] = '#';
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;
//棋盘满了
}
char IsWin(char board[ROW][COL], int row, int col)//1. 玩家赢了 - *//2. 电脑赢了 - #//3. 平局 - Q//4. 游戏继续 - C
{int i = 0;
//判断三行
for (i = 0; i< row; i++)
{if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{ return board[i][1];
//
}
}
//判断三列
for (i = 0; i< col; i++)
{if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{ return board[1][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];
} //判断平局
//如果棋盘满了返回1, 不满返回0
int ret = IsFull(board, row, col);
if (ret == 1)
{return 'Q';
}
return 'C';
}
五、结语以上是我对三子棋游戏的实现,如果时间充足还是要从前到尾看一遍,肯定会有收获的,尽量不要直接跳转到完整代码直接复制!!!如果有大佬感兴趣可以进一步优化。
因本人能力还有待提高,如有错误可以及时指出。感谢大家观看和支持。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧