C++游戏开发,超简单的⼊门项⽬,50⾏代码搞定开⼼消消乐
⼀提到开发游戏,很多⼈都会觉得要很⾼深的技术,有⼀种望尘莫及的感觉。其实要编⼀款⼩游戏也没有想象的那么难,下⾯跟着⼩编⼀起来看看C++是如何⼀步步制作游戏的。
本⽂的代码下载地址在⽂章末尾,有需要的同学⾃取。
⼤家应该都玩过连连看,游戏规则不多说了,我们先看看设计思路。
第⼀件事要根据游戏玩法确定程序的数据结构,不同的数据结构决定了不同的算法设计,⽤错了数据结构可能直接让代码复杂好⼏倍。
连连看中玩家操作的数据是⼀个个的图⽚,多个图⽚组成⼀个棋盘式的矩阵界⾯。程序根据玩家的点击位置计算两个图⽚的连接路线,这要求程序以最快、最简单的⽅式获得矩阵中每个格⼦的数据。
【源码获取】:
由于平台原因,⼩编将完整源码放在⼩编⾃⼰的C语⾔/C++交流④群:836880131! 资料共享在群⽂件⾥⾯,有需要的可以⾃⾏添加获取~珠宝奢侈品品牌
管理能力包括哪些
如果对代码有任何建议,都可以添加⼩编的学习交流群,欢迎⼤家来讨论~
⽤⼆维数组表⽰游戏中的矩阵界⾯⽐较合适,因为数组可以通过索引快速访问数据,⼆维数组的两个索引刚好对应矩阵界⾯的(x, y)坐标。例如:
图中矩阵数据在代码中应该这样表⽰:
data[1][2] = 0;
data[1][3] = 1;
data[2][2] = 2;
可以⽤不同的数字代表不同的图⽚,⽐如:
那么上⾯的矩阵绘制的时候就会是这样:
0表⽰空格,不显⽰图⽚。初始化时的空格或消除后的空格,都会被设置为0。
// 定义数组
#define WIDTH 10
#define HEIGHT 8
int data[HEIGHT][WIDTH] = { 0 };
接下来要初始化数据,我打算⽤8种不⼀样的图⽚,每种6张,随机放⼊矩阵中,矩阵最外⼀圈是空的。这个算法可以⽤标准库函数std::random_shuffle 来完成。
std::random_shuffle ⽤于把容器内的数据随机打乱,因此按顺序把数据放⼊数组中,然后调⽤ std::random_shuffle 就可以完成初始化。
int tmpData[HEIGHT - 2][WIDTH - 2] = { 0 }; // 定义⼀个8 * 6的临时数组⽤于存放48个图⽚数据
int picNum = 1;
int curPicCount = 0;
for (int j = 0; j < 6; ++j)
{
for (int i = 0; i < 8; ++i)
{
// 填⼊数据
tmpData[j][i] = picNum;
curPicCount++;
if (curPicCount == picCount)
{
picNum++; // 图⽚⽤完,换下⼀种图⽚
curPicCount = 0;
}
}
}
// 随机数据
std::random_shuffle((int*)tmpData, (int*)tmpData + (HEIGHT - 2) * (WIDTH - 2));
/
/ 再填⼊10*8数组中
for (size_t i = 1; i < WIDTH - 1; i++)
{
for (size_t j = 1; j < HEIGHT - 1; j++)
{
data[j][i] = tmpData[j - 1][i - 1];
}
}
断点运⾏观察数组数据,和我们设计的⼀样:
贴上图⽚看起来还不错:
现在来分析游戏玩法。
这个游戏的难点是两个图⽚连接的判定算法,要求连接线只能转折两次。
军训个人小结
我的第⼀反应这是⼀个寻路算法,要求找到转折两次以下的最短路径。教科书上常见的⼴度优先搜索、深度优先搜索、DijKstra算法或是游戏中常⽤的A星算法,稍作修改加上两次转折的限制都能解决这个问题。
但是如果我⽤这些⽐较复杂的算法来教新⼿,显然是在劝退。所以还是考虑找⼀找连线判定的算法有没有简单的规律。
多玩⼏次游戏,把不同种类的连线记录下来,总结后可以发现总共有3种连线类型,分别是不转折连接、转折⼀次和转折两次。
还是从最简单的情况开始考虑。这是解决难题的通⽤⽅法:从最简单的情况开始考虑,再逐步增加复杂的条件。
郭德纲相声段子最简单的不转折连接,有两种情况,横向连线和纵向连线:
这两种情况很容易处理,横向、竖向依次检查每个格⼦是否被阻挡即可。
// 横向是否连接
bool IsHLinked(int x1, int y1, int x2, int y2)
{
if (y1 != y2)
{
海鲜豆腐煲>爱在情人节
// 横向不在⼀条线
return fal;
}
int minX = std::min(x1, x2); // 找到左边的点
int maxX = std::max(x1, x2); // 找到右边的点
for (size_t i = minX +1; i < maxX - 1; i++) // 从左到右检查中间的点是不是空的
{
if (data[y1][i] != 0)
{
return fal;
}
}
return true;
}
// 纵向是否连接
bool IsVLinked(int x1, int y1, int x2, int y2)
{
// 代码类似
}
最后把这两个合并就是不转折的情况下:
// 不转折时判断
bool IsZeroTurnLinked(int x1, int y1, int x2, int y2)
{
if (IsHLinked(x1, y1, x2, y2))
{
return true;
}
if (IsVLinked(x1, y1, x2, y2))
{
return true;麻花的制作方法
}
return fal;
}
转折⼀次:
转折⼀次的算法也是⽐较明显的,像上图中的两种情况,找到绿⾊点的位置,如果这个点可以不转折连到两个红⾊的图⽚,那么这两个红⾊的图⽚就可以通过⼀次转折连接。
绿点的位置是由两个红点决定的,只有上图中的两种可能。
// 转折⼀次
bool IsOneTurnLinked(int x1, int y1, int x2, int y2)
{
int tmpPointX[2] = { x1, x2 };
夏之韵
int tmpPointY[2] = { y2, y1 };// 找到两个黄⾊点的坐标
for (size_t i = 0; i < _countof(tmpPointX); i++)
{
if (IsZeroTurnLinked(tmpPointX[i], tmpPointY[i], x1, y1)
&& IsZeroTurnLinked(tmpPointX[i], tmpPointY[i], x2, y2))
{
return true;
}
}
return fal;
}
转折两次的情况就多了,下图同样是连接红⾊图⽚,要绕过绿⾊图⽚。
转折两次的情况很多,这⾥⽆法⼀⼀列举,但是仔细思考可以发现和转折⼀次本质上是⼀样的,就是找到两个点,这两个点可以分别和红⾊图⽚⽆转折连接,并且这两个点也可以⽆转折连接。
这两个点需要位于经过红⾊图⽚的⼗字线上,并且只要确定⼀个了其中⼀个点,就能对应地找到另⼀个点:
因此只要遍历其中⼀个图⽚的两条⼗字线经过的所有的点,并计算出另⼀个图⽚⼗字线上对应点的位置,检查这两个点和两个红⾊图⽚是否可以⽆转折连接: