首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java 貪食蛇小遊戲原始碼深度剖析

     編輯:Java 程式設計入門

專案架構概覽

本專案採用經典的 MVC 分層思想,包含兩個核心類別:

  • GreedSnake(視圖/控制層):繼承 JFrame,負責遊戲視窗建構、鍵盤事件監聽、畫面重繪、分數顯示與遊戲循環啟動。
  • SnakeModel(模型層):實作 Runnable,封裝蛇身移動邏輯、食物生成、碰撞檢測、計分規則、速度控制與暫停/繼續狀態管理。

視圖層關鍵實現細節

視窗與元件佈局

public GreedSnake() {
    mainFrame = new JFrame("GreedSnake");
    Container cp = mainFrame.getContentPane();
    
    // 頂部分數標籤
    labelScore = new JLabel("Score:");
    cp.add(labelScore, BorderLayout.NORTH);
    
    // 中央繪圖畫布
    paintCanvas = new Canvas();
    paintCanvas.setSize(canvasWidth+1, canvasHeight+1);
    paintCanvas.addKeyListener(this);
    cp.add(paintCanvas, BorderLayout.CENTER);
    
    // 底部操作提示面板
    JPanel panelButtom = new JPanel(new BorderLayout());
    // ... 新增三行 JLabel 提示鍵位 ...
    cp.add(panelButtom, BorderLayout.SOUTH);
    
    mainFrame.addKeyListener(this);
    mainFrame.pack();
    mainFrame.setResizable(false);
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainFrame.setVisible(true);
    begin(); // 啟動遊戲邏輯執行緒
}

鍵盤事件處理策略

實作 KeyListener 介面,在 keyPressed() 中根據按鍵代碼分派動作:

  • 方向鍵(上下左右) → snakeModel.changeDirection()
  • PageUp/PageDown → 加速/減速
  • Space/P → 切換暫停狀態
  • Enter/R/S → 重新開始遊戲(重置模型並重啟執行緒)

註:方向改變邏輯在 SnakeModel.changeDirection() 中透過奇偶性判斷防止 180 度反向移動導致立即自殺。

畫面渲染機制

void repaint() {
    Graphics g = paintCanvas.getGraphics();
    // 1. 清空背景
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, canvasWidth, canvasHeight);
    
    // 2. 繪製蛇身(黑色)
    g.setColor(Color.BLACK);
    for (Node n : snakeModel.nodeArray) {
        drawNode(g, n);
    }
    
    // 3. 繪製食物(紅色)
    g.setColor(Color.RED);
    drawNode(g, snakeModel.food);
    
    updateScore();
}

private void drawNode(Graphics g, Node n) {
    g.fillRect(n.x * nodeWidth, n.y * nodeHeight, nodeWidth-1, nodeHeight-1);
}

採用主動繪圖模式,直接取得 Canvas 的 Graphics 進行即時渲染,而非覆寫 paint() 方法。

模型層核心邏輯深度解析

資料結構設計

  • boolean[][] matrix:二維布林陣列標記格子佔用狀態,實現 O(1) 碰撞檢測。
  • LinkedList<Node> nodeArray:雙向鏈表儲存蛇身節點,頭尾操作均為 O(1),完美契合蛇身「頭部新增、尾部移除」的移動特性。
  • Node food:單一食物物件,座標即為格子索引。

初始化邏輯

public SnakeModel(GreedSnake gs, int maxX, int maxY) {
    // 矩陣初始化
    matrix = new boolean[maxX][maxY];
    for (boolean[] row : matrix) Arrays.fill(row, false);
    
    // 蛇身初始長度:寬度>20則為10,否則為寬度一半
    int initLen = maxX > 20 ? 10 : maxX / 2;
    for (int i = 0; i < initLen; i++) {
        int x = maxX/2 + i, y = maxY/2;
        nodeArray.addLast(new Node(x, y));
        matrix[x][y] = true;
    }
    
    food = createFood();
    matrix[food.x][food.y] = true;
}

移動與碰撞核心算法

public boolean moveOn() {
    Node head = nodeArray.getFirst();
    int x = head.x, y = head.y;
    
    // 根據方向計算新頭部座標
    switch(direction) {
        case UP:    y--; break;
        case DOWN:  y++; break;
        case LEFT:  x--; break;
        case RIGHT: x++; break;
    }
    
    // 邊界檢查
    if (x < 0 || x >= maxX || y < 0 || y >= maxY) return false;
    
    // 碰撞檢查
    if (matrix[x][y]) {
        // 撞到食物
        if (x == food.x && y == food.y) {
            nodeArray.addFirst(food); // 蛇身增長,不移除尾部
            int scoreGet = (10000 - 200 * countMove) / timeInterval;
            score += scoreGet > 0 ? scoreGet : 10;
            countMove = 0;
            food = createFood();
            matrix[food.x][food.y] = true;
            return true;
        }
        // 撞到牆壁或自己
        return false;
    }
    
    // 正常移動:頭部新增、尾部移除
    nodeArray.addFirst(new Node(x, y));
    matrix[x][y] = true;
    Node tail = nodeArray.removeLast();
    matrix[tail.x][tail.y] = false;
    countMove++;
    return true;
}

計分與速度機制

  • 基礎分數:吃到食物獲得基礎 10 分。
  • 獎勵分數:(10000 - 200 * 移動步數) / 當前間隔時間,鼓勵玩家快速直線吃食。
  • 速度控制:timeInterval 為移動間隔毫秒數,預設 200ms。加速/減速以 0.75 倍率調整(最小 20ms)。

執行緒運行循環

SnakeModel.run() 方法(原始碼截斷前)會在 while(running) 循環中周期性呼叫 moveOn(),根據回傳值判斷遊戲結束或繼續,並透過 Thread.sleep(timeInterval) 控制幀率。暫停狀態下進入 wait() 釋放 CPU。

設計亮點與改進建議

亮點

  1. 職責分離清晰:視圖與模型解耦,模型不依賴 Swing 元件,易於單元測試。
  2. 資料結構選型精準:LinkedList + boolean[][] 實現高效移動與碰撞檢測。
  3. 狀態機設計:running、paused、direction 狀態管理完備。

潛在改進方向

  1. 採用 Swing Timer 或獨立渲染執行緒替代 Canvas.getGraphics() 主動繪圖,避免閃爍與執行緒安全問題。
  2. 引入雙緩衝機制(BufferStrategy)提升渲染流暢度。
  3. 將鍵盤處理改為 Key Bindings API,解決焦點導致的按鍵無響應問題。
  4. 增加遊戲狀態枚舉(READY, RUNNING, PAUSED, GAME_OVER)替代布林旗標,邏輯更清晰。
  5. 支援高分紀錄持久化、關卡系統、道具機制等擴展功能。

總結

這個貪食蛇實作雖然代碼簡潔,卻完整展示了 Java 遊戲開發的核心要素:幀循環、狀態管理、輸入處理、碰撞檢測、渲染管線。其模型層設計尤為優秀,資料結構選型教科書級別,是學習 Java 遊戲程式設計與 MVC 架構的極佳範例。建議讀者嘗試在保持模型不變的前提下,將視圖層遷移至 JavaFX 或 LibGDX 等現代框架,體驗架構解耦帶來的擴展性紅利。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved