七步手把手教你实现三子棋(c语言)
C语言实现三子棋
一. 整体思路
首先第一步 我们试着创建三个工程文件
test.c 它的作用是帮助我们来测试我们的代码是否可以运行
game.h 用来声明我们的函数
game.c 用于函数的实现
然后呢 我们要在开始玩游戏之前 创建一个菜单 这个菜单要有以下的功能
1 要让我们可以选择游玩和退出
2 要可以多次游玩
当然啦 如果大家想到了什么有意思的功能也可以加上去
二. 创建菜单
实现功能
1 要让我们可以选择游玩和退出
2 要可以多次游玩
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("---------------------------------------\n");
printf("-------- 1.游戏开始 -----------\n");
printf("-------- 0.游戏结束 -----------\n");
printf("---------------------------------------\n");
}
上面这段代码其实挺有意思的
通过这里我们能获取到两个知识点
第一点
我们使用了printf函数但是却没有include它的头文件 这是为什么捏
玄机就在于上面的game.h上
在game.h文件里面 我们已经include了我们游戏内所需要的几个头文件 所以说这里只需要导入下 game.h就好啦
是不是很神奇
第二点
我们让玩家输入1来开始游戏 0来结束游戏 这样在我们使用while循环的时候如果玩家想玩游戏就可以一直循环啦
如果不想玩游戏 只要输入一个0就可以退出啦 又是一个小细节
代码如下
void menu()
{
printf("---------------------------------------\n");
printf("-------- 1.游戏开始 -----------\n");
printf("-------- 0.游戏结束 -----------\n");
printf("---------------------------------------\n");
}
int main()
{
int input = 0;
do
{
menu();
scanf("%d\n", &input);
} while (input);
}
我们先来看看效果嗷
咦 好像看上去实现的不错 但是呢 这里有一个小bug就是如果输入2 3 4这些值呢 它也会进入循环 因为除
0以外的所有数字都为真嘛
那我们就在下一个章节来解决掉这些可能出现的bug。
三. 调试菜单(解决一些bug 完善功能)
当我们选择1或者0的时候 不能光看着它打印菜单吧 那这个游戏也太无聊啦
那么我们来写个switch case语句来将我们选择的功能进行下去
switch (input)
{
case 1:
break;
case 0:
break;
default:
break;
}
这样子就看上去舒服多啦
然后我们试着给每一个选项加上功能
实现代码如下
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误 请重新输入\n");
break;
}
看看调试结果怎么样
不错不错 运行的很好
那么到目前为止我们就完成菜单的功能啦
接下来让我们开始设计游戏
四. 设计游戏(棋盘)
我们说 在下棋的时候想要在上面这样一个棋盘里面来进行游戏
看上去很简单嘛 只需要设计一个3x3的数组 然后再用这样的格式将棋盘包裹再里面就好啦
按照这个思路 我们首先来设计一个3x3的数组
再game.h的头文件里面先定义一个行和列 这样子就可以直接用定义的符号来表示啦
代码如下
char board[3][3] = {0};
void init(char board[row][col], int x, int y)
{
int i = 0;
for ( i = 0; i < x; i++)
{
int j = 0;
for ( j = 0; j < y; j++)
{
board[i][j] == ' ';
}
}
}
我们 试着将它打印出来
咦 形状有点奇怪
我们仔细分析下 怎么每一行之间只打印了两个空格的数据
在我们上一篇文章里 已经详细说明了 ‘\0’的ascll码值是0 这也就是为什么没有将%c打印出来的原因
知道这个原因之后 后面就容易多了 我们将数组初始化成空格就可以
初始化代码如下
void init(char board[row][col], int x, int y)
{
int i = 0;
for ( i = 0; i < x; i++)
{
int j = 0;
for ( j = 0; j < y; j++)
{
board[i][j] = ' ';
}
}
}
我们发现 这样子打印出来的代码就好看多了
但是呢 这样子还有几个问题
下面最后一行应该是不打印的 那我们再修改下代码
printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
if (i<x-1)
{
printf("---|---|---\n");
}
这样子修改之后看着就舒服多啦
五. 设计游戏(玩家)
这一步要来设计玩家的行动
我们可以假设玩家使用的棋子是‘*’号 电脑使用的棋子是‘#’号 玩家的每一步都要下在九宫格里面
如果下的位置有棋子已经落了 那么就要提醒玩家重新落子
这里有一点特别要注意!!!
因为玩家有可能并不是程序员 所以我们在设计输入坐标的时候 要加一才可以
代码表示如下
void player_move(char board[row][col], int x, int y)
{
int i = 0;
int j = 0;
// 判断坐标合法性
// 判断坐标是否被占用
while (1)
{
printf("玩家下棋->\n");
scanf("%d %d", &i, &j);
if ((i >= 1 && i <= 3) && (j >= 1 && j <= 3))
{
if (board[i-1][j-1] == ' ')
{
board[i-1][j-1] = '*';
break;
}
else
{
printf("坐标被占用 请重新输入\n");
}
}
else
{
printf("坐标不合法 请重新输入\n");
}
}
五. 设计游戏(电脑)
这里我们的电脑就设计的简单一点 让他随机下期就好啦
随机的x y坐标 判断合法性
然后落子
关于如何实现随机数 可以参考下我的这篇文章
完整电脑下棋代码如下
void computer_move(char board[row][col], int x, int y)
{
printf("电脑下棋->\n");
while (1)
{
int i = rand() % x;
int j = rand() % y;
if (board[i][j] == ' ')
{
board[i][j] = '#';
break;
}
}
}
六. 判断胜利条件以及结束条件
我们可以设定一个参数 ret
当ret返回‘*’时 玩家获胜
当ret返回‘#’时 电脑获胜
当ret返回‘Q’时 游戏结束
当ret返回‘C’时 游戏继续
代码如下
char is_win(char board[row][col], int x, int y)
{
int i = 0;
for ( i = 0; i < x; 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 < y; 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,row,col)==1)
{
return 'q';
}
else
{
return 'c';
}
}
static int is_full(char board[row][col], int x, int y)
{
int i = 0;
for (size_t i = 0; i < x; i++)
{
int j = 0;
for (size_t j = 0; j < y; j++)
{
if (' ' == board[i][j])
{
return 0;
}
}
}
return 1;
}
七. 总结常见错误
1错误1:数据类型出错
例如本来要传输的是char 类型的数组 传递成了int 类型的数组导致出错错误2:传递参数出错
例如要传递一个数组的地址作为参数 而自己却传递了一个数组元素board[i][j]过去 导致出错错误3:形参类型未定义或者与define定义的常量冲突
例如在定义函数数据类型时 使用define定义的row col 或者是不定义变量类型 导致出错
实现的效果图如下
以上就是本期博客的全部内容啦
由于博主的知识浅薄 难免会出现一些纰漏 发现错误欢迎大佬在评论区或者私信指正~