使用【数组,函数,循环】实现一个超级简单的三子棋,总共200行代码。
先来看看成果。
运行程序,显示出菜单。
选择1,开始游戏,玩家先
输入坐标,如:1 1
‘#’为电脑,‘*’为玩家
玩家胜利
按任意键继续,返回菜单
首先分别创建一个头文件和两个源文件
game.h用来存放游戏的函数和变量的申明
game.c用来实现游戏的各种函数
test.c用来测试游戏
在头文件中包含标准输入输出流<stdio.h>
然后给两个源文件都包含“game.h”
在test.c中创建一个int main()函数,并添加如下代码
在int main()的上方添加菜单menu函数和游戏game函数
接下来实现game函数
在头文件中声明行ROW和列COL,还有初始化数组InitBoard和打印数组DisplayBoard的函数
在game.c中实现初始化数组InitBoard和打印数组DisplayBoard的函数
初始化
将每个格子初始化成空格
打印,打印这边有点难理解,所以要细讲
虽然我们的棋盘是3*3,但我们实际打印出来需要5行,为什么呢?
其次,一个格子看似是放一个字符,但为了美观,我们实际上放了3个字符(有两个是空格)
两边的空格是我们为了美观而放的,中间的是放棋子的位置
回到test.c初始化和打印都结束了之后,我们就要开始下棋了
在game函数中打印数组之后添加如下代码,这里注意在函数开头要加一个ret
分别在头文件game.h中添加game函数中新加的函数的声明
然后在game.c中分别一个个实现
首先实现玩家下棋PlayerMove函数
假如说玩家要下在第一个格子,那这时他输入的坐标应该是1 1,而这个位置在程序中的下标应该是0 0,所以我们在改变内容的时候应该要将坐标减去1
下面是在game.c中电脑下棋ComputerMove函数的实现
在game.h中添加<stdlib.h>头文件
在tese.c的mian函数开头加上srand((unsigned)time(NULL));
这里简单说明下, 关于srand((unsigned)time(NULL))
虽然rand()函数生成的是一个随机数,0~32767,但是每次关闭exe程序之后重新启动,它生成的数字还是会重复,比如说,我启动exe程序,它第一次生成的随机数是3,第二次生成了65,第三次是77,这样看上去确实随机,但是当我关闭exe程序再次开启,它第一次生成的随机数又会是3,第二次又会是65,第三次又会是77,这种就叫伪随机数,所以这个时候为了更好的体验,我们加上srand((unsigned)time(NULL))
srand()是一个函数,它的作用是设置一个供rand()函数使用的随机数种子,什么是种子,这里的种子就相当于对一个数字进行一种计算从而改变它的值,换句话说,就是把rand输出的值经过一种计算(比如加减乘除),之后再输出这个数作为rand生成的随机数。所以这个种子一定也是要随机的,如果计算方式一样,那么第二次打开程序,就又是一样的伪随机数了。
那么我们怎么改变算法呢,我们知道时间是一直在变化的,所以我们可以利用时间来改变它的算法。我们输入time()函数,它的作用是返回当前系统时间,()里面需要传一个指针,这边我们不需要了解,也用不到,所以直接传入一个空指针NULL,由于它返回的不是整形,所以我们需要强制类型转换,就是在time的前面加上一个(unsigned),unsigned是无符号整形的意思,也就是说把返回的时间强制类型转换成一个正整数,由于时间一直在变,所以算法也就一直在变,那么我们的随机数就是真的随机数了。
因为用到了time()函数,它需要包含时间的头文件,所以我们在game.h中包含<time.h>头文件
接下来就是实现判断输赢的函数了
判断棋盘是否为满
这样一来,我们简单的三子棋就完成啦,不过还有一些可以优化的地方,比如说下面这张图
我们每次下完棋之后都会打印,但是打印出来的东西不会清空,而是一直往下叠加,这样看着会有点乱,要是在打印之前可以把屏幕清空,仅仅就放一个棋盘,这样岂不是更好。所以我们只需要在每次打印新的棋盘前清空屏幕就好了,那么怎么清空呢。这里需要用到一个库函数system(),这个函数的作用是调用控制台命令,我们需要的就是调用"cls"也就是“清空”这个命令,而它所需要的头文件是<stdlib.h>,这个头文件我们在之前已经包含过了,所以这里就不用再重复包含了。在下面这些地方加上system("cls"),就可以达到效果啦。
ok 到这里我们的三子棋就大功告成啦!