第九章 C++ 拼字游戏

到目前为止,我们已经学习了数据类型,基本运算,控制结构,以及函数和输入和输出。那么我们接下来要使用这些内容做一个简单的拼字游戏。我们在控制台输出9宫格,每个格子代表一个数字,数字从1到9随机排列,然后我们需要通过”wasd”控制数字格子移动,使其形成1-9的从小到大的顺序排列,即可完成游戏。我们先梳理一下开发思路:

1. 使用整型数组来存储9宫格
2. 使用随机数来打乱数字的排列
3. 使用cout来输出9宫格
4. 使用cin来获取用户的输入
5. 使用控制结构来移动数字
6. 使用函数来拆分各个功能

大部分的游戏开发的核心都是一个无限循环体,当然我们在无限循环体之前需要初始化基础数据,以及循环体结束后释放数据占有的内存。在无限循环体的内部,基本上又包含两部分,第一部分是接收用户的输入并根据输入来修改数据,第二部分就是根据修改后的数据来渲染出游戏界面。这个两个部分在循环体内周而复始的不断执行。

我们要开发的小游戏也基本上遵从上面的大致结构。在游戏初始化的时候,初始化九宫格并随机打乱其数字,在游戏结束的时候在释放九宫格做占有的内存。在循环体内部,首先就是获取用户的输入,然后根据用户输入来调整九宫格数据里面的数字位置,第二部分则是根据九宫格的数据来输出到控制台即可。在实际的2D/3D游戏开发中,游戏界面的渲染是一个非常复杂和困难的部分,这里我们只是使用cout输出九宫格到控制台即可。

以下是我们代码框架:

#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
using namespace std;
	
// 定义九宫格数组
int nineCellArray[] = { 1,2,3,4,5,6,7,8,9 };

// 声明游戏开始函数(初始化数据)
void startGame();

// 声明游戏循环函数
void loopGame();

// 声明游戏结束函数(释放数据)
void endGame();

// 入口函数
int main()
{
    // 调用函数
    startGame();
    loopGame();
    endGame();
}

// 定义游戏开始函数
void startGame() {}

// 定义游戏循环函数
void loopGame() {}

// 定义游戏结束函数
void endGame() {}

首先,我们来完成九宫格数据初始化的函数功能。这里主要就是打乱九宫格的顺序,我们采用的算法就是产生两位0-8之间的随机数,这两个随机数相当于九宫格数组的下标,然后我们将两个下标对应的数组元素兑换即可。这样循环几次这样的操作,九宫格数组内的数字就很乱了。startGame函数内部代码如下:

int range = 8;
srand((unsigned)time(NULL));

// 循环5次进行数组元素交换
for (int i = 1; i <= 5; i++) {

    // 随机两个0-7之间的数字(数组下标值)
    int x = rand() % range;
    int y = rand() % range;

    // 根据随机下标交换两个数组元素
    int temp = nineCellArray[x];
    nineCellArray[x] = nineCellArray[y];
    nineCellArray[y] = temp;
}

接下来,我们应该把九宫格输出到控制台上,这个功能是属于游戏循环体的,因此我们可以进一步把游戏循环体拆分出两个部分,一个部分是用户输入,一个是输出九宫格。同样我们可以定义两个函数来实现,如下:

// 声明游戏循环中处理用户输入函数
bool update();

// 声明游戏循环中游戏界面渲染函数
void render();


......


// 定义处理用户输入函数
bool update() { return false; }

// 定义游戏界面渲染函数
void render() {}

完成游戏循环体的函数声明后,我们先来完成渲染函数,也就是把九宫格数组打印到控制台上,render函数内部代码如下:

cout << nineCellArray[0] << nineCellArray[1] << nineCellArray[2] << endl;
cout << nineCellArray[3] << nineCellArray[4] << nineCellArray[5] << endl;
cout << nineCellArray[6] << nineCellArray[7] << nineCellArray[8] << endl;

然后我们只需要在游戏开始初始化九宫格数组后,调用render函数就可以看到效果了。记得把render添加到startGame函数的最后!!!此时运行整个程序,我们应该能够在控制台上看到打乱的九宫格数字。

接下来我们来完成循环体函数loopGame,既然是一个无限循环体,那么在该函数中就应该有一个循环控制结构,然后在控制结构中调用update函数和render函数。

// 游戏循环标示
bool loopFlag = true;


......



// 定义游戏循环函数
void loopGame() {
    while (loopFlag) {
        if (update()) render();
    }
}

用户处理函数作为布尔类型返回的原因在于,用户的输入是不确定的,用户有可能进行了输入操作,也可能没有,或者用户输入的数据是有问题的,因此只有正确处理了用户输入,才能渲染游戏界面。如果用户输入返回false的话,则应该让用户继续输入。

接下来就是游戏的核心部分,处理用户的输入,并修改九宫格数据。这也是游戏开发过程中最主要的工作内容。首先,我们需要接收用户的输入。为了简化游戏的复杂性,我们要求用户先输入要移动的数字(“1-9”),然后在输入移动方向(”wsad”),这样我们就可以根据这两项输入来交换数组元素的位置。先来update函数内部代码:

// 获取用户的输入
int number;
char direction;
cout << "请输入数字键和wasd方向键:";
cin >> number >> direction;

// 清空缓冲区,防止残留数据影响
cin.ignore(1024, '\n');

// 用户输入检查
if (!(number > 0 && number < 10)) return false;
if (!(direction == 'w' || direction == 'a' || direction == 's' || direction == 'd')) return false;

如何根据用户的输入来调整九宫格数组呢?因为交换数组元素,必须知道交换两元素的下标。也就是说我们需要根据用户输入的数字,来找到它在九宫格数组中的下标,这个不难,做一个循环即可。然后还有根据移动方向来找到目标元素的下标,同时还要考虑位于九宫格边缘的数字是不可以再向外移动的。也就是说这个目标元素必须在九宫格内存在。

// 先找到被移动数字的位置(数组下标)
int oldPos = -1;
for (int i = 0; i < 9; i++) {
    if (nineCellArray[i] == number) {
        oldPos = i;
        break;
    }
}
if (oldPos == -1) return false;

// 根据位置和移动方向返回新的位置
int newPos = oldPos;
switch (direction) {
	case 'w': newPos -= 3; break;
	case 'a': newPos -= 1; break;
	case 's': newPos += 3; break;
	case 'd': newPos += 1; break;
	default: newPos = -1;
}

这个算法很简单,左右移动分别减1和加1,这个很简单。上下移动分别减3和加3,主要是九宫格的布局格式决定的。也就是说上下两个元素相差3。当然我们还需要做一个判断,就是九宫格的最外层的元素不能再向外层继续移动了。这里我们简单做判断即可,如下:

// 最上面一行不能再向上移动了
if (oldPos < 3 && direction == 'w') newPos = -1;

// 最下面一行不能再向下移动了
if (oldPos > 5 && direction == 's') newPos = -1;

// 最左边一行不能再向左移动了
if (oldPos % 3 == 0 && direction == 'a') newPos = -1;

// 最右边一行不能再向右移动了
if ((oldPos + 1) % 3 == 0 && direction == 'd') newPos = -1;
    
// 获取移动后的新位置
if (newPos == -1) return false;

两位交换元素的数组下标找到后,我们就可以交换数字了,代码如下:

// 交换两个数组元素
int temp = nineCellArray[oldPos];
nineCellArray[oldPos] = nineCellArray[newPos];
nineCellArray[newPos] = temp;
    
// 返回
return true;

至此update函数代码完毕。

接下来,我们还需要判断游戏是否结束,也就是说经过玩家的输入调整后,九宫格的数字是否按照1-9从小到大的顺序排列,如果是,则表示游戏结束。这个操作应该放在渲染游戏界面之后操作。也就是在render函数后面做判断。如果玩家成功,结束游戏的话,也就是结束游戏循环体,并执行endGame函数。那么render函数中新增加代码如下:

// 判断九宫格顺序
bool flag = true;
for (int i = 0; i < 8; i++) {
    if (i + 1 != nineCellArray[i]) {
        flag = false;
        break;
    }
}

// 如果顺序正确,则游戏结束
if (flag) {
    loopFlag = false;
    cout << "游戏结束" << endl;
}

拼字游戏开发完成,以下是开发过程的总结:

1. 游戏是一个无限循环体
2. 游戏需要根据用户的输入来调整数据
3. 游戏的渲染是根据数据进行的
4. 游戏的代码开发优先要梳理好思路
5. 我们使用函数对功能进行拆分
6. 游戏涉及的算法需要很强的逻辑思维能

本课程的所有代码案例下载地址:

C++示例源代码(配合教学课程使用)-C/C++文档类资源-CSDN下载

备注:这是我们游戏开发系列教程的第一个课程,主要是编程语言的基础学习,优先学习C++编程语言,然后进行C#语言,最后才是Java语言,紧接着就是使用C++和DirectX来介绍游戏开发中的一些基础理论知识。我们游戏开发系列教程的第二个课程是Unity游戏引擎的学习。课程中如果有一些错误的地方,请大家留言指正,感激不尽!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咆哮的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值