接上篇技術調研,本文完成需求分析 (明確做什麼、不做什麼) 與概要設計 (模塊劃分、接口契約、數據流),為詳細設計與編碼奠定基礎。
| 階段 | 玩家動作 | 視覺反饋 | 鍵盤映射 |
|---|---|---|---|
| 選擇棋子 | 方向鍵移動光標 | 黑框高亮當前光標位置 | UP/DOWN/LEFT/RIGHT |
| 確認選中 | 按確認鍵 | 綠框鎖定選中棋子主格 | FIRE (SELECT) |
| 選擇目標位置 | 方向鍵移動光標 | 紅框高亮目標區域 | UP/DOWN/LEFT/RIGHT |
| 執行移動 | 按確認鍵 | 棋子平滑移動 (幀動畫)、框消失 | FIRE |
| 取消選中 | 再次按確認鍵或軟鍵 | 綠/紅框消失、回到選擇階段 | FIRE / BACK |
四大核心概念區分 (記入數據字典):
選擇區域 (光標所在格) ≠ 選中區域 (已按 FIRE 鎖定的棋子主格) ≠ 要移動區域 (同選中區域) ≠ 要移動到區域 (目標空白區域)
五大核心類,單一職責原則:
| 類名 | 繼承/實現 | 核心職責 | 關鍵接口 |
|---|---|---|---|
| MIDlet1 | extends MIDlet | 應用生命週期、屏幕切換總控、退出處理 | startApp(), quitApp() |
| Images | final class | 圖片資源常量定義、加載、常量 (顏色、尺寸、角色 ID) | init(), 常量字段 |
| Draw | class | 通用繪圖工具:drawImage、drawRect、drawString 封裝 | paint(Graphics, ...) |
| Map | class | 地圖數據結構、外部文件讀取、邏輯坐標↔繪圖坐標轉換 | read_map(level), draw_map(Graphics), Grid[][] |
| Displayable1 | extends Canvas implements CommandListener | 遊戲主視圖、輸入處理、遊戲狀態機、繪圖調度 | paint(), keyPressed(), commandAction(), 內部輔助方法 |
// Images.java 常量定義
public final class Images {
public static final byte CAOCAO = 1, GUANYU = 2, ZHANGFEI = 3,
ZHAOYUN = 4, HUANGZHONG = 5, MACHAO = 6, ZU = 7;
public static final byte BLANK = 0, DLEFT = -1, DUP = -2, DLEFTUP = -3; // 合併格標記
public static final int WIDTH = 4, HEIGHT = 5; // 棋盤邏輯寬高
public static final int UNIT = 30; // 每格像素大小 (運行時動態計算)
public static Image image_Frame; // 背景圖
public static void init() { image_Frame = Image.createImage("/frame.png"); }
}
// Map.java 核心結構
public class Map {
public byte[][] Grid = new byte[HEIGHT][WIDTH]; // 邏輯棋盤
public int[] read_map(int level) { // 返回曹操初始位置 [x,y]
// 從 /map/level1.dat 讀取字節流填充 Grid
// 合併格標記:曹操左上格=CAOCAO, 右上=DLEFT, 左下=DUP, 右下=DLEFTUP
}
public void draw_map(Graphics g) { // 遍歷 Grid 調用 Draw.paint 繪製
}
}
paint(Graphics g):雙緩衝繪製入口,分發 drawMap/drawCursor/drawPieceskeyPressed(int keyCode):getGameAction 映射 → 分發 moveCursor/selectPiece/movePiecesetRange():光標移動後,根據 Grid 合併格標記修正光標到棋子主格、計算選中區域寬高setMoveRange():目標位置合法性檢查 (邊界、非空格、非選中區域內)Move():執行棋子移動,更新 Grid,處理合併格拆分/合併win():檢查曹操是否到達出口位置 Grid[HEIGHT-2][WIDTH-3] == CAOCAO// Displayable1 持有 Map 實例 private Map myMap = new Map(); // 初始化 int[] cursorPos = myMap.read_map(currentLevel); // 返回曹操左上角坐標 // 繪製 myMap.draw_map(g); // 內部遍歷 Grid 調用 Draw.paint // 邏輯判斷 byte cell = myMap.Grid[y][x]; // 直接訪問公共數組 (簡化設計) // 移動操作 // Displayable1 直接修改 myMap.Grid[][],移動後調用 repaint()
下篇進入詳細設計:Displayable1 完整狀態機圖、setRange/setMoveRange/Move 算法偽代碼、Map.read_map 文件格式規範、RMS 存儲鍵值設計、異常情況處理矩陣。