- 扫雷游戏
让我们一起来玩扫雷游戏!
给定一个代表游戏板的二维字符矩阵。 ‘M’ 代表一个未挖出的地雷,‘E’ 代表一个未挖出的空方块,‘B’ 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的已挖出的空白方块,数字(‘1’ 到 ‘8’)表示有多少地雷与这块已挖出的方块相邻,‘X’ 则表示一个已挖出的地雷。
现在给出在所有未挖出的方块中(‘M’或者’E’)的下一个点击位置(行和列索引),根据以下规则,返回相应位置被点击后对应的面板:
如果一个地雷('M')被挖出,游戏就结束了- 把它改为 'X'。
如果一个没有相邻地雷的空方块('E')被挖出,修改它为('B'),并且所有和其相邻的未挖出方块都应该被递归地揭露。
如果一个至少与一个地雷相邻的空方块('E')被挖出,修改它为数字('1'到'8'),表示相邻地雷的数量。
如果在此次点击中,若无更多方块可被揭露,则返回面板。
示例 1:
输入:
[[‘E’, ‘E’, ‘E’, ‘E’, ‘E’],
[‘E’, ‘E’, ‘M’, ‘E’, ‘E’],
[‘E’, ‘E’, ‘E’, ‘E’, ‘E’],
[‘E’, ‘E’, ‘E’, ‘E’, ‘E’]]
Click : [3,0]
输出:
[[‘B’, ‘1’, ‘E’, ‘1’, ‘B’],
[‘B’, ‘1’, ‘M’, ‘1’, ‘B’],
[‘B’, ‘1’, ‘1’, ‘1’, ‘B’],
[‘B’, ‘B’, ‘B’, ‘B’, ‘B’]]
扫雷游戏可dfs
或者bfs
- 先检查当前递归节点是否是
周围埋雷的点
,是就标记个数并停止递归 - 不是,就向下递归她的
8
个方向
void dfs(vector<vector<char> >& mtx, int r, int c) {
int cnt = 0;
for(int i=0; i<8; i++) {
int nr = r + dr[i],
nc = c + dc[i];
if(nr<0 || nc<0 || nr>=n || nc>=m) continue ;
cnt += (mtx[nr][nc] == 'M');
}
if(cnt) { //周围有雷,标记并退出
mtx[r][c] = '0' + cnt;
return ;
}
mtx[r][c] = 'B';
for(int i=0; i<8; i++) {
int nr = r + dr[i],
nc = c + dc[i];
if(nr<0 || nc<0 || nr>=n || nc>=m) continue ;
if(mtx[nr][nc] == 'E') dfs(mtx, nr, nc);
}
}
bfs
思路是一致的
queue<Node> q;
q.push( {v[0], v[1]} );
memset(vis, false, sizeof(vis));
while(!q.empty()) {
Node& now = q.front();
vis[now.r][now.c] = true;
int cnt = 0;
for(int i=0; i<8; i++) {
int nr = now.r + dr[i],
nc = now.c + dc[i];
if(nr<0 || nc<0 || nr>=n || nc>=m) continue ;
cnt += (mtx[nr][nc] == 'M');
}
if(cnt) {
mtx[now.r][now.c] = '0' + cnt;
goto POPIT;
}
mtx[now.r][now.c] = 'B';
for(int i=0; i<8; i++) {
int nr = now.r + dr[i],
nc = now.c + dc[i];
if(nr<0 || nc<0 || nr>=n || nc>=m) continue ;
if(!vis[nr][nc] && mtx[nr][nc]=='E') {
vis[nr][nc] = true;
q.push( {nr, nc} );
}
}
POPIT :
q.pop();
}
完整代码
#define debug
#ifdef debug
#include <time.h>
#endif
#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <math.h>
#define MAXN ((int)1e5+7)
#define ll long long int
#define INF (0x7f7f7f7f)
#define fori(lef, rig) for(int i=lef; i<=rig; i++)
#define forj(lef, rig) for(int j=lef; j<=rig; j++)
#define fork(lef, rig) for(int k=lef; k<=rig; k++)
#define QAQ (0)
using namespace std;
#define show(x...) \
do { \
cout << "\033[31;1m " << #x << " -> "; \
err(x); \
} while (0)
void err() { cout << "\033[39;0m" << endl; }
template<typename T, typename... A>
void err(T a, A... x) { cout << a << ' '; err(x...); }
namespace FastIO{
char print_f[105];
void read() {}
void print() { putchar('\n'); }
template <typename T, typename... T2>
inline void read(T &x, T2 &... oth) {
x = 0;
char ch = getchar();
ll f = 1;
while (!isdigit(ch)) {
if (ch == '-') f *= -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - 48;
ch = getchar();
}
x *= f;
read(oth...);
}
template <typename T, typename... T2>
inline void print(T x, T2... oth) {
ll p3=-1;
if(x<0) putchar('-'), x=-x;
do{
print_f[++p3] = x%10 + 48;
} while(x/=10);
while(p3>=0) putchar(print_f[p3--]);
putchar(' ');
print(oth...);
}
} // namespace FastIO
using FastIO::print;
using FastIO::read;
int n, m, Q, K;
int dr[] = { 1, -1, 0, 0, 1, 1, -1, -1 },
dc[] = { 0, 0, 1, -1, 1, -1, 1, -1 };
int vis[64][64], timer;
struct Node {
int r, c;
} ;
class Solution {
public:
void dfs(vector<vector<char> >& mtx, int r, int c) {
int cnt = 0;
for(int i=0; i<8; i++) {
int nr = r + dr[i],
nc = c + dc[i];
if(nr<0 || nc<0 || nr>=n || nc>=m) continue ;
cnt += (mtx[nr][nc] == 'M');
}
if(cnt) {
mtx[r][c] = '0' + cnt;
return ;
}
mtx[r][c] = 'B';
for(int i=0; i<8; i++) {
int nr = r + dr[i],
nc = c + dc[i];
if(nr<0 || nc<0 || nr>=n || nc>=m) continue ;
if(mtx[nr][nc] == 'E') dfs(mtx, nr, nc);
}
}
vector<vector<char>> updateBoard(vector<vector<char>>& mtx, vector<int>& v) {
n = mtx.size(), m = mtx[0].size();
if(mtx[v[0]][v[1]] == 'M') {
mtx[v[0]][v[1]] = 'X';
return mtx;
}
if(mtx[v[0]][v[1]] != 'E') return mtx;
#if 1
queue<Node> q;
q.push( {v[0], v[1]} );
memset(vis, false, sizeof(vis));
while(!q.empty()) {
Node& now = q.front();
vis[now.r][now.c] = true;
int cnt = 0;
for(int i=0; i<8; i++) {
int nr = now.r + dr[i],
nc = now.c + dc[i];
if(nr<0 || nc<0 || nr>=n || nc>=m) continue ;
cnt += (mtx[nr][nc] == 'M');
}
if(cnt) {
mtx[now.r][now.c] = '0' + cnt;
goto POPIT;
}
mtx[now.r][now.c] = 'B';
for(int i=0; i<8; i++) {
int nr = now.r + dr[i],
nc = now.c + dc[i];
if(nr<0 || nc<0 || nr>=n || nc>=m) continue ;
if(!vis[nr][nc] && mtx[nr][nc]=='E') {
vis[nr][nc] = true;
q.push( {nr, nc} );
}
}
POPIT :
q.pop();
}
#else
dfs(mtx, v[0], v[1]);
#endif
return mtx;
}
};
#ifdef debug
signed main() {
vector<vector<char> > vec = {{'E', 'E', 'E', 'E', 'E'},
{'E', 'E', 'M', 'E', 'E'},
{'E', 'E', 'E', 'E', 'E'},
{'E', 'E', 'E', 'E', 'E'}};
Solution s;
vector<int> pos = { 3, 0 };
vec = s.updateBoard(vec, pos);
for(int i=0; i<vec.size(); i++) {
for(int j=0; j<vec[i].size(); j++) printf("[%c] ", vec[i][j]);
printf("\n");
}
return 0;
}
#endif