扫雷清除算法

3

我正试图用Flash重新制作扫雷游戏,已经放置了地雷和数字。但我似乎无法找出递归算法来扩展单击瓦片并清除其相邻瓦片。有两个数组,_map包含背景+地雷和数字,_clickable map包含位于背景上方的瓦片。因此,我所要求的基本上是递归帮助。如果这不够清楚,我会更新问题并提供必要的信息。

private function onClick(e:MouseEvent):void 
{
    trace("on Click");

    var symbol = e.currentTarget;
    var tempTileMask:TileMask = symbol;
    var tempTile:Tile = _map[tempTileMask.yCoord][tempTileMask.xCoord]

    if (tempTile.hasMine)
    {
        for (var i:int = _gridSize - 1; i >= 0; i--)
            for (var j:int = _gridSize - 1; j >= 0; j--)
            {
                var temp:TileMask = _clickableMap[i][j];
                removeChild(temp);
            }

        //explosion();

        //gameOver();
    }

    if (tempTile.hasNumber)
    {
        removeChild(tempTileMask);
        tempTile.cleared = true;
    }

    else
    {
        clearTiles(tempTile.xCoord, tempTile.yCoord);
    }
}

这是我修改后的清除地雷功能。
function clearTiles( x:int, y:int )
{
    // Get an object that contains the tile information for the location
    // we are checking
    if(_map[y][x] != null) 
    {
        var tempTile:Tile = _map[y][x];
        var tempTileMask:TileMask = _clickableMap[y][x];

        // Check if the location we are checking is out of the bounds of the
        // playable area

        trace(tempTile);
        if ( tempTile.outOfBounds(x, y) )
        {
            return;
        }

        // If the tile has already been revealed then there is nothing to do

        trace("before clearing");
        if ( tempTile.cleared )
        {
            trace("clearing tile");
            return;
        }

        // If the tile hasn't been revealed and it's an empty square we
        // reveal the location then call this function again for each
        // surrounding block

        trace("before check for surrounding tiles");
        if ( tempTile.hasNumber != true && tempTile.hasMine != true )
        {
            trace("check for surrounding tiles");

            // Remove the mask hiding the tiles property
            removeChild( tempTileMask );
            // Set the tile as cleared
            tempTile.cleared = true;

            if(_map[tempTile.yCoord][tempTile.xCoord - 1] != null)
            {
                var tile1:Tile =_map[tempTile.yCoord][tempTile.xCoord - 1]

                if(!tile1.cleared)
                    clearTiles( tempTile.xCoord - 1 , tempTile.yCoord ); //Check tile to the left
            }

            if(_map[tempTile.yCoord][tempTile.xCoord + 1] != null)
            {
                var tile2:Tile =_map[tempTile.yCoord][tempTile.xCoord + 1]

                if(!tile2.cleared)
                    clearTiles( tempTile.xCoord + 1 , tempTile.yCoord ); //Check tile to the left
            }

            if(_map[tempTile.yCoord - 1][tempTile.xCoord] != null)
            {
                var tile3:Tile =_map[tempTile.yCoord - 1][tempTile.xCoord]

                if(!tile3.cleared)
                    clearTiles( tempTile.xCoord, tempTile.yCoord - 1 ); //Check tile to the left
            }

            if(_map[tempTile.yCoord + 1][tempTile.xCoord] != null)
            {
                var tile4:Tile =_map[tempTile.yCoord + 1][tempTile.xCoord]

                if(!tile4.cleared)
                    clearTiles( tempTile.xCoord, tempTile.yCoord + 1 ); //Check tile to the left
            }

            if(_map[tempTile.yCoord - 1][tempTile.xCoord - 1] != null)
            {
                var tile5:Tile =_map[tempTile.yCoord - 1][tempTile.xCoord - 1]

                if(!tile5.cleared)
                    clearTiles( tempTile.xCoord - 1, tempTile.yCoord - 1 ); //Check tile to the left
            }

            if(_map[tempTile.yCoord + 1][tempTile.xCoord + 1] != null)
            {
                var tile6:Tile =_map[tempTile.yCoord + 1][tempTile.xCoord + 1]

                if(!tile6.cleared)
                    clearTiles( tempTile.xCoord + 1, tempTile.yCoord + 1 ); //Check tile to the left
            } 

            if(_map[tempTile.yCoord - 1][tempTile.xCoord + 1] != null)
            {
                var tile7:Tile =_map[tempTile.yCoord - 1][tempTile.xCoord + 1]

                if(!tile7.cleared)
                    clearTiles( tempTile.xCoord + 1, tempTile.yCoord - 1 ); //Check tile to the left
            }


            if(_map[tempTile.yCoord + 1][tempTile.xCoord - 1] != null)
            {
                var tile8:Tile =_map[tempTile.yCoord + 1][tempTile.xCoord - 1]

                if(!tile8.cleared)
                    clearTiles( tempTile.xCoord - 1, tempTile.yCoord + 1 ); //Check tile to the left
            }
        }
    }
    else
        return;

}
1个回答

4

如果我弄错了actionscript语法,请谅解。我只是喜欢递归函数,所以我必须回答这个问题。我将粘贴代码并提供最准确的注释。如果您有任何问题,请问。我相信您可以将任何需要转换为适当的函数调用、属性引用等。

// Function to check if a tile is an empty space and then call
// itself for the surrounding tiles

function clearTiles( x:int, y:int ):void
{
    // Check if the location we are checking is out of the bounds of the
    // playable area
    if ( outOfBounds( x, y ) )
    {
        return;
    }

    // Get an object that contains the tile information for the location
    // we are checking
    var tempTile:Tile = _map[x][y];


    // If the tile has already been revealed then there is nothing to do
    if ( tempTile.cleared )
    {
        return;
    }

    // If the tile is a number then reveal it and return without checking
    // surrounding tiles
    var tempTileMask:DisplayObject = getTileMask(x,y);
    // since we're no longer in the click handler context, we need
    // to initialize the variable with something [TODO]
    if ( tempTile.hasNumber )
    {
        removeChild( tempTileMask );
        tempTile.cleared = true;
        return;
    }


    // If the tile hasn't been revealed and it's an empty square we
    // reveal the location then call this function again for each
    // surrounding block

    if ( tempTile.isEmpty )
    {
        // Remove the mask hiding the tiles property
        removeChild( tempTileMask );
        // Set the tile as cleared
        tempTile.cleared = true;

        clearTiles( tempTile.x - 1 , tempTile.y ); //Check tile to the left
        clearTiles( tempTile.x + 1 , tempTile.y ); //Check tile to the right
        clearTiles( tempTile.x , tempTile.y - 1 ); //Check tile above
        clearTiles( tempTile.x , tempTile.y + 1 ); //Check tile below
    }

}

您需要创建一个outOfBounds()函数,仅检查被检查的X和Y是否大于当前游戏板。看起来您引用了_gridSize作为静态数字,因此我假设您所有的游戏板都是正方形的(例如:4x4、9x9、120x120)。在这种情况下,您可以使用以下内容:

function outOfBounds( int x, int y )
{
    if ( x < 0 )
    {
        return true;
    }

    if ( y < 0 )
    {
        return true;
    }

    if ( x > _gridSize - 1 )
    {
        return true;
    }

    if ( y > _gridSize -1 )
    {
        return true;
    }

    return false;
}

tempTile.outOfBounds()是什么意思?这是我需要编写的函数,还是Flash的一部分,检查数组的边界,我不知道呢? - user3523222
我刚刚添加了一个编辑以帮助澄清。因为我引用了超出数组边界的数组元素,所以我有很多崩溃的经验。所以现在处理数组时,我首先要确保我不引用不存在的东西。我给你的代码肯定不能只是复制粘贴,但希望你能看到我如何构建递归函数,并传递任何你认为合适的参数。 - Stack of Pancakes
你能否编辑一下你的原始帖子,这样我就可以看到你是如何实现它的?其思路是检查一个方块,如果它是空的,就会揭示它,然后立即调用相邻每个方块的同一函数(北、南、东、西)。 - Stack of Pancakes
阅读您的编辑,我似乎找不到它失败的地方,除非您是在谈论数字瓷砖没有被揭示。老实说,我认为如果您包括我编辑的 if (tempTile.hasNumber) 部分,那么它应该可以正常工作。如果还有问题,请随时在这里跟进。 - Stack of Pancakes
我在Flash中一直遇到这个错误,但是一切似乎都清除得很好。TypeError: Error #1010: 术语未定义且没有属性。 在GameLoop / clearTiles()处 在GameLoop / clearTiles()处 在GameLoop / onClick()处 - user3523222
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接