https://leetcode.com/problems/minesweeper/
지뢰 찾기 중 다음으로 클릭할 정보가 주어진다. 해당 클릭 정보를 누른 후 보드 상태 반환하기
보드 정보
M : 아직 누르지 않은 지뢰 있는 칸
E : 아직 누르지 않은 빈 칸
B : 누른 상태에서 빈 칸
digit : 누른 상태에서 숫자 칸 (숫자는 상하좌우 및 대각선 주변의 지뢰 개수)
X : 누른 상태에서 지뢰
Rule
1) M을 누르면 X로 변경한 후 게임 종료
2) E를 눌렀을 때 만약 주변에 인접한 지뢰가 없으면 B로 변경 후 주변의 (상하좌우 및 대각선) 모든 빈 칸 열기
3) E를 눌렀을 때 주변에 인접한 지뢰가 있으면 해당되는 숫자로 변경
public class Solution {
public char[][] UpdateBoard(char[][] board, int[] click) {
// bfs direction (상하좌우대각선)
int[] dirX = new int[8] {1, -1, 0, 0, 1, 1, -1, -1};
int[] dirY = new int[8] {0, 0, 1, -1, 1, -1, 1, -1};
bool[,] visited = new bool[board.Length,board[0].Length];
Queue<int[]> queue = new Queue<int[]>();
queue.Enqueue(click);
while (queue.Count >= 1)
{
int[] currentPos = queue.Dequeue();
if (visited[currentPos[0], currentPos[1]]) continue; // 방문했으면 넘기기
visited[currentPos[0], currentPos[1]] = true;
switch (board[currentPos[0]][currentPos[1]])
{
case 'M': // 현재 누른게 지뢰면 x로 바꾸고 바로 종료
board[currentPos[0]][currentPos[1]] = 'X';
return board;
case 'E': // 빈 칸이면 B되야하는지 Digit 되야하는지 체크
UpdateSquare(currentPos);
break;
}
}
return board;
void UpdateSquare(int[] currPos)
{
int adjacentMineCnt = 0;
List<int[]> adjacentEList = new List<int[]>();
for (int i = 0; i < 8; i++)
{
int x = currPos[0] + dirX[i];
int y = currPos[1] + dirY[i];
if (x >= board.Length || x < 0 || y >= board[0].Length || y < 0) continue; // board 범위 밖
switch (board[x][y])
{
case 'M': // 주변 지뢰면 지뢰 개수 업데이트
adjacentMineCnt += 1;
break;
case 'E': // 주변 빈 칸이면 지뢰 개수 0일 때 방문해야 하므로 저장
adjacentEList.Add(new int[2] {x, y});
break;
}
}
if (adjacentMineCnt >= 1) // digit 되는 케이스 -> 그냥 digit으로 변경
{
board[currPos[0]][currPos[1]] = (char) (adjacentMineCnt + '0');
}
else // 주변 0이라 B되는 케이스 -> 주변 E들 큐에 넣고 B로 변경
{
foreach (int[] pos in adjacentEList)
{
queue.Enqueue(pos);
}
board[currPos[0]][currPos[1]] = 'B';
}
}
}
}