欢迎来到 Claffic 的博客
前言:
三子棋是一种常见的民间传统游戏,游戏为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子走成一条线视为胜利,其背后的逻辑并不难,接下来跟着C用C语言把三子棋写出来,跟电脑对对线可好?
初学C语言的小伙伴放心食用~~~
注意:为了方便,我将代码做了分块,他们分别是:
test.c :main函数所在项,用于整体的运行;
game.c : 实现游戏逻辑的项;
game.h : 声明函数的项.
目录
❤️1.整体框架
2.游戏逻辑
2.1数据的储存
2.2初始化棋盘
2.3打印棋盘
2.4下棋
2.4.1玩家下棋
2.4.2电脑下棋
2.5判断结局
2.5.1判断输赢
2.5.2平局
2.5.3继续
3.最终成果展示
基本框架类似于往期猜数字游戏
进入程序,输入1开始猜数字,输入0退出游戏,此处可用switch-case执行分支;
要使游戏至少能进行一次,可以使用do while循环;
这样可以先写出整体框架:
#define _CRT_SECURE_NO_WARNINGS 1
#include
void menu()
{
printf("********************\n");
printf("* 1.play *\n");
printf("* 0.exit *\n");
printf("********************\n");
}
int main()
{
int input = 0;//input要在do-while体系外
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)//1-真 0-假 可作判断条件
{
case 1:
//game();
printf("三子棋\n");
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);//1-真 0-假 可作判断条件
return 0;
}
运行:
整体框架完。
要实现如下的棋盘
要储存数据,需要一个3*3的数组;
void game()
{
char board[3][3];
}
我们发现初始状态下棋盘内都是空格,这就需要初始化,即把数组中的每个元素改为空格;
void init_board(char board[3][3], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)//初始化行
{
int j = 0;
for (j = 0; j < col; j++)//初始化列
{
board[i][j] = ' ';
}
}
}
前面已经初始化了棋盘,再看一眼我们想要的棋盘
对,接下来要做的就是把那些杠杠(棋盘的边)打印出来:
我们把行中的数据+竖杠记为 1 ,分割行记为 2 ,1 和 2 的组合记为 3 ;
仔细观察可以发现,这些杠杠其实就是两个 3 加一个不带 2 的 3 组成的;
void print_board(char board[3][3], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
printf(" %c | %c | %c \n",board[i][0], board[i][1], board[i][2]);
if(i
运行:
怎么样,是不是得到了完美的棋盘?
下棋 其实就是把棋子( * # )放到初始化后的数组里面.
要输入的是:要下的棋所在空格的坐标
注意:1.坐标不能越界
2.不能用已占用的坐标
3.玩家眼中的坐标和程序员眼中的坐标
第一点:
可以用 if 语句,条件就是 x 和 y 都在 1~3 之间;
第二点:
用 if 语句,判断原来的坐标是否位空格;
第三点:
实现方法其实很简单:
输入的坐标是 (x,y)
实际更改的坐标是(x-1,y-1)
此部分代码如下:
void player_move(char board[3][3], int row, int col)
{
printf("玩家下棋\n");
while (1)
{
printf("请输入坐标:");
int x = 0;
int y = 0;
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 computer_move(char board[3][3], int row, int col)
{
printf("电脑下棋\n");
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
判断输赢的代码要告诉我:玩家赢了?电脑赢了?平局?游戏继续?
像这种多情况的可以各接收一个返回值作为标识;
玩家赢:返回 * ;
电脑赢:返回 # ;
平局:返回 Q ;
游戏继续:返回 C ;
while (1)
{
player_move(board, 3, 3);
print_board(board, 3, 3);
//判断
ret = is_win(board, 3, 3);
if (ret != 'C')
{
break;
}
computer_move(board, 3, 3);
print_board(board, 3, 3);
//判断
ret = is_win(board, 3, 3);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
printf("恭喜你赢了!!!\n");
if(ret=='#')
printf("你输了\n");
if(ret=='Q')
printf("平局\n");
根据规则,赢的情况无非就三种:行,列,对角 三子连珠;
所以可以直接穷举 :
//判断行
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 (is_full(board, 3, 3) == 1)
{
return 'Q';
}
int is_full(char board[3][3], 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;
}
没有玩家或者电脑赢,也没有平局,游戏继续;
末尾返回C即可;
test.c
#include"game.h"
void menu()
{
printf("********************\n");
printf("* 1.play *\n");
printf("* 0.exit *\n");
printf("********************\n");
}
void game()
{
char board[3][3];
init_board(board, 3, 3);
print_board(board, 3, 3);
char ret = 0;
while (1)
{
player_move(board, 3, 3);
print_board(board, 3, 3);
//判断
ret = is_win(board, 3, 3);
if (ret != 'C')
{
break;
}
computer_move(board, 3, 3);
print_board(board, 3, 3);
//判断
ret = is_win(board, 3, 3);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
printf("恭喜你赢了!!!\n");
else if(ret=='#')
printf("你输了\n");
else if(ret=='Q')
printf("平局\n");
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void init_board(char board[3][3], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)//初始化行
{
int j = 0;
for (j = 0; j < col; j++)//初始化列
{
board[i][j] = ' ';
}
}
}
void print_board(char board[3][3], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
printf(" %c | %c | %c \n",board[i][0], board[i][1], board[i][2]);
if(i 1)
{
return;
}
}
void player_move(char board[3][3], int row, int col)
{
printf("玩家下棋\n");
while (1)
{
printf("请输入坐标:");
int x = 0;
int y = 0;
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 computer_move(char board[3][3], int row, int col)
{
printf("电脑下棋\n");
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
}
static int is_full(char board[3][3], 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 is_win(char board[3][3], 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 (is_full(board, 3, 3) == 1)
{
return 'Q';
}
//继续
return 'C';
}
game.h
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
//声明函数
//初始化棋盘
void init_board(char board[3][3], int row, int col);
//打印棋盘
void print_board(char board[3][3], int row, int col);
//玩家下棋
void player_move(char board[3][3], int row, int col);
//电脑下棋
void computer_move(char board[3][3], int row, int col);
//判断输赢
char is_win(char board[3][3], int row, int col);
代码已上传至 我的gitee
如果你觉得这篇文章还不错并且对你有帮助,不妨动动手指点赞收藏加转发,给一个大大的关注
你们的每一次支持都将转化为我前进的动力!!!