本專案完整復刻 Windows 經典掃雷遊戲於 J2ME 平台,採用 MIDlet 入口控制 + Canvas 自繪 + 遞迴展開演算法 架構,展示行動遊戲開發核心知識點:陣列操作、事件監聽、多執行緒、幾何座標轉換、狀態機管理。
gameStart.midlet = this),供 Canvas 回調控制生命週期myCanvas 實例建立/銷毀與顯示切換destroyApp(false); notifyDestroyed();遊戲邏輯與渲染核心,關鍵成員:
int[][] map = new int[8][8]:地圖狀態矩陣(0=未揭開, 10=空白, 1-8=數字, 20=地雷)Image offScreen + Graphics offg:雙緩衝離屏繪圖,消除閃爍int px, py:游標像素座標(格子大小 20px)boolean gameOver, gameWin:遊戲結束狀態旗標void initMap() {
for (int n = 0; n < mineNumber; n++) {
int tmp = Math.abs(r1.nextInt() % 64);
int row = tmp / 8, col = tmp % 8;
if (map[row][col] != 20) map[row][col] = 20;
else n--; // 重試避免重複佈雷
}
}
checkNum(int r, int c) 遍歷 8 方向鄰居,統計值為 20 的格子數。邊界檢查使用硬編碼 0 與 7(8x8 固定棋盤)。
void check(int row, int col) {
if (map[row][col] == 20) { gameOver = true; return; }
int k = checkNum(row, col);
if (k > 0) { map[row][col] = k; return; }
// k == 0:遞迴展開 8 鄰居
map[row][col] = 10; // 標記為已揭開空白
// 8 方向遞迴呼叫 check()...
}
關鍵點:以 map[r][c] < 10 判斷「未揭開」狀態,避免重複遞迴導致堆疊溢位。
void checkWin() {
int count = 0;
for (所有格子) if (map[i][j] > 0) count++; // 已揭開格子數
if (count + mineNumber == 64) gameWin = true;
}
void keyPressed(int n) {
// 導航鍵移動游標(20px/格)
int action = getGameAction(n);
switch (action) {
case Canvas.UP: if (py >= 20) py -= 20; break;
case Canvas.DOWN: if (py <= 120) py += 20; break;
case Canvas.LEFT: if (px >= 20) px -= 20; break;
case Canvas.RIGHT: if (px <= 120) px += 20; break;
case Canvas.FIRE: // 確認鍵
int row = py / 20, col = px / 20;
check(row, col);
checkWin();
break;
}
repaint(); serviceRepaints();
}
paint(Graphics g) 呼叫順序:drawMap() → drawCricle()(游標) → 結束畫面覆蓋 → g.drawImage(offScreen, 0, 0, 0) 一次性呈現。
| 知識點 | 本專案體現形式 |
|---|---|
| 雙緩衝繪圖 | Image.createImage() + getGraphics() 離屏合成 |
| 狀態機 | gameOver/gameWin 控制渲染分支 |
| 遞迴演算法 | 洪水填充展開空白區域 |
| 座標系統轉換 | 像素座標 ⇄ 格子索引 互轉 |
| 資源管理 | try-catch 載入 PNG 圖片資源 |
此專案為 J2ME 遊戲開發入門極佳範例,程式碼結構清晰、邏輯自包含,適合作為教學參考或快速原型基礎。