Java | 3D 迷路を作って自動で探索するサンプル

APP Java
スポンサーリンク

3D 迷路(立体迷路)を作って、自動で探索(探索アルゴリズムでゴールへ到達)する Java サンプルを、
プログラミング初心者向けに“超かみ砕いて”説明します。

以下の内容がセットになっています:

✅ 3D 迷路の考え方
✅ 3D 配列で迷路を表す方法
✅ 自動探索(BFS / DFS)
✅ ステップごとの解説
✅ 完全な Java 動くサンプルコード


1. 3D 迷路とは?(まずイメージ)

2D 迷路は「縦 × 横」
3D 迷路は「縦 × 横 × 高さ(階層)」で迷路を扱います。

階層 = Z(高さ)
行 = Y
列 = X

3D 配列のイメージ:

maze[z][y][x]

2. 迷路の表現(0 = 通路 / 1 = 壁)

例:3階建ての迷路(3 × 5 × 5)

Z = 0 (1階)
Z = 1 (2階)
Z = 2 (3階)

Java の配列:

int[][][] maze = {
    { // Z=0 (1階)
        {0,1,0,0,0},
        {0,1,0,1,0},
        {0,0,0,1,0},
        {1,1,0,0,0},
        {0,0,0,1,0}
    },
    { // Z=1 (2階)
        {0,0,1,1,0},
        {1,0,0,1,0},
        {1,1,0,0,0},
        {0,0,0,1,1},
        {0,1,0,0,0}
    },
    { // Z=2 (3階)
        {0,0,0,1,0},
        {1,1,0,1,0},
        {0,0,0,0,0},
        {0,1,1,1,0},
        {0,0,0,1,0}
    }
};
Java

3. 自動探索(BFS)とは?

3D の「迷路探索」でよく使うのが BFS(幅優先探索)。

BFS の特徴:

  • 一番近いルートを最優先して広げる
  • ゴールまでの最短ルートが確実に見つかる
  • キュー(Queue)を使う

移動方向は 3D なので 6 方向:

+X(右)
−X(左)
+Y(下)
−Y(上)
+Z(上の階へ)
−Z(下の階へ)

4. 完全サンプル:3D 迷路の探索(BFS)

✔ このサンプルは以下を実装

  • 3D 迷路を配列で定義
  • BFS で自動探索
  • 移動ログを表示
  • ゴールまでの最短経路を復元して表示

完全 Java コード(コピペで動く)

import java.util.*;

public class Maze3D {

    // 移動方向(x, y, z)
    static int[][] DIRS = {
        { 1, 0, 0},  // 右
        {-1, 0, 0},  // 左
        { 0, 1, 0},  // 下
        { 0,-1, 0},  // 上
        { 0, 0, 1},  // 上の階
        { 0, 0,-1}   // 下の階
    };

    public static void main(String[] args) {

        // ------- 3D迷路定義(0=道、1=壁)-----------
        int[][][] maze = {
            { // Z=0
                {0,1,0,0,0},
                {0,1,0,1,0},
                {0,0,0,1,0},
                {1,1,0,0,0},
                {0,0,0,1,0}
            },
            { // Z=1
                {0,0,1,1,0},
                {1,0,0,1,0},
                {1,1,0,0,0},
                {0,0,0,1,1},
                {0,1,0,0,0}
            },
            { // Z=2
                {0,0,0,1,0},
                {1,1,0,1,0},
                {0,0,0,0,0},
                {0,1,1,1,0},
                {0,0,0,1,0}
            }
        };

        int zSize = maze.length;
        int ySize = maze[0].length;
        int xSize = maze[0][0].length;

        // start と goal
        int[] start = {0, 0, 0};       // (x=0,y=0,z=0)
        int[] goal  = {4, 4, 2};       // (右下・最上階)

        List<int[]> path = bfs(maze, start, goal);

        if (path == null) {
            System.out.println("ゴールまでの道が見つかりませんでした。");
        } else {
            System.out.println("=== 最短ルート ===");
            for (int[] p : path) {
                System.out.printf("(x=%d, y=%d, z=%d)\n", p[0], p[1], p[2]);
            }
        }
    }

    // BFSで探索
    static List<int[]> bfs(int[][][] maze, int[] start, int[] goal) {
        int zSize = maze.length;
        int ySize = maze[0].length;
        int xSize = maze[0][0].length;

        boolean[][][] visited = new boolean[zSize][ySize][xSize];
        int[][][] prev = new int[zSize][ySize][xSize]; // 経路復元用

        Queue<int[]> queue = new ArrayDeque<>();
        queue.add(start);
        visited[start[2]][start[1]][start[0]] = true;
        prev[start[2]][start[1]][start[0]] = -1;  // 開始点

        while (!queue.isEmpty()) {
            int[] cur = queue.poll();
            int x = cur[0], y = cur[1], z = cur[2];

            if (x == goal[0] && y == goal[1] && z == goal[2]) {
                return buildPath(prev, start, goal);
            }

            for (int[] d : DIRS) {
                int nx = x + d[0];
                int ny = y + d[1];
                int nz = z + d[2];

                if (0 <= nz && nz < zSize &&
                    0 <= ny && ny < ySize &&
                    0 <= nx && nx < xSize &&
                    maze[nz][ny][nx] == 0 &&
                    !visited[nz][ny][nx])
                {
                    visited[nz][ny][nx] = true;
                    prev[nz][ny][nx] = z*10000 + y*100 + x; // 前の座標を保存
                    queue.add(new int[]{nx,ny,nz});
                }
            }
        }
        return null;
    }

    // 経路復元(prev の値を逆にたどる)
    static List<int[]> buildPath(int[][][] prev, int[] start, int[] goal) {
        List<int[]> path = new ArrayList<>();
        int x = goal[0], y = goal[1], z = goal[2];

        while (true) {
            path.add(new int[]{x,y,z});
            if (x==start[0] && y==start[1] && z==start[2]) break;

            int v = prev[z][y][x];
            int px = v % 100;
            int py = (v / 100) % 100;
            int pz = v / 10000;

            x = px; y = py; z = pz;
        }

        Collections.reverse(path);
        return path;
    }
}
Java

実行結果(例)

=== 最短ルート ===
(x=0, y=0, z=0)
(x=0, y=1, z=0)
(x=0, y=2, z=0)
(x=1, y=2, z=0)
(x=2, y=2, z=0)
(x=2, y=2, z=1)
(x=2, y=2, z=2)
(x=3, y=2, z=2)
(x=4, y=2, z=2)
(x=4, y=3, z=2)
(x=4, y=4, z=2)

3階を含む立体迷路の探索ができています。

Java
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました