乐趣区

扫雷游戏开发基本思路

今天给大家介绍传统扫雷游戏的制作思路吧,为什么选择这个游戏呢?
1. 它太金典了,金典到我们都知道,都玩过,都会玩;
2. 它也是一个轻量级的小游戏,比较简单。

我们先来捋一下扫雷游戏中的要素:
从上到下的 UI:遮罩层——> 雷层——> 数字层——> 底层背景层。

下面来介绍一下制作流程:
1. 我们制作的时候需要从底层开始做起,首先是底层背景层,只需要一张图片就 ok 了, 作为游戏的背景;
2. 按道理来水,我们应该接下来做数字显示层。可能有些朋友和我一样,一开始认为是先把数字标好再去布雷,其实应该是先布雷,再根据布雷情况给每个格子标数字,所以我们接下来是做雷层。
在这里提供给大家最简单的布雷思路:遍历 nm 个格子,每个格子随机指定是否是雷。为了不让生成雷的概率过大,我们可以根据概率来决定是否生成雷。
3. 生成每个格子的遮罩层: 遍历 nm 个格子,分别创建一个 Button。
4. 根据玩家点击的格子位置,判断周围 8 个格子雷的数量显示数字。

现在我就来剖析一下扫雷的制作思路:
1. 创建地图,并随机生成雷
   在这里我们创建一个 m * n 的地图,用二维数组存储地图信息,0 代表无雷,1 代表又雷。由于 ts 不能直接使用二维数组,需要借助一维数组帮助,使用方法如下:

let arr = new Array();
for (let i = 0; i < m; i++) 
{arr[i] = new Array();
    for (let j = 0; j < n; j++)   
    {
        let num;//num= 0 或 num=-1
        arr[i][j] = num;
    }
}  

2. 判断当前点击的是否是雷。
在玩家点击了一个 i 格子时,我们需要判断接下来游戏的状态:
1. 如果不是雷,则计算该格子周围雷的个数。我们需要计算格子周围 8 个数中雷的个数,显示在当前格子上。如下图:

// 不是炸弹,创建数字
            else {if (evt.currentTarget.x - this.currentCellW == this.bowContainer.getChildAt(i).x && evt.currentTarget.y - this.currentCellH == this.bowContainer.getChildAt(i).y) {this.bowNum++;}
                if (evt.currentTarget.x - this.currentCellW == this.bowContainer.getChildAt(i).x && evt.currentTarget.y == this.bowContainer.getChildAt(i).y) {this.bowNum++;}
                if (evt.currentTarget.x - this.currentCellW == this.bowContainer.getChildAt(i).x && evt.currentTarget.y + this.currentCellH == this.bowContainer.getChildAt(i).y) {this.bowNum++;}
                if (evt.currentTarget.x == this.bowContainer.getChildAt(i).x && evt.currentTarget.y - this.currentCellH == this.bowContainer.getChildAt(i).y) {this.bowNum++;}
                if (evt.currentTarget.x == this.bowContainer.getChildAt(i).x && evt.currentTarget.y + this.currentCellH == this.bowContainer.getChildAt(i).y) {this.bowNum++;}
                if (evt.currentTarget.x + this.currentCellW == this.bowContainer.getChildAt(i).x && evt.currentTarget.y - this.currentCellH == this.bowContainer.getChildAt(i).y) {this.bowNum++;}
                if (evt.currentTarget.x + this.currentCellW == this.bowContainer.getChildAt(i).x && evt.currentTarget.y == this.bowContainer.getChildAt(i).y) {this.bowNum++;}
                if (evt.currentTarget.x + this.currentCellW == this.bowContainer.getChildAt(i).x && evt.currentTarget.y + this.currentCellH == this.bowContainer.getChildAt(i).y) {this.bowNum++;}
            }
       textNum.text = this.bowNum.toString();

2. 如果是雷,则显示所有雷,游戏失败。在第一步生成地图的时候我们顺便也应该生成雷,这时候我们比较友好的做法是把所有的雷装进一个雷的数组,方便这里失败时的显示。

/// 点击某个方格后显示对应信息
        // 遍历雷,看当前对象是否是雷
        for (var i = 0; i < this.bowContainer.numChildren; i++) {
            // 如果是雷,显示所有雷
            if (evt.currentTarget.x == this.bowContainer.getChildAt(i).x && evt.currentTarget.y == this.bowContainer.getChildAt(i).y) {this.gamePanel.addChildAt(this.bowContainer, 4);
                this.failM.play(0, 1);
                // 地图上所有按钮不可点击
                this.lockAllBtn();
                this.showBannerAd("adunit-4a5e80c193902450");
                // this.showVideoAd("adunit-4ad7c6693898c4b0", this.VideoAdSuccess, this.VideoAdfail);
                break;
            }

3. 自动展开无雷区域
   先给大家讲讲标题的含义。即当前点击的格子不是雷,寻找周围的 8 个格子,如果 8 个格子中其中至少有一个不存在雷,找到该种格子,继续寻找周围 8 个格子判断是否存在不为雷的。如此反复迭代
上述方法采用的是迭代递归的思想,其实该方法效率并不高,但作为初学者我们能实现此功能就 ok 了。
4. 胜利判断
   就差最后一步了,当然是判断胜利了,其实方法很简单,只需要判断剩下未点击的格子数是否等于雷的个数。
扫雷的算法就介绍给大家了,这个算法是我第一次做扫雷时候使用的,可能不是特别完美,有什么建议或意见的,大家可以在下方留言哦!

退出移动版