挖矿技巧
本帖最后由 qweytr_1 于 2018-1-21 18:40 编辑不知大家有没有遇到过挖到最后一格才出通往下一层的梯子的情况
我反正经常遇到,于是我更新了自己的挖矿顺序,于是脸白了许多
手工做图或许比较麻烦,懒得做了
大约效果是这个样子,都是一次挖矿过程中(很多是手残多点了好几个点,于是没截图,外加,开始图片出了点小问题,后面补图时候发现游戏在后台似乎不是暂停……)
大家脑补细节就好了
首先,给出一个游戏会生成的布局,或许我们可以得到这样一个分布(不要管“占位”,这个字的作用是让表格对齐)
矿 占位
矿 占位
占位
梯子 占位
矿 占位
矿 占位
矿 矿 占位
占位
占位
占位 占位 占位 占位 占位 占位 占位占位
占位 占位
问最多开几个格子可以开到向下一层的梯子?
感觉一般人看到这个会很懵逼,觉得不开完小半张图应该找不到梯子,但答案是8,至多是18
首先要介绍两个引理
第一个被证实的版本是,迷宫应当是按照九宫格随机生成的,每一个九宫格只有一个功能,即,回家,有矿,没矿,向下
后两者表现相同,否则我绝对能只开4个格子解决问题。
九宫格是从左上开始的,于是可以这样划分:
矿 0 0 1 1 1 2 2 2 占位
0 0 0 1
矿 1 2 2 2 占位
0 0 0 1 1 1 2 2 2 占位
3 3 梯子 4 4 4 5 5 5 占位
3 3 3 4 4 4 5 矿 5 占位
3 3
3 4 4 矿 5 5 5 占位
7 7 7 8 矿 8 矿 9 9 占位
7 7 7 8 8 8 9 9 9 占位
7 7 7 8 8 8 9 9 9 占位
占位 占位 占位 占位 占位 占位 占位占位
占位 占位
(数数时候把6漏掉了,不要在意)
可以看出,同一编号的格子只有一个作用,即,有一格矿,什么都没有,或者有一个梯子
于是可以大胆猜测(两次开到31层也证明了这一点)
向下的梯子一定位于什么都没有的九宫格(即,标2的或者标7的)
然后呢,迷宫设计其实是有缺陷的,就是,很有可能某次生成的时候,最下面某一行或者最右边某一行被删除。
万一删掉梯子怎么办呢?
一个可行的答案是,不允许梯子随机出现在九宫格的最下或者最右
也就是,梯子只会出现在红色部分
矿 0 0 1 1 1 2 2 2 占位
0 0 0 1
矿 1 2 2 2 占位
0 0 0 1 1 1 2 2 2 占位
3 3 梯子 4 4 4 5 5 5 占位
3 3 3 4 4 4 5 矿 5 占位
3 3
3 4 4 矿 5 5 5 占位
7 7 7 8 矿 8 矿 9 9 占位
7 7 7 8 8 8 9 9 9 占位
7 7 7 8 8 8 9 9 9 占位
占位 占位 占位 占位 占位 占位 占位占位
占位 占位
虽然不清楚作者是怎么写程序的,但是根据最近10次挖洞经验,梯子的确是这样生成的
借助这个或许可以让挖矿速度x2x3x6
具体能乘多少就看原先脸有多黑了
比如先挖矿再顺路挖矿附近的……大约可以x12吧
Note:从第46层开始,分块大小变成了4x4(测试是44-49,50又回到了3x3的分块,不知具体缘由),因而上述算法需要修正
具体怎么改正在总结规律
本帖最后由 qweytr_1 于 2018-1-21 18:53 编辑
找到了或许相关的代码位置,有兴趣的可以分析一下,或者照着这条路继续走下去
首先这个应该说是最有用的
// MazeGenerator
public void SetFloorData()
{
this.ReleaseAllMineral();
this.m_upRadder.gameObject.SetActive(true);
this.m_downRadder.gameObject.SetActive(false);
MazeData levelData = this.m_mineData.GetLevelData();
levelData.GenerateChip();
MapCellData cell = MapManager.GetInstance().GetCell(levelData.m_upLevPos);
cell.m_eventID = 2;
this.m_upRadder.SetPos(levelData.m_upLevPos);
this.m_downLevelPos = levelData.m_downLevPos.Clone();
if (levelData.m_isAppearLadder)
{
this.SetDownLevel();
}
MineralManager.GetInstance().Apply(levelData.m_mineralList, true);
}
// MazeData
public void LevelGenerate(IVec2 entrancePos, MineLevel mineLevel, bool isEnableDownLevel)
{
IVec2 vec = mineLevel.size.Clone();
int num = (vec.x + vec.y) / 2;
int max;
if (num < 15)
{
max = 3;
}
else if (num < 20)
{
max = 4;
}
else
{
max = 5;
}
int num2 = UnityEngine.Random.Range(3, max);
int num3 = UnityEngine.Random.Range(mineLevel.mineralMin, mineLevel.mineralMax);
int breakWallCount = mineLevel.breakWallCount;
entrancePos = this.GenerateMaze(entrancePos, vec, num2, breakWallCount);
this.SetupRoof(MazeData.k_wallHeight);
this.m_upLevPos = entrancePos;
if (isEnableDownLevel)
{
this.m_downLevPos = this.GetEntryPoint();
if (this.m_downLevPos != null)
{
this.m_downLevPos *= num2;
this.m_downLevPos.x += UnityEngine.Random.Range(0, num2 - 1);
this.m_downLevPos.y += UnityEngine.Random.Range(2, num2);
}
else
{
this.m_downLevPos = this.m_upLevPos.Clone();
this.m_downLevPos.x += num2 - 1;
}
}
else
{
this.m_downLevPos = new IVec2(0, 0);
}
Assert.Message(this.m_downLevPos != null, "迷路作成で下り梯子を作成できませんでした");
IVec2 vec2 = new IVec2();
int num4 = 0;
for (int i = 0; i < num3; i++)
{
vec2 = this.GetEntryPoint();
if (vec2 != null)
{
vec2 *= num2;
vec2.x += UnityEngine.Random.Range(0, num2);
vec2.y += UnityEngine.Random.Range(1, num2);
int mineralID = 6 + mineLevel.mineLevel;
this.m_mineralList.AddStatus(mineralID, vec2);
num4++;
}
}
if (num4 == 0)
{
vec2 = entrancePos.Clone();
vec2.x = vec2.x / num2 * num2;
vec2.y = vec2.y / num2 * num2;
IVec2 vec3 = new IVec2();
IVec2 vec4 = entrancePos.Clone();
vec4.y--;
int num5 = 20;
do
{
vec3.x = vec2.x + UnityEngine.Random.Range(0, num2);
vec3.y = vec2.y + UnityEngine.Random.Range(1, num2);
}
while ((vec3 == entrancePos || vec3 == this.m_downLevPos || vec3 == vec4) && --num5 >= 0);
if (num5 < 0)
{
vec3 = entrancePos;
vec3.x++;
}
int mineralID2 = 6 + mineLevel.mineLevel;
this.m_mineralList.AddStatus(mineralID2, vec3);
}
Debug.Log(string.Concat(new object[]
{
"坑道サイズ(",
this.m_genMazeSize.x,
",",
this.m_genMazeSize.y,
")\n上り座標(",
entrancePos.x,
",",
entrancePos.y,
")\n下り座標(",
this.m_downLevPos.x,
",",
this.m_downLevPos.y,
")\n"
}));
}
// MazeData
private void GenerateMaze(IVec2 bPos)
{
this.m_createChip = 0;
int[] array = new int[]
{
0,
1,
2,
3
};
for (int i = 0; i < 4; i++)
{
int num = UnityEngine.Random.Range(0, 4);
int num2 = array;
array = array;
array = num2;
}
for (int j = 0; j < 4; j++)
{
IVec2 vec = bPos + this.m_mzGrid];
IVec2 vec2 = vec + this.m_mzGrid];
if (vec2.x >= 0 && vec2.x < this.m_genMazeSize.x && vec2.y >= 0 && vec2.y < this.m_genMazeSize.y && this.m_createChip == 1 && this.m_createChip == 1)
{
this.m_createChip = 0;
this.GenerateMaze(vec2);
}
}
}
// MazeData
private IVec2 GenerateMaze(IVec2 entrancePos, IVec2 size, int grid, int breakCount)
{
IVec2 vec = entrancePos.Clone();
this.m_createChip = null;
this.m_genMazeSize = size.Clone();
if (this.m_genMazeSize.x > this.m_size.x)
{
this.m_genMazeSize.x = this.m_size.x;
}
if (this.m_genMazeSize.y > this.m_size.y)
{
this.m_genMazeSize.y = this.m_size.y;
}
vec /= grid;
this.m_genMazeSize /= grid;
if (vec.x >= this.m_genMazeSize.x - 1)
{
vec.x = this.m_genMazeSize.x - 2;
}
if (vec.y >= this.m_genMazeSize.y - 1)
{
vec.y = this.m_genMazeSize.y - 2;
}
vec.x |= 1;
vec.y |= 1;
this.m_createChip = new int[this.m_genMazeSize.x, this.m_genMazeSize.y];
MazeData.ccc++;
Debug.Log(string.Concat(new object[]
{
MazeData.ccc,
" MazeSize = (",
this.m_genMazeSize.x,
",",
this.m_genMazeSize.y,
") grid=",
grid,
" start pos =",
vec.x,
",",
vec.y,
" / ",
entrancePos.x,
",",
entrancePos.y
}));
for (int i = 0; i < this.m_genMazeSize.y; i++)
{
for (int j = 0; j < this.m_genMazeSize.x; j++)
{
this.m_createChip = 1;
}
}
this.GenerateMaze(vec);
this.m_createChip = 0;
this.m_entryPoint.Clear();
IVec2 vec2 = new IVec2();
for (int k = 0; k < this.m_genMazeSize.y; k++)
{
for (int l = 0; l < this.m_genMazeSize.x; l++)
{
vec2.x = l;
vec2.y = k;
if (vec != vec2 && this.m_createChip == 0)
{
this.m_entryPoint.Add(vec2.Clone());
}
}
}
int num = breakCount * 4;
for (int m = 0; m < breakCount; m++)
{
vec2.x = UnityEngine.Random.Range(1, this.m_genMazeSize.x - 1);
vec2.y = UnityEngine.Random.Range(1, this.m_genMazeSize.y - 1);
bool flag = false;
for (int n = 0; n < 4; n++)
{
int num2 = Mathf.Clamp(vec2.x + this.m_sideVec.x, 0, this.m_genMazeSize.x - 1);
int num3 = Mathf.Clamp(vec2.y + this.m_sideVec.y, 0, this.m_genMazeSize.y - 1);
if (this.m_createChip == 0)
{
flag = true;
}
}
if (flag)
{
this.m_createChip = 0;
}
else if (--num >= 0)
{
m--;
}
}
this.ResetChip(1);
for (int num4 = 0; num4 < this.m_size.y; num4++)
{
for (int num5 = 0; num5 < this.m_size.x; num5++)
{
int num6 = num5 / grid;
int num7 = num4 / grid;
if (num6 >= 0 && num6 < this.m_genMazeSize.x && num7 >= 0 && num7 < this.m_genMazeSize.y && this.m_createChip == 0)
{
this.m_chip = 0;
}
}
}
vec *= grid;
vec.y += grid - 1;
return vec;
} 但是当到31层或者更高(记得不是很清了)这个方法就不适用了 ,应该是换了一系列代码导致下一层的楼梯不在那些位置了 殇丶丶丶 发表于 2018-4-12 18:51
但是当到31层或者更高(记得不是很清了)这个方法就不适用了 ,应该是换了一系列代码导致下一层的楼梯不在 ...
似乎是有的地图把3x3改成了4x4
然而梯子的位置一定还是在那四格之中
qweytr_1 发表于 2018-4-12 20:49
似乎是有的地图把3x3改成了4x4
然而梯子的位置一定还是在那四格之中
了解了:lol
膜拜大神!受益匪浅!{:3_113:} 这个属于意外情况吗?
666123123 发表于 2018-12-5 02:11
这个属于意外情况吗?
话说你到底挖了多少层……
这并不是意外情况
只是布局变成了4*4而已
而这一个布局中,梯子仍然在4*4布局的左上角
第八十层 一样的情况 本帖最后由 qweytr_1 于 2018-12-7 18:01 编辑
666123123 发表于 2018-12-5 23:34
第八十层 一样的情况
可以看出,同一编号的格子只有一个作用,即,有一格矿,什么都没有,或者有一个梯子
这张图是3x3的布局
每个3*3的格子,如果有东西(梯子/矿)就一定挖不到向下
而看上去是空的3*3的格子才有可能有向下的坑
而这样的空格子,只有左上角2*2的区域有可能是梯子
我的表述能力真的这么差吗
可以可以,很到位 NICE,很到位
页:
[1]