转珠游戏介绍
转珠游戏不同于传统三消游戏,传统三消是通过单次移动(移位)消除相连的珠子(以下简称COMBO).转珠游戏是通过移动珠子(可以理解单次操作多次移位)。在形成最终版面后一并计算结果,本系列主要探索消珠算法,最短路径算法,最优路径解等。
智龙迷城
这边用转珠游戏代表作,日本itunes app常年前三的国民游戏,智龙迷城为例
通过移动红色珠子 如箭头移动后,可以达到两次消除(combo)(可以脑里模拟一下)
最短路径?
这类游戏的算法已经非常成熟,基本是通过dfs或者djstra、抑或是floyd去求解的,(官方也有自动路径,但是只有三步,推测暴力算的)
市面上的APP用过几个都是无法求到最优解(版面最大COMBO),怀疑也是floyd或者暴力+剪枝(这一部分不确定,如果我错了先说声抱歉)
在求最短路径算法之前,我们需要一个模拟获取游戏结果的算法:
消珠问题简化
转珠游戏分两种,一种是通过移动一个珠子N次,另一种是移动”任意”珠子“N次(业界俗称CTW:即Change the world)达到版面最大COMBO
即:在N x M的二维数组中,任意交换两个相邻元素,N次交换后达到最大Combo(CTW),如果限定除开始位置外,每次移动均限制为上一次移动的对象,即转为本次问题,如下所示:
1 2 6 2 2 2
5 6 4 4 1 3
1 6 4 1 3 1
1 6 4 2 2 1
1 5 5 3 3 1
上述数组进行消珠后,返回7,并且数组变为
--------------next combo---------
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 4 0 0
0 0 0 1 1 0
1 2 6 2 2 0
注:
1.移动包括上下左右,不包括斜角,因为斜角移动可以通过:左右→上下,两次移动达到同样效果,这样可以简化问题。
2.消除条件为,同一直线(不包括斜角)有相同属性的元素>=n(n为消珠限制且默认为3),则进行消除,全部消除完毕后,剩余珠子会掉落下来,掉落的珠子如果形成消除的话会再进行消除。
算法实现
对于元素分组问题一般是用并查集或者dfs实现,因为本问题行列均不大于10,使用DFS即可。
然而本文用的bfs
大概的伪代码如下:
int 获取最大combo(matrix[][]):
for each col row:{
bfs队列.push(最后一个非0元素).
标记该位置已被访问
while(bfs不为空) {
向四个方向寻找元素相同解
if(存在相同解)则bfs.push,且标记该位置已被访问 } }
int result = 执行combo计算(标记数组[][])
执行消除(matrix[][])
执行模拟掉落(matrix[][])
执行递归(this.获取最大combo(matrix[][]))
CODE (C++)
// 点集合 包含是否存在加珠,珠子类型等
struct binary
{
//珠类型
int cata;
//是否存在combo增加
bool comboPlus = false;
int i,j;
binary(int x ,int i,int j) : cata(x), i(i), j(j){
}
};
//单论消珠完成后进行掉落,每次迭代返回掉落后的数组
void finish(vector<vector<int>> &matrix)
{
int sizeCol = matrix.size(), sizeRow = matrix[0].size();
for (int i = sizeCol - 1; i >= 0; --i)
for (int j = sizeRow - 1; j >= 0; --j)
if(matrix[i][j]==0){
int ii=i-1;
while(ii>=0){
if(matrix[ii][j]>0) {
matrix[i][j] = matrix[ii][j];
matrix[ii][j] = 0;
break;
}
ii--;
}
}
cout<<endl;
cout<<