test.c(测试游戏的逻辑)
game.h(关于游戏相关的函数声明符号声明)头文件包含的
game.c游戏相关函数的实现
游戏如何玩
希望游戏玩完一把还可以继续玩/*
用dowhile形式 (无论如何都会进去一次 打印一个菜单)
void menu()
{
printf("***************************\n");
printf("********* 1.play ********\n");
printf("********* 0.exit *******\n");
printf("***************************\n");
}
int main()/*希望游戏玩完一把还可以继续玩*/
{
do
{
menu();
} while ();
return 0;
}
//上面代码的意思就是按下运行后会在屏幕上打印一个菜单 菜单的内容就是printf的里 像一个图案。
打印完字符 给用户一个反馈 让用户知道要干嘛 然后用户要选择 1 还是2 所以用scanf接收
int main()/*希望游戏玩完一把还可以继续玩*/
{
do
{
int input = 0;
menu();
printf("请选择");
scanf("%d",&input)//比如用户选择1 输入了1这个scanf就起到了接受的作用,input就是把选择的值存起来
} while ();
return 0;
}
然后根据他选的值作出反应 下面代码如下
int main()/*希望游戏玩完一把还可以继续玩*/
{
int input = 0;
do
{
menu();
printf("请选择");
scanf("%d", &input);
switch (input)
{
case 1://选择1做出的反应
printf("三子棋游戏\n");
break;
case 0:
printf("退出游戏\n");
break;
default://如果选择的不是0也不是1,会跑到这里
printf("输入错误,重新选择\n");
break;
}//break 跳出的是switch语句会来到这里 执行下面的
} while (input);//不管做了哪种选择最后这里进行判断放入input。解析为啥input 因为如果选择1 玩完后break跳出来 下面while(1)又执行一遍 我们的玩完还想玩目的就达到了。直到选择0while(0)为假跳出来
return 0;
}
default作用如下
**解析为啥input 因为如果选择1 玩完后break跳出来 下面while(1)又执行一遍 我们的玩完还想玩目的就达到了。直到选择0while(0)为假跳出来
**
完成了初步接下来我们就可以来进入三子棋了 用到game函数 放到case1下 调用下函数, 函数实现还得main在上面
voidgame 不需要返回 里边只要是三子棋运行逻辑就行三子棋都在这里完成
game函数实现分析如下
根据我们的运行结果可以得出如下
一个字也没下的时候是这样的
**
1.玩家下一个电脑下一个 发现玩家下完电脑下的时候 玩家的旗子还在 还有记录 电脑玩家同理
2.下完之后要记录 由图可以看出我们这是一个3×3的格子,所以我们可以用一个3×3的二维数组来记录
** 3.没有落子的时候是空的所以是空格 玩家落子给*号电脑落子给#号
#define _CRT_SECURE_NO_WARNINGS 1
#include //游戏如何玩
void game()
{
//游戏的运行需要存储数据 所以用到了二维数组 二维数组的创建用到了char因为游戏的实现用到的都是字符 *#类似的
char board[3][3]//board是自己定义的 我用了board是为了更容易理解
**3×3可能不够 用了就得改比较麻烦 关于棋盘大小是游戏的一些属性了所以咱们直接写到game.h里**
}
void menu()
{
printf("***************************\n");
printf("********* 1.play ********\n");
printf("********* 0.exit *******\n");
printf("***************************\n");
}
int main()/*希望游戏玩完一把还可以继续玩*/
{
int input = 0;
do
{
menu();
printf("请选择");
scanf("%d", &input);
switch (input)
{
case 1://选择1做出的反应
game();//把之前的删了是因为之前放那个更好理解
break;
case 0:
printf("退出游戏\n");
break;
default://如果选择的不是0也不是1,会跑到这里
printf("输入错误,重新选择\n");
break;
}//break 跳出的是switch语句会来到这里 执行下面的
} while (input);//不管做了哪种选择最后这里进行判断放入input. 解析为啥input 因为如果选择1 玩完后break跳出来 下面while(1)又执行一遍 我们的玩完还想玩目的就达到了。直到选择0while(0)为假跳出来
return 0;
}
game.h下放这两个
#pragma once
#define ROW 3//define 定义符号 这两个符号是行和列的意思
#define COL 3
因为刚刚的头文件 然后我们这里可以直接引用 如果要做修改可以在我们创建的game.h里修改 这样写的好处有利于后续的更改 比如想玩5子棋直接改头文件ROW LOC就行就不需要动用其他的 。头文件还有一个好处就是只要谁想用都可以直接调用
报错是因为没有引用 如下
有我们的最终结果运行图可以看出来用到了很多的空格
所以我们先打印一个全都是空格的
直接放到函数里实现 定义initboard()如下:
void game()
{
//游戏的运行需要存储数据 所以用到了二维数组 二维数组的创建用到了char因为游戏的实现用到的都是字符 *#类似的
char board[ROW][COL];//board是自己定义的 我用了board是为了更容易理解
InitBoard(board,ROW,COL);//因为这个函数要初始化上面的棋盘 所以传过去 二维数组。
//因为不知道几行几列所以rowcol一块传过去. 这个初始化棋盘 属于游戏模块 放到game.h中实现
}
#pragma once
//符号的定义
#define ROW 3//define 定义符号 这两个符号是行和列的意思
#define COL 3
//函数的声明
//InitBoard(board, ROW, COL) 这个单独拿过来做对比 因为之前传三个 ,声明的时候也需要三个
//下面是初始化棋盘函数
void InitBoard(char board[ROW][COL], int row, int col);//第一个数组 交代数组行和列。 第二三个行和列 接收真实传递给他的行和列
//上面函数写完了要实现 去game.c里实现
接下来在game.h中实现给数组的每个元素初始化成空格 代码如下:
初始化棋盘函数
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)//row是行
{
for (j = 0; j < col; j++)
{
//原理 如果他们真的传过来3 3 这里是访问三行三列的元素 每个元素都会被初始化为空格
board[i][j] = ' ';//
}
}
}
打印棋盘本质上是打印数组内容
因为打印数组所以要把数组内容传过去
打印棋盘就出现,然后去game.h中声明
打印完也需要实现 区game.c中实现
函数是放在头文件定义 而在函数里边进行相应的实现
打印这样一个棋盘
紫色圈起来的 打印方法—|—|—
红色也就是第一个方法空格%c一个空格。一个字符一个空格然后| 大概原理就是这样 ,一行数据一行分割看成一组
实现如下
void DisplayBoard(char board[ROW][COL], 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]);
printf("---|---|---\n");
}
}
运行一下 发现不行因为没有引用头文件 stdio 咱们直接在头文件中引用就可以了
————————————————————————
打印下看看目前进度
发现多了一行 接下来演示控制代码不打印最后一行
打印中如果遇见这种情况 是因为你没有初始化棋盘格(初始化空格)
void InitBoard(char board[ROW][COL],int row, int col);
如果我们需一个不是3行3列的棋盘格如下
显然这样打印出来不太合适,所以需要改造下代码让他通用起来
把每一行数据加一个竖杠作为一个
分割行如何处理如下
printf(“—|—|—\n”)这一行拆开
if (i < row - 1)
/*printf("---|---|---\n");*///这一行的打印不是总打印 可以给个判断
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if(j<col-1)
printf("|");//这个再打印的时候不是同时打印的 所以加上循环
}
printf("\n");//从j=0这一行打印完换行
}
玩家输入11的时候其实代表数组为00
发现打印之后不能看到 解决如下
把打印的代码在主函数内部复制下就可以
void PlayerMove(char board[ROW][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)//对于玩家来说行列从1开始 所以这样写
{
//下棋 首先判断坐标有没有被占用.判断的方法就是没有被占用的时候里面是空格
if (board[x - 1][y - 1] == ' ')//玩家输入11的时候其实代表数组为00 所以xy减去1
{
board[x - 1][y - 1] = '*';//玩家下棋放一颗星号 这时候玩家下棋了 所以break跳出
break;
}
else
{
printf("坐标被占用,请重新输入\n");//如果已经不是空格了
}
}
else
{
printf("坐标非法,请重新输入!\n");
}
}
}
电脑怎么下棋 让他随机下
**里边用到了rand随机数函数 rand在生成坐标前要调用 srand 因为他在整个代码里只需要执行一次所以放到main函数里 因为main函数只会执行一次 **
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑走:>\n");
//电脑怎么 走 第一步生成坐标
int x = rand();
int y = rand();
}
srand((unsigned int)time(NULL));//用time函数返回值作为随机数的生成器 time函数调用的时候传一个空指针。返回类型强制转换为
srand和time函数需要头文件 引用到 game.h就可以
接下来就可以设置随机数了
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑走:>\n");
//电脑怎么 走 第一步生成坐标
while (1)
{
int x = rand() % row;
int y = rand() % col;//模上谁得到谁
//判断落子
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
没有输赢是不完整的如下
四种状态
IsWin 用来判断游戏的状态
代码实现
判断输赢还是的看数组里边有没有三个相连的,所以其实还是要传参过去
以下图一可以写成图二
接下来写 iswin
接下来在game.c里实现
char IsWin(char board[ROW][COL], 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][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];
}
}
}
char IsWin(char board[ROW][COL], 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][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];
}
//判断平局(判断棋盘是否满了)满没满就看有没有空格了一个空格也没了那他就满了
int ret =IsFull(board, row, col);//如果棋盘满了返回一 不满返回0 平局返回q
if (ret == 1)
{
return 'Q';
}
//如果都没有 那就继续继续返回C
return 'C';
}
接下在这个函数上边实现isfull函数
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;//棋盘满了
}
如果有人需要完整版源码联系我我会发出来