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

Java 控制台版推箱子遊戲完整實現:二維數組地圖、WASD 控制、碰撞檢測與勝負判邏輯詳解

     編輯:Java 綜合教學

前言

推箱子是經典的益智遊戲,使用 Java 控制台實現能直觀理解二維數組建模、座標系移動、邊界檢測、箱子推動邏輯、終點判定等遊戲開發核心概念。本文提供完整可運行代碼,並詳細註釋關鍵算法邏輯,適合初學者練習邏輯思維與 Java 基礎語法。

一、核心數據結構設計

int[][] map = new int[15][15]; // 15x15 地圖矩陣
// 元素編碼:
// 0 = 空地 □
// 1 = 人  囚
// 2 = 箱子 ▲
// 3 = 終點 ★

使用整型矩陣而非對象數組,簡化渲染與碰撞判斷,適合控制台輕量級遊戲。

二、初始化佈局

int rx = 1, ry = 2;     // 人初始座標
int bx = 13, by = 12;   // 箱子初始座標
int tx = 10, ty = 3;    // 終點座標

map[rx][ry] = 1;
map[bx][by] = 2;
map[tx][ty] = 3;

三、主遊戲循環

boolean win = false;
Scanner scanner = new Scanner(System.in);

while (true) {
    // 1. 渲染地圖
    renderMap(map);

    // 2. 勝利判定
    if (win) {
        System.out.println("成功將箱子推到終點!");
        break;
    }

    // 3. 獲取輸入
    System.out.print("要往哪走(w上,s下,a左,d右):");
    String dir = scanner.next();

    // 4. 移動邏輯分發
    win = movePlayer(dir, map, rx, ry, bx, by, tx, ty, win);
    // 注意:Java 值傳遞,需返回新座標或封裝狀態對象
}

四、核心移動算法(以向上 'w' 為例)

// 返回是否勝利
boolean moveUp(int[][] map, int[] player, int[] box, int[] target) {
    int px = player[0], py = player[1];
    int bx = box[0], by = box[1];
    int tx = target[0], ty = target[1];

    // 1. 邊界檢查
    if (px - 1 < 0) return false;

    // 2. 遇到箱子 -> 嘗試推箱子
    if (map[px - 1][py] == 2) {
        // 箱子前方是牆/邊界 -> 不能推
        if (px - 2 < 0) return false;
        // 箱子前方是終點 -> 勝利
        if (map[px - 2][py] == 3) return true;
        // 箱子前方是空地 -> 移動箱子
        map[px - 2][py] = 2;
        map[px - 1][py] = 0; // 原箱子位置變空地(人即將移過去)
    }

    // 3. 處理人移動(含終點踩踏邏輯)
    // 人踩在終點上時,原位置應保留終點標記
    if (map[px][py] == 3) map[px][py] = 3; // 保留終點
    else map[px][py] = 0;                  // 普通空地

    player[0]--; // 人座標更新
    map[player[0]][player[1]] = 1; // 新位置標記人

    return false; // 未勝利
}

四個方向邏輯對稱,只需修改座標增減。完整代碼見文末。

五、渲染方法

void renderMap(int[][] map) {
    for (int[] row : map) {
        for (int cell : row) {
            switch (cell) {
                case 1: System.out.print("囚"); break;
                case 2: System.out.print("▲"); break;
                case 3: System.out.print("★"); break;
                default: System.out.print("□");
            }
        }
        System.out.println();
    }
}

六、完整可運行代碼(單文件)

import java.util.Scanner;

public class SokobanConsole {
    static int[][] map = new int[15][15];
    static int[] player = {1, 2};
    static int[] box = {13, 12};
    static int[] target = {10, 3};
    static boolean win = false;

    public static void main(String[] args) {
        map[player[0]][player[1]] = 1;
        map[box[0]][box[1]] = 2;
        map[target[0]][target[1]] = 3;

        Scanner sc = new Scanner(System.in);
        while (true) {
            render();
            if (win) { System.out.println("成功將箱子推到終點!"); break; }
            System.out.print("要往哪走(w上,s下,a左,d右):");
            String dir = sc.next();
            win = move(dir);
        }
    }

    static void render() {
        for (int[] row : map) {
            for (int c : row) {
                if (c == 1) System.out.print("囚");
                else if (c == 2) System.out.print("▲");
                else if (c == 3) System.out.print("★");
                else System.out.print("□");
            }
            System.out.println();
        }
    }

    static boolean move(String dir) {
        int px = player[0], py = player[1];
        int bx = box[0], by = box[1];

        int npx = px, npy = py, nbx = bx, nby = by;
        switch (dir) {
            case "w": npx--; break;
            case "s": npx++; break;
            case "a": npy--; break;
            case "d": npy++; break;
            default: return false;
        }

        // 邊界檢查
        if (npx < 0 || npx >= 15 || npy < 0 || npy >= 15) return false;

        // 遇到箱子
        if (map[npx][npy] == 2) {
            int nnpx = npx + (npx - px), nnpY = npy + (npy - py); // 箱子下一格
            if (nnpx < 0 || nnpx >= 15 || nnpY < 0 || nnpY >= 15) return false; // 箱子撞牆
            if (map[nnpx][nnpY] == 3) { win = true; } // 箱子進終點
            else if (map[nnpx][nnpY] != 0) return false; // 箱子前非空
            // 移動箱子
            map[nnpx][nnpY] = 2;
            map[npx][npy] = 0;
            box[0] = nnpx; box[1] = nnpY;
        }

        // 處理人移動(含終點保留)
        if (map[px][py] == 3) map[px][py] = 3;
        else map[px][py] = 0;
        player[0] = npx; player[1] = npy;
        map[npx][npy] = 1;
        return win;
    }
}

七、擴展方向建議

  1. 多關卡:從文件加載地圖數據,支持多關卡切換。
  2. 撤銷功能:棧保存歷史狀態(地圖+座標),實現 'u' 撤銷一步。
  3. 圖形化界面:Swing/JavaFX 替換控制台渲染,添加動畫與音效。
  4. 自動尋路:BFS/A* 算法實現 AI 自動解關。

八、總結

控制台推箱子雖簡單,卻蘊含狀態建模、邊界條件、碰撞檢測、輸入處理、遊戲循環等遊戲開發精髓。通過手寫這個小遊戲,能扎實掌握 Java 面向過程編程邏輯,為後續學習遊戲引擎、圖形界面打下堅實基礎。

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