推箱子是經典的益智遊戲,使用 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 值傳遞,需返回新座標或封裝狀態對象
}
// 返回是否勝利
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;
}
}
控制台推箱子雖簡單,卻蘊含狀態建模、邊界條件、碰撞檢測、輸入處理、遊戲循環等遊戲開發精髓。通過手寫這個小遊戲,能扎實掌握 Java 面向過程編程邏輯,為後續學習遊戲引擎、圖形界面打下堅實基礎。