目录
三子棋简单介绍
大家都玩过五子棋吧,三子棋和这个类似,就是三子连成一线就获得胜利。
大概就是这么个情况。
实现方式
首先,我们将这个游戏的实现分为3个部分,放在test.c 文件, game.c文件 ,game.h文件里。
test.c :游戏的外部测试;
game.c :游戏的实现;
game.h :游戏的头、声明;
游戏外部测试(test.c文件)
先来看test.c文件,也就是外部测试如何实现。
第一步:先设计一个游戏菜单,做成类似这种简易形式:
***********************************
*************1. play ************
*************0. exit ************
***********************************
第二步:将其放入循环中,这边选择do while 是因为必定会先进入菜单选择一次。
下面的判断部分采用Switch更加方便简洁一些,当然 if 也可以实现。
这个函数设计的巧妙之处就在于这里do while 的结束条件,是一开始输入的input的值,如果输入的是1,那就玩过一次游戏后再进入选择,看是再玩一次还是退出。 如果输入的是0,就直接while(0)跳出循环了。如果输入其他值,也会再次进入循环进行选择。
这是测试游戏的实现,放在test.c文件中,下面来看游戏的具体实现。
以我们的test.c中的game函数为接口进入。将游戏的声明放在game.h中,具体游戏内容放在game.c中。
游戏内容具体实现(game.c和game.h)
设想一下,要完成三子棋游戏,那么首先需要棋盘吧,我么来看看棋盘长什么样。
这就是棋盘的样式,很自然地可以想到用二维数组存储数据,制作棋盘。
那就先设二维数组board[ ] [ ],再创建一个函数InitBoard定义棋盘。
char board[ROW][COL] = { 0 };
InitBoard(board,ROW,COL);
这里数组里面的元素个数我们不用board[3][3],而是在头文件里定义两个常量叫ROW,COL,用于表示行和列。这是因为方便以后要扩充棋盘时,不用一个一个去找board数组,直接改头文件里的定义常量ROW,COL就行了。
#define ROW 3
#define COL 3
但是要记得在test.c 和 game.c中包含头文件game.h 。
#include"game.h"
接下来就是在头文件中声明InitBoard函数,并在game.c中实现它了。
传参的时候要注意:传过来的是二维数组首行元素的地址,我们相应的也用数组接受,然后一并将其行和列也接收。这就获得了这个二维数组的全部信息。
定义棋盘样式就将其每行每列都赋成空格就行了。
定义完棋盘后随之打印棋盘,创建一个DisplayBoard函数来实现。
看一下棋盘格式
这棋盘可以看做是三部分组成的。上面两块都是
| |
---|---|---
这样组成的,最下面一部分可以看做是上述图案少了---|---|---
这样就可以用循环来实现行的表示:
关于类似循环图案的打印,我前面专门写过一篇博客来讲解,有兴趣的朋友可以点开看看:牛客网C语言刷题总结之------循环输出图形_SAKURAjinx的博客-CSDN博客
好,现在棋盘有了,那下一步就该下棋落子了,下棋必定是一人下一步,所以我们将电脑和玩家下棋放在一个循环中,下一步棋,我们展现一下棋盘落子位置。
我在这里设计的是电脑先下,因为这只是个简单的程序,没有设计算法,电脑完全是随机落子,为了增加可玩性,让电脑占得一点先机吧 ^ ^
那问题是怎么让电脑随机落子呢?这就需要产生随机数,需要借助我们的time函数来实现。
代码如下:
在test.c文件中引用生成随机值
srand((unsigned int)time(NULL));
在game.c中调用
int x = rand() % row;
int y = rand() % col;
这样变量x , y产生的随机值就在0~2之间。
注意:别忘了在game.h中包含头文件
#include<stdlib.h>
#include<time.h>
有了随机值,下面就让电脑落子,但是不能落在已经有棋子的地方。
电脑落子就是这样实现的,下面来看玩家落子。
玩家落子就需要我们手动输入棋子坐标了 ,由于游戏是给大众玩的,所以输入坐标时要从[1][1] 开始,所以这里设出变量x,y后,在棋盘中使用要x-1,y-1 。
详细代码如下:
运行情况展示:
到这里大家发现了吧,还差一个东西,就是判断胜负。下着下着一方赢了,但是没显示结果还在下,所以下面我们来设计结果判定函数Is_win。
我们假定:电脑获胜---返回‘#’
玩家获胜---返回‘*’
平局--------返回‘P’
游戏继续---返回‘R’
那么这个Is_win 函数就需要字符类型的返回值,并在循环外进行胜负判断。
Is_win函数的具体实现
获胜条件:
如果一行、一列或是一斜线上字符都相等,那么就可以判断获胜,至于是哪方获胜,依据返回值判断,代码如下:
如果两边都没获胜,那就看棋盘下满没,下满了就是和棋的情况,没下满那就继续走。
所以这里创建一个判断棋盘是否下满的函数Is_full,并将其返回值定为int类型,和棋返回0,继续下返回1 。
int a=Is_full(board, ROW, COL);
if (a == 1)
return 'R';
else
return 'P';
}
Is_full 函数的具体实现:
注意:test.c的测试函数部分,因为下棋和判断都是在while(1)循环中,所以如果结束了要跳出去,因此,这里还是用Is_win函数的返回值给出跳出条件,如下:
没有这个跳出条件,那就一直在里面循环了,所以一定要记得判断是否继续,然后break。
这样整个程序也就写完了,来看一下完整代码以及三种运行效果:
test.c部分(游戏外部测试):
game.h部分(游戏的头【声明】):
game.c部分(游戏的具体实现):
总的来说三子棋并不复杂,只是结合了二维数组、循环以及函数的一些相关知识,大家仔细揣摩就能写出来了,当然,要是感兴趣的话,也可以自己设计算法,不要让电脑方当个笨笨机器人,哈哈^ ^
三子棋会了,五子棋......想必也难不倒大家了,原理都是一样的。好了,我的分享就到这里了,祝大家万事顺遂!!!