三子棋游戏
关于三子棋游戏的实现
- 首先创建项目
打开VS编译器,点击创建新项目。
- 建立所需的源文件和头文件
这里我建立了一个主函数的源文件和一个实现game的源文件以及游戏所需的头文件
大家可以根据自己的需求建立
- 代码的实现和运行结果
首先呢,不管三七二十一我们先把模板扔上去。
3.1然后开始思考实现Trimoku game的第一步该如何实现
我认为一个游戏的最初应该是一个可供用户选择的菜单。
比如这样的一个可供选择的菜单:选择1 开始游戏
选择0 退出游戏
*这里我们要注意:菜单的实现我是单独创建了一个menu()函数,而不是在主函数内部直接实现。这样子我们的代码会看起来更加条理清晰,方便理解和后期的改bug。文章以后所用到的功能我都是用一个个函数来实现,之后就不在赘述了。
上面两个图是实现这个游戏我自己写的函数,大家可以看到的确是能赏心悦目一些。让我们接着来。
然后我们在主函数内部运用这个菜单
这时大家要思考一下:我们在玩游戏的时候最开始出现的是菜单接下来呢,我们玩游戏大概率不是只玩一局所以呢这个游戏的实现要在循环里。而不管玩不玩游戏菜单都要最先出现,所以我们可以用一个do while 的循环。
这里循环的条件先不急着写我们一步一步慢慢来。
3.2接下来是选择菜单上给出的内容进入游戏或者退出
因为菜单上显示的是1或0所以我们需要定义一个整形变量input来输入数据
接下来就是选1 进入游戏
或者选0 退出游戏
显而易见这里需要一个选择语句switch
当我们输入1时进入函数Trimoku_Game()内部
输入0则退出游戏
如果输入错误提醒用户输入错误并重新输入。
这就是我们在do while循环里需要写的大致思路
接下来我们考虑循环条件如何去写
1 进入
0 退出
其它数字都要重新选择 也就是进入循环
所以我们可以看到当 input非0时都要一直循环
所以()里这么写
也可以把!=0省略都是一个意思
3.3接下来我们该进入Trimoku_Game()内部来实现游戏了
我们可以先只在Trimoku_Game()函数内部输出一个三子棋游戏来检查前面代码写的对不对。
运行截图
可以看到当我们输入1时就打印三子棋游戏
输入0时就退出游戏
并且是可以重复运行游戏的。
接下来是在Trimoku_Game()内部写游戏了。
我们下棋呢,首先需要一个棋盘。这里我定义一个char类型的数组board
board的行和列我们可以在game.h文件里用#define定义
*我们可以把需要用到的库函数的头文件和自己写的函数的声明都放到game.h这个头文件下
然后在game.c和main.c中引用game.h这样就不用重复声明或者引用库函数的头文件
之所以board的ROW和COL用#define来定义是为了在将来我们如果需要把三子棋变成五子棋甚至是十字棋时方便修改。
并且这样做,还有一个好处是:在函数传参时可以用COL和ROW方便理解,而不是传个数字3。
3.4有了棋盘之后我们需要将棋盘初始化一下,让棋盘一片空白,也就是让棋盘里的元素都为’空格’。
我们先定义一个初始化函数Init_Board(),然后思考它的返回值和形参都需要什么。显而易见,
它仅仅只是要进行初始化棋盘也就是把board数组里的值都改为’空格’并不需要返回数字和字符所以类型就是void 形参的话 初始化棋盘需要棋盘和棋盘的行和列。
所以我们把 board,ROW,COL传进去
然后用下方图片里的形参接收
然后在Init_Board()函数里进行一个简单的赋值操作。
我们把棋盘初始化后,接下来我们应该打印棋盘,让玩家能看到棋盘,才能继续下棋。
于是我们再定义一个Print_Board()函数来打印棋盘。
3.5棋盘的打印
Print_Board()的使用和声明
Print_Board()函数的实现同样需要数组board以及行和列所以我们依然把这三个值传进去。
Print_Board()函数的返回类型和形参
我们在打印棋盘是不仅要打印棋盘的棋子还要打印棋盘的格子,所以我们在Print_Board()函数中还要实现格子的打印功能。
这是我们需要打印的棋盘
中间是需要放的棋子因为是空格所以不可见。那么如何来实现这个功能呢?
首先我们要了解棋盘的构成
棋盘第一行是由若干个红色的三个空格以及黄色的|组成的。(需要注意的是中间的空格是我们需要填写的棋子只是因为初始化棋盘后里面的棋子就是空格,后期玩家下棋时就是将这个空格替换为棋子)
棋盘第二行是由若干个蓝色的三个—以及黄色的|组成
整个棋盘就是由3个第一行和2个第二行组成
搞清楚棋盘的构成思路后,我们来进行代码的实现。
在Print_Board()函数写完之后我们又可以测试一下自己写的函数正不正确了。
运行如果是上图这样说明你的函数应该是没有问题。我们还可以把初始化函数里的空格改为x来观察棋盘是否能正确存放棋子
然后我们再次运行程序
结果应该如下图所示
里面的x就是未来我们存放棋子的地方。
在我们有了棋盘之后就该下棋了,我们接下来研究如何让玩家下棋。
3.6玩家下棋(玩家的棋子是*)
首先依旧是定义一个函数Player_Move()来实现功能
函数类型和形参如下图所示
玩家下棋首先我们要提醒玩家下棋了,然后提醒他下棋的格式 如果输入坐标错误则重新输入或者当该棋盘格已经有子时不能再下了。这是玩家下棋我们需要实现以及注意的地方。
*还有一个要注意的地方,我们数组是从0开始的0 1 2这样下棋。但是玩家不是我们程序员,这样不方便理解所以我们要把他们的1在程序里改为0 ,1改为2以此类推。
因此我们在Player_Move()函数内部定义两个变量x,y这两个变量就是玩家下棋的横坐标以及纵坐标,我们操作时需要把它们减一。
Player_Move()函数的实现如下:
玩家下棋之后就是电脑下棋
3.7电脑下棋(电脑的棋子是#)
因为是一个简单的三子棋小游戏所以我们让电脑随机下棋而不是人工智能下棋。当然如果你想两个人对弈的话就不需要电脑下棋了,将Player_Move()函数执行两次就可以了。
同玩家下棋一样,我们依旧需要定义一个函数Computer_Move()来实现电脑下棋的功能
同样我们先定义x,y作为电脑下棋的横、纵坐标。
然后提示电脑下棋
然后就是下棋了,电脑并不需要我们人为输入,想让它随机下的话,这里我们需要引入一个rand函数
rand函数的功能就是产生随机值
引用rand函数需要引用一个头文件 #include<stdlib.h>
我们令x = rand() % row + 1;
y = rand() % col + 1;
这样可以把x和y的值控制在1-3之间满足棋盘要求。
在使用rand函数的同时要先使用srand()函数来产生种子,
这个种子是要变化的因此我们在srand()函数里面用time()时间函数,因为时间是一直变的。
在引用time函数时,也要引用一个time.h的头文件
又因为srand()函数里要求使用的类型是无符号整形也就是unsigned int 类型。
代码实现如下:
这样的种子只需要有一个就可以所以我们把它写在main()函数里
*如果想更深地了解rand函数、srand函数、以及time函数可以下载 MSDN 或者 进入
cpulsplus网站搜索这几个函数。
电脑随机下棋的同时我们依旧要判断是否该棋盘格子由棋子,并且下错了要重新下,所以依旧是一个循环。
代码实现如下:
这样电脑下棋我们就写好了.
在玩家下棋和电脑下棋之后,我们都需要打印棋盘。
并且这个过程是一个循环,直到决出胜负为止
可以用一个死循环来实现,后续只要判断输赢然后break跳出循环就可以了。
接下来我们运行程序
已经可以实现人和电脑相互下棋了
最后我们只需要判断输赢这个游戏就大功告成了!
3.8判断输赢
判断输赢我们需要判断这几种情况
1.人赢 *
2.电脑赢 #
3.平局(棋盘满了,并且人和电脑都没赢) Q
4.或者谁都没赢,棋盘也没满则继续游戏 Z
我们让人赢的时候返回字符*
电脑赢则返回字符#
平局返回字符Q
继续游戏返回字符Z
我们依旧是先定义一个Is_Wine()函数来实现这些功能。
这次的Is_Wine()函数的返回值就是 char而不是void了因为它需要返回字符。
函数的类型以及形参如下:
我们如何判断输赢呢?
三子棋想赢无非就三种情况
有一行三个子一样
有一列三个子一样
有一个对角线三个子一样
只要这三种情况满足一个就赢了
接下来我们就对这三种情况进行书写。
1判断行
如果没满足一行相等则令flag=字符往下继续操作
2判断列
3判断对角线
以上三种情况是对玩家下棋时行、列以及对角线的判断
电脑下棋同理只是把返回的*改为#,不再赘述。
有了返回值之后我们就可以在Trimoku_Game()函数里进行输赢的判断了
如果玩家赢则输出玩家赢
电脑赢则输出电脑赢
平局则输出平局
这时我们这个三字棋小游戏就写好了。
我们就可以玩上几局进行测试了。
玩家赢的情况:
平局的情况:
电脑赢的情况:
以下是我代码的实现内容: