首先,问题分析。三子棋首先得有一个游戏界面,即菜单——菜单有两个选项(1.play 0.exit),可供玩家进行选择,如果选0,则弹出退出游戏,程序结束运行;选择1,则进入游戏;选非0非1,则弹出选择错误,请重新选择。
创建一个头文件,两个源文件。
game.h------函数的声明,符号的定义
game.c------函数的内容,游戏代码的实现
test.c------测试游戏的逻辑
这里采用do--while循环,其目的就是保证游戏能先进入菜单,保证玩家至少能够玩一把,
选项采用1和0有一个好处,在系统中0为假,非0为真。因此当输入0以后,可以跳出选择语句,进入循环的判断,为假,就直接跳出循环;输入非0非1以后,就会一直在循环中,也就有多次选择的机会了。
---------------------------------------------------------------------------------------------------------------------------------
选择1以后就进入了游戏。
下棋得有一个棋盘,还得有3*3=9个棋子的位置,
因此可以定义一个二维数组,来装这9个棋子。
这里是一个无返回类型的一个函数。
这里创建了两个define定义的常量,这样的一个好处,就是方便后期,我要去修改棋盘大小的时候,只用修改这两个常量,就比较的方便。由于写在头文件中,所以test.c中需要引入一个头文件(引入个人写的头文件用" "括起来,如果是引用系统自带库函数则用< >括起来)
引用初始化函数,然后开始对落子位置,也就是棋子进行初始化。
这里的实参接收参数,写的是数组名,几行,几列。
在初始化函数的内容中,通过两个for循环,将二维数组的全部元素赋值为了空格,并在头文件件中进行声明。
之所以用空格进行赋值,首先是保证下棋的位置为空的,并且保证落子以后,不会改变棋盘原有的结构,这是因为将原有的空格替换成了棋子。
---------------------------------------------------------------------------------------------------------------------------------
棋盘的样子:
试着想一下,如果没有空格,但我们去下棋以后,整个棋盘就会发生错位。
整理一下思路:打红点的那个位置就是存放数组元素滴。
接下来就是要打印棋盘了
无非就是写两个循环,一个负责行,一个赋值列。
当进入循环,首先是第一行,然后在进入一个循环,这一个循环说负责将这一行的内容打印完,退出这个循环,进入第二行,如此反复,直到最后一行结束。
---------------------------------------------------------------------------------------------------------------------------------
棋盘和落子问题解决以后,就开始下棋了,下棋就是人下,电脑下,是一个循环。
人可以去指定位置去下,去输入一个坐标,电脑就生成一个随机的坐标,
写简单对棋循环:
函数实现玩家下棋:
以上是一个错误的写法:
这里必须要写一个循环,如果不写循环,会出现这么一种情况,玩家只有一次机会,当玩家输入错误以后,会弹出提示,然后电脑就开始落子了。
写循环,判断这是这一个正确的坐标以后才能跳出循环,然后才是电脑落子。
这个函数里,首先定义x,y两个变量,用于表示坐标,
坐标是在一定范围内的,在使用时,通常情况下,我们会把第一排第一格的默认坐标写成(1,1),然而事实上,正确的表达应该是(0,0),因为用的是数组,数组下标是从0开始的,那该如何调整的呢?将输入的x,y值同时减去1就可以了。
---------------------------------------------------------------------------------------------------------------------------------
函数实现电脑下棋:
这里要补充新的内容,即如何生成存在一定范围内的随机整数?
rand()表示是随机生成一个整数,取row和col的余可以很好的限制,x,y的范围。
x,y的范围都在0~2,x,y生成的随机值对应的直接就是下标,可以很好实现落子,不用像前面那样还受我们习惯性因素影响,还需要进行多一步的减1。
还得在主函数中添加这代码,目前只知晓(unsigned int)的使用是强制无符号整形,time函数传一个空指针。目前还未学习到这方面内容,了解不深刻,只知晓要这么用。
---------------------------------------------------------------------------------------------------------------------------------
并非每一次的随机值都能很好的满足条件,就比如,将如随机生成的坐标对应的棋盘上刚好已经有棋子了,该怎么办?
就得去写循环判断,直到取到合适的值即可。
---------------------------------------------------------------------------------------------------------------------------------
通过以上的代码又能让运行时,更加的清晰,它的作用是延迟1秒,清空上一次打印的内容
---------------------------------------------------------------------------------------------------------------------------------
上述代码已经基本的实现了玩家和电脑的对弈。
现在就是判断输赢了,这是一个难点,如果要给玩家加点难度的话,这涉及我们给电脑设计的一个算法,这又是一个难点,在不久的将来,我将具备这方面的能力,你也一样。
判断输赢:
玩家赢,就返回一个*
电脑赢,就返回一个#
平局,就返回一个Q
还未分出胜负,就返回一个c,表示继续
以下,循环是处于玩家和电脑下棋这个循环中,
如果电脑和玩家接受的值都不是c,就跳出循环。
跳出循环以后:
根据返回的值,来判断到底谁赢,还是平局。最后在打印棋盘。
当把以上的这个大纲,写完以后就可以进一步写函数来决定如何返回,以及什么情况该返回那个符号,
通过每行,每列,以及斜着的情况分别判断是否存在三个一样的符号连成一线,直接用二维数组下标去表示返回值,很好解决了该返回什么样的值。
判断棋盘是否下满,通过两个for循环,依次检验,如果存在空格直接返回0;反之就返回1,就进入if语句中,实现平局。
如果没有谁赢,也没有平局,就说明还没有下完,最后返回c,继续。
待办问题:
1、在判断输赢时,有很大的局限,只能对于n行3列,才行的通,那该如何实现对于5*5甚至是10*10的情况判读呢?
2、如何给电脑写一个算法,让玩家不容易赢?