用C语言C++手把手教你编写“井字棋”小游戏

用C语言C++手把手教你编写“井字棋”小游戏_第1张图片
用C++编写游戏容易吗?有什么开源的小游戏吗?能分享一下吗? 这个答案中,我提到学习游戏编程可从回合制游戏开始,例如井字棋。

下面是小编整理好的一套C/C++资料,加小编C/C++编程学习群:825414254,获取系统性学习C/C++的学习资料

用C语言C++手把手教你编写“井字棋”小游戏_第2张图片

考虑到一些初学者的学习需求,我就写一个井字棋的教程吧。

用C语言C++手把手教你编写“井字棋”小游戏_第3张图片

1. 游戏状态的表示

首先,我认为表示方法(representation)是编程中应最先要考虑的事情。对于回合制游戏,我们需要存储一个回合中的游戏状态(game state)。

以下用一个结构体表示井字棋一个回合中的状态,并加入函数作初始化:

用C语言C++手把手教你编写“井字棋”小游戏_第4张图片
以上用二维数组存储棋盘(board)是其中一种表示方式,另一种方式则是记录每个回合下棋子的位置。我们采用前者是因为它较容易实现胜负判定。有些回合制游戏可能使用冗余的表示方式,以方便实现各种规则。

而使用结构体而不是直接用全局变量,可带来一些优点,例如增强可读性及内聚性。

2. 显示游戏状态

编写游戏时,我们通常希望先显示游戏状态,之后才加入其他规则,因为这样可以方便测试。

我希望用这样的文本显示游戏状态,当空置时写上位置编号(1-9),以方便玩家输入下棋位置:

用C语言C++手把手教你编写“井字棋”小游戏
简单直白地编写代码的话:

用C语言C++手把手教你编写“井字棋”小游戏_第5张图片
由于 display() 只读而不改变游戏状态,所以其参数类型为 const state*。

我们稍压缩一下代码:

用C语言C++手把手教你编写“井字棋”小游戏_第6张图片
我们可以加入 main() 函数去显示初始化的状态:

用C语言C++手把手教你编写“井字棋”小游戏
3. 实现下棋

然后,我们加入第一个游戏规则,就是下棋:

用C语言C++手把手教你编写“井字棋”小游戏
函数内做了一个合法性判断,如果该位置已有棋子,则返回 0 表示失败。成功的话,在偶数回合填入 0,表示 O;奇数回合填入 1,表示 X;然后都把回合加一。

更改 main() 简单测试:

用C语言C++手把手教你编写“井字棋”小游戏_第7张图片
输出:

用C语言C++手把手教你编写“井字棋”小游戏_第8张图片
4. 处理输入

在每一回合中,提示当前玩家(O 或 X),并让玩家输入一个下棋位置(1-9),如果位置不合法,则重新输入:

用C语言C++手把手教你编写“井字棋”小游戏
在标准输入中,要到回车键才能处理输入,所以这里我们读了第一个输入字符后,就忽略其他字符直到读到换行符。我们把表示位置的字符转换成二维数组索引。

然后,就可以修改 main() 实现二人下棋的流程:

用C语言C++手把手教你编写“井字棋”小游戏
5. 胜负判定

众所周知,井字棋的胜利条件,是有三个棋子在横线、直线或斜线连成一线。我们实现一个 evaluate() 函数去评估棋局的状态,如果 O 胜出则返回 1,X 胜出则返回 -1,不分胜负则返回 0:

用C语言C++手把手教你编写“井字棋”小游戏
上面的代码使用了一个宏 CHECK() 去检测三个位置是否都为相同的棋子,如是则直接返回胜方。

最后,我们在 main() 中,待每次下棋及显示状态后, 判定是否出现胜方,如果到达第 9 个回合(回合从 0 开始),则判定是平局(draw):

用C语言C++手把手教你编写“井字棋”小游戏_第9张图片
6. 总结

本篇实现了二人井字棋,它是一个简单的回合制游戏。我们先选择了游戏的状态表示方式(state结构体及init()函数),然后把状态以文本形式显示(display()函数),加入每回合下棋规则(move()函数),以及人类玩家的输入处理(human()函数),并作胜负判定(evaluate()函数),最后在main()里则实现了按回合的循环及输出胜负结果。

虽然这个游戏本身以及 60 行的示例代码都很简单,但这个框架可以用于实现其他(更复杂的)回合制游戏。实时游戏(如动作游戏)的主要区别,其实也只在于把输入部分做成非阻塞的函数,而该循环则称为游戏循环(game loop)。

你可能感兴趣的:(C语言,计算机,C++,c/c++,互联网,编程,C++,C语言,C,C/C++)