這個題仍是規矩比較多的,尤爲是一開始打算用C語言作(本人學習密碼編碼學,算法工程上都是用C實現,因此刻意練習用C寫算法)。一看到那個C語言提交的模板就傻了,那參數多的啊……果斷C++寫!算法
好了,廢話很少說!數組
給出click的位置,要求問你click以後的遊戲面板會變成啥子模樣~
若是你不當心點到了雷,那就顯示一個 ‘X’ ,遊戲天然結束(和掃雷同樣~)
不然就須要去處理不少東西了,你想一想看,本身玩掃雷的時候,是否是一點就空出來一大片,這就是根據這個算法去處理的。處理的規則是什麼呢??markdown
若是你點到的周圍有雷,那麼就不繼續了,只留下八個方向上雷的個數,告訴玩家。ide
若是你點到的八個方向上一個雷也沒有,那就由 ‘E’ 變成 ‘B’ 。至關於告訴玩家,你點過了,這也是爲什麼你掃雷遊戲有時候一點空出一大片的緣由。就是由於這個位置周圍沒有雷,因此直接顯示成 ‘E’ !!性能
好了,規則其實也就這麼兩點啦,是本身太浮躁一開始沒看進去啦~學習
而後如何編碼實現呢?給出一個click的點,而後你能夠獲得click的行 r 和 列 c,若是這個位置就是雷,那麼直接表示成 ‘X’ ,本次 click 結束!不然進入dfs()!編碼
具體怎麼去 dfs 呢?首先初始化的面板只有 ‘M’ 和 ‘E’ ,因此可以進入 dfs() 就說明你當前是 ‘E’,因此須要先判斷它周圍有無雷,有的話,求出有多少,而後此處的位置改爲數字便可!改爲數字以後這個位置也不須要繼續下去了~不然就說明這個位置周圍沒有雷,就改爲 ‘B’,表明是個周圍沒有雷的,且已經點擊過的地方!!而後朝着八個方向去遞歸,而遞歸的出口如何處置呢?咱們能夠設置一個狀態記錄的數組,若是當前的點是已經處理過的,那就return,就行了!atom
class Solution { public: int dir[8][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}}; int vis[50][50] = {0}; void dfs(int x, int y, vector<vector<char>>& board){ if(vis[x][y]) return ; vis[x][y] = 1; int cnt = 0; for(int i = 0;i < 8;++i){ int dx = x + dir[i][0]; int dy = y + dir[i][1]; if(dx >= 0 && dx < (int)board.size() && dy >= 0 && dy < (int)board[0].size()){ if('M' == board[dx][dy]) cnt++; } } if(cnt > 0){ board[x][y] = cnt + '0'; } else{ board[x][y] = 'B'; for(int i = 0;i < 8;++i){ int dx = x + dir[i][0]; int dy = y + dir[i][1]; if(dx >= 0 && dx < (int)board.size() && dy >= 0 && dy < (int)board[0].size()) if(!vis[dx][dy]) dfs(dx, dy, board); } } } vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) { int r = click[0], c = click[1]; if('M' == board[r][c]) board[r][c] = 'X'; else dfs(r, c, board); return board; } };
這個性能很不理想啊,但願有提出更好的解決方案的同仁前輩,不吝賜教!spa
有不少人會問,爲什麼樣例的正上方還有一個 ‘E’ 沒有被處理呢??
其實很簡單,由於從click的位置出發,在遇到這個 ‘E’ 以前,會遇到周圍有雷的位置,遇到這些位置的時候,就會中止遞歸處理了!因此沒法處理這個 ‘E’ ~
其實你去玩掃雷這個遊戲,也會發現,人家也就是這麼處理的!code
因爲本人能力有限,若是有寫錯或者有瑕疵的地方,還請各位不吝賜教!但願可以經過留言私信,獲得您的指教!