上一篇:【unity】11.胜利失败界面
需求梳理
我们发现真正的扫雷在游玩的时候可以做到点击数字自动开启附近的格子。参考下图:在数字“4”附近的格子任意放下4个旗子,然后点击数字“4”的格子,会自动开启附近的格子并出现雷。
在线扫雷网址
而在下图例子中,在数字“2”附近的格子放下2个旗子后,点击数字“1”的格子,会自动开启附近的格子并出现数字“3”
因此梳理规则如下:
- 只有点击数字格有这种效果,点击雷格和旗格无此效果。
- 并非点击所有数字格都有效,只有当数字格附近旗子数量>=数字格附近雷数量时才会自动开启。
- 玩家可能标错附近的旗子,因此自动开格子的时候可能会开出雷。考虑到我们之前DFS在遇雷格子时会自动停止,这里不能直接调用之前的DFS函数。
代码思路
梳理清需求后,我们可以使用这样的思路来编写代码:
- 在左键点击格子时,判断此格子为数字格时,如果附近旗子数量>=附近雷数量,则自动点击附近的空白格子。
- 数字格的判断方法为enable为false的格子,同时不含雷和旗子。
- 修改DFS函数的触发时机,改为只有空白格才能触发DFS函数。
代码编写
思路清晰后编写代码如下:
//左键点击格子
public void ClickMine(GameObject _button)
{
//前略
//如果点击的格子是旗子,则不执行任何操作
if (_button.GetComponent<MinesweeperButton>().GetHasFlag() == false)
{
if (bombList.Contains(_row * maxCol + _col))
{
//点中雷格的情况,此处省略
}
else //两个if后这里的情况为非其非雷,只有空白和数字格两种情况
{
//数字格的情况(不可点击,说明已经点击过了,所以是数字格)
if (_button.GetComponent<Button>().enabled == false)
{
//如果附近的雷数量<=附近的旗子数量少则自动点击附近格子,这里为了方便取附近旗子数量,复制粘贴了GetAroundBombNumber函数写了一个GetAroundFlagNumber函数。
if (GetAroundBombNumber(_row, _col) <= GetAroundFlagNumber(_row, _col))
{
//取附近空白格,这里写了个新函数来取
List<GameObject> _aroundButtons = GetAroundClickableButton(_row, _col);
//把附近的空白格全部点一遍
foreach(GameObject _aroundButton in _aroundButtons)
{
ClickMine(_aroundButton);
}
}
}
else //空白格的情况,这里改为只有空白格才执行DFS
{
DFSMine(_row, _col);
}
//后略
}
}
}
//复制粘贴了GetAroundBombNumber函数写了一个取附近旗子数量的函数
private int GetAroundFlagNumber(int _row, int _col)
{
int result = 0;
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
int _nRow = _row + i;
int _nCol = _col + j;
//各种非法边界情况,注意不取自己的格子
if (i == 0 && j == 0) { continue; }
if ((_nRow < 0) || (_nCol < 0) || (_nRow > maxRow - 1) || (_nCol > maxCol - 1)) { continue; }
if ((_nRow * maxCol + _nCol < 0) || (_nRow * maxCol + _nCol > maxRow * maxCol - 1)) { continue; }
//如果对应格子有旗子,则返回值+1
if (buttonList[_nRow * maxCol + _nCol].GetComponent<MinesweeperButton>().GetHasFlag()) { result++; }
}
}
return result;
}
//取附近的空白格
List<GameObject> GetAroundClickableButton(int _row, int _col)
{
List<GameObject> _resultButtonList = new();
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
//注意跳过自己的格子
if (i == 0 && j == 0) { continue; }
int _nRow = _row + i;
int _nCol = _col + j;
//去掉非法格子
if (!IsLegalMine(_nRow, _nCol)) { continue; }
GameObject _button = buttonList[_nRow * maxCol + _nCol];
//去掉点过的格子
if (_button.GetComponent<Button>().enabled == false) { continue; }
//去掉有旗子的格子
if (_button.GetComponent<MinesweeperButton>().GetHasFlag() == true) { continue; }
//注意这里没有去掉有雷的格子,因为这个函数返回的是附近可以点的格子,而带雷的格子开启前也是可以点的。这也导致我们在点击数字自动开启格子时可能开出雷
_resultButtonList.Add(_button);
}
}
return _resultButtonList;
}
运行结果
运行结果如下:
在错误地点放下旗子后点击数字格,开出雷导致游戏失败
在正确地点放下旗子,点击附近数字“1”后开出数字“3”
下一篇: