引言
C语言学了一段时间了,第一篇博客纪念一下自己独立完成的第一个小项目,还请大佬们多多指教!(所有代码内容在最后)。C语言编写一个简单的小游戏,井字棋。完成后的表现形式如下:
运行代码后,先进入游戏菜单页面:
选项1进入游戏,选项0退出游戏,我们先看0选项的效果:
然后就进入我们的正题了选项1(play环节!):
直接打印出我们的棋盘,并由玩家先手开始下棋。ok开始部分就到此为止了,接下就是对弈环节了
相信井字棋大家都玩,至于具体的过程会在正文中体现。
开始编写
分析需求
首先是分析整个游戏的框架:
我们希望他能先打印出菜单;并且在我们选择开始游戏后出现棋盘,以供我们与电脑对局;接着是正式开始游戏:我们下一步,电脑下一步,直至有一方胜利,或是整个棋盘下满了都无人获胜,出现平局。无论是任何一方获胜还是出现平局,都结束这盘游戏,我们可以重新选择开始或是退出。
开始编码
分析了整个框架,明确了我们的需求后,就正式开始编写:
首先,为了使整个项目的代码比较规范,看上去一目了然,我们选择用三个文件来编写,分别为test.c,game.c,game.h,其中test.c用来表现整个游戏的整体逻辑并测试;game.h为用来包含需要的头文件,并且声明函数与符号;game.c用来实现函数。
首先将用到的头文件放到game.h里,
并将game.h引用到其他两个文件中,防止等会编译出错:
主题框架
具体内容表现为菜单的不同选择所触发的不同结果。
菜单
大致框架写好了,我们先来完成菜单menu():
(就是一个纯粹的打印哈哈哈)这个时候试运行就能跑出菜单的效果了。
开始游戏
ok,重中之重,关键内容来了game():
因为行和列经常用到,并且方便我们之后优化所有选择直接在头文件中声明:
我们先设置一个数组用来存放到时候下的棋子,并写一个函数(InitBoard(board,ROW,COL))将其初始化置空,然后在写一个函数(DisplayBoard(board,ROW,COL))将棋盘打印出来供我们下棋;玩家与电脑正式开始对弈,分别用两个函数来实现玩家下棋PlayerMove(board,ROW,COL)和电脑下棋ComputerMove(board,ROW,COL),并且每一方下过一次后都要同步更新棋盘,将新下的棋子打印出来,然后判断输赢,出结果了,对手自然也不用下了。当然判断输赢我们通过函数实现IsWin(board,ROW,COL)。
初始化棋盘
简单的全部置空。
打印棋盘
值得注意的是棋盘第一行先是空格,再是分隔,最后还是空格结尾,因此 '| '要比空格位少一个;同样的第二行与下一行的分隔 '_' 也是这样,因此循环时需要行列数减一。(这个时候已经可以将棋盘打印出来看看效果了)
玩家下棋
首先玩家下棋,因为主观性比较强,因此,我们还要判断下的位置是否合法(3*3的格子总不能下到200去),给与相应的提示并让他重新下,直到下的合法为止,用*来表示我们的棋子。
电脑下棋
电脑就比较老实了,我们只要写好程序,他就一定下的合法。这里我们使用随机数来决定电脑的棋子位置,先前主题中的srand((unsigned int)time(NULL)),与头文件中包含的#include<stdlib.h>,#include<time.h>都是此时为随机数服务的。因为3*3的格子在数组中表现为0到2,因此我们再%行列数,就能保证随机数的范围了。
判断胜负
最后就是我们的判断输赢了
我们只需要进行行遍历与列遍历,就能判断行列的输赢了。至于斜线判断,由于棋盘的限制,我们只需要简单判断固定的对角线就可以了。平局的判断,我额外写了一个函数通过返回值来判断:
平局
结果一出,我们只需要根据对应的函数返回值就能打印出对应的结果了。
Tips:记得所有函数在编写前在头文件game.h中声明一下哦
这样横跨两个文件才能使用,也方便逻辑上查漏补缺。
至此我们的井字棋项目就完成了!当然,这个简单的项目还有很多可优化之处,例如电脑的下棋逻辑可以改成判断对手棋子并以堵截为优先,这个等我事后再来尝试一下吧。
最后是我的代码汇总
代码汇总
test.c
game.h
game.c
最后欢迎各位大佬指点与交流!