LeetCode第529题:扫雷游戏

让我们一起来玩扫雷游戏!

给你一个大小为 m x n 二维字符矩阵 board ,表示扫雷游戏的盘面,其中:

'M' 代表一个 未挖出的 地雷,
'E' 代表一个 未挖出的 空方块,
'B' 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的 已挖出的 空白方块,
数字('1' 到 '8')表示有多少地雷与这块 已挖出的 方块相邻,
'X' 则表示一个 已挖出的 地雷。
给你一个整数数组 click ,其中 click = [clickr, clickc] 表示在所有 未挖出的 方块('M' 或者 'E')中的下一个点击位置(clickr 是行下标,clickc 是列下标)。

根据以下规则,返回相应位置被点击后对应的盘面:

如果一个地雷('M')被挖出,游戏就结束了- 把它改为 'X' 。
如果一个 没有相邻地雷 的空方块('E')被挖出,修改它为('B'),并且所有和其相邻的 未挖出 方块都应该被递归地揭露。
如果一个 至少与一个地雷相邻 的空方块('E')被挖出,修改它为数字('1' 到 '8' ),表示相邻地雷的数量。
如果在此次点击中,若无更多方块可被揭露,则返回盘面。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minesweeper
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路: 

        题目要求点击一个方块时,若该方块周围(最多8个方块)都不是雷,则需要点击周围方块。

所以采用递归的方式点击。

        构建递归函数void dfs(....)。需传递矩阵board信息和点击位置(x,y)。

1、检测位置是否合法。越界 或者 该位置已被点开,直接退出。

2、检测是否点到了地雷。是地雷则只需简单修改该位置的值,然后退出。

3、不是雷。获取周围有地雷个数num(构建一个新的函数实现)。

        若num>0:周围有地雷,只需简单修改矩阵信息即可退出,不用点击周围的方块。

        若num== 0:要递归点击周围的方块。遍历周围8个格子,依次调用dfs。

//获取周围地雷个数
int get_bombs(char** board,int m,int n,int x,int y){
    int new_x,new_y;
    int num = 0;
    for(int i = -1;i<2;i++)
        for(int j = -1 ;j<2;j++){
            if(i==0 && j==0)
                continue;
            new_x = x + i;
            new_y = y + j;
            if(new_x < 0 || new_x >= m || new_y < 0 || new_y >= n)  //出界了
                continue;
            if(board[new_x][new_y] == 'M')
                num++;
        }
    return num;
}


//递归点击
void dfs(char**board,int m, int n,int x,int y){
    //该位置已被点击,直接退出
    if(board[x][y] != 'M' && board[x][y] != 'E')
        return board;
    //点到地雷
    if(board[x][y] == 'M'){
        board[x][y] = 'X';
        return;
    }
    //不是地雷
    int num = get_bombs(board,m,n,x,y); // 获取x,y周围地雷个数
    if(num > 0){
        board[x][y] = '0' + num;
        return;
    }
    //周围没雷,需递归点击周围每个格子
    board[x][y] = 'B';
    int new_x,new_y;
    for(int i  = -1;i<2;i++)
        for(int j = -1;j<2;j++){
            if(i == 0 && j == 0)
                continue;
            new_x = x + i;
            new_y = y + j;
            if(new_x < 0 || new_x >= m || new_y < 0 || new_y >= n)  //出界了
                continue;
            dfs(board,m,n,new_x,new_y);
        }
    return;
}

char** updateBoard(char** board, int boardSize, int* boardColSize, int* click, int clickSize, int* returnSize, int** returnColumnSizes){
    int m = boardSize,n = boardColSize[0];
    *returnSize = boardSize;
    (*returnColumnSizes) = malloc(sizeof(int)*m);
    for(int i =0;i<m;i++)
        (*returnColumnSizes)[i] = boardColSize[i];

    if(clickSize < 2)
        return board;
    //点击位置不对
    int x = click[0],y = click[1];
    if(x < 0 || x >= m || y < 0 || y >= n)
        return board;

    //点击(x,y)处
    dfs(board,m,n,x,y);

    return board;

}

运行结果如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值