【Unity】迷路を生成する

Assets で右クリックし、Create から C# Script を選択してファイルを作成する。
ファイル名を Maze として、以下のように編集する。

MazeController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MazeController : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Maze maze1 = new Maze(15, 15);
        maze1.set_maze_boutaoshi();

        GameObject wall = new GameObject("Wall");
        GameObject[,] walls = new GameObject[maze1.maze.GetLength(0), maze1.maze.GetLength(1)];
        GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);

        cube.transform.position = new Vector3(0.5f, 0.5f, 0.5f);
        cube.transform.parent = wall.transform;

        plane.transform.localScale = new Vector3(1.5f, 1, 1.5f);
        plane.transform.position = new Vector3(7.5f, 0, 7.5f);

        for (int y = 0; y < maze1.maze.GetLength(0); ++y) {
            for (int x = 0; x < maze1.maze.GetLength(1); ++x) {
                if (maze1.maze[y, x] == Maze.WALL) {
                    walls[y, x] = Instantiate(wall, new Vector3(x, 0, y), Quaternion.identity);
                }
            }
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

Maze.cs

using System;
using System.Collections.Generic;
using System.Linq;

public class Maze {
    public const int PATH = 0;
    public const int WALL = 1;
    public int width;
    public int height;
    public int[,] maze;
    public int[,] dist;
    public int[] start;
    public int[] goal;
    private Random random;
    
    public Maze(int width, int height, int seed = 0) {
        this.width = width;
        this.height = height;
        if (this.width < 5 || this.height < 5) {
            Environment.Exit(0);
        }
        if (this.width % 2 == 0) {
            this.width++;
        }
        if (this.height % 2 == 0) {
            this.height++;
        }
        this.maze = new int[this.height,this.width];
        for (int y = 0; y < this.height; ++y) {
            for (int x = 0; x < this.width; ++x) {
                this.maze[y,x] = Maze.PATH;
            }
        }
        this.dist = new int[this.height,this.width];
        for (int y = 0; y < this.height; ++y) {
            for (int x = 0; x < this.width; ++x) {
                this.dist[y,x] = -1;
            }
        }
        this.start = new int[] {1, 1};
        this.goal = new int[] {this.width-2, this.height-2};
        this.random = new Random(seed);
    }

    public int[,] set_outer_wall() {
        for (int y = 0; y < this.height; ++y) {
            for (int x = 0; x < this.width; ++x) {
                if (x == 0 || y == 0 || x == this.width-1 || y == this.height-1) {
                    this.maze[y,x] = Maze.WALL;
                }
            }
        }
        return this.maze;
    }
    
    public int[,] set_inner_wall() {
        for (int y = 2; y < this.height-1; y += 2) {
            for (int x = 2; x < this.width-1; x += 2) {
                this.maze[y,x] = Maze.WALL;
            }
        }
        return this.maze;
    }
    
    public int[,] set_maze_boutaoshi() {
        int wall_x;
        int wall_y;
        int direction;
        this.set_outer_wall();
        this.set_inner_wall();
        for (int y = 2; y < this.height-1; y += 2) {
            for (int x = 2; x < this.width-1; x += 2) {
                while (true) {
                    wall_x = x;
                    wall_y = y;
                    if (y == 2) {
                        direction = random.Next(0,4);
                    } else {
                        direction = random.Next(0,3);
                    }
                    switch (direction) {
                        case 0:
                            wall_x += 1;
                            break;
                        case 1:
                            wall_y +=1;
                            break;
                        case 2:
                            wall_x -=1;
                            break;
                        case 3:
                            wall_y -=1;
                            break;
                    }
                    if (this.maze[wall_y,wall_x] != Maze.WALL) {
                        this.maze[wall_y,wall_x] = Maze.WALL;
                        break;
                    }
                }
            }
        }
        return this.maze;
    }

    public int[,] set_start_goal(int[] start, int[] goal) {
        if (this.maze[start[1],start[0]] == Maze.PATH) {
            this.start = start;
        }
        if (this.maze[goal[1],goal[0]] == Maze.PATH) {
            this.goal = goal;
        }
        return this.maze;
    }

    public int[,] set_dist_bfs(bool flag = false) {
        int[] point;
        int[,] x = new int[,] {{0,-1},{1,0},{0,1},{-1,0}};
        Queue<int[]> queue = new Queue<int[]>();
        this.dist[this.start[1],this.start[0]] = 0;
        queue.Enqueue(this.start);
        while (queue.Count > 0) {
            point = queue.Dequeue();
            for (int i = 0; i < x.GetLength(0); ++i) {
                if (this.maze[point[1]+x[i,1],point[0]+x[i,0]] == 0 && this.dist[point[1]+x[i,1],point[0]+x[i,0]] == -1) {
                    this.dist[point[1]+x[i,1],point[0]+x[i,0]] = this.dist[point[1],point[0]] + 1;
                    queue.Enqueue(new int[] {point[0]+x[i,0],point[1]+x[i,1]});
                }
                if (flag != true) {
                    if (point[0]+x[i,0] == this.goal[0] && point[1]+x[i,1] == this.goal[1]) {
                        queue.Clear();
                        break;
                    }
                }   
            }
        }
        return this.dist;
    }

    public int[,] set_dist_dfs(bool flag = false) {
        int[] point;
        int[,] x = new int[,] {{0,-1},{1,0},{0,1},{-1,0}};
        Stack<int[]> stack = new Stack<int[]>();
        this.dist[this.start[1],this.start[0]] = 0;
        stack.Push(this.start);
        while (stack.Count > 0) {
            point = stack.Pop();
            for (int i = 0; i < x.GetLength(0); ++i) {
                if (this.maze[point[1]+x[i,1],point[0]+x[i,0]] == 0 && this.dist[point[1]+x[i,1],point[0]+x[i,0]] == -1) {
                    this.dist[point[1]+x[i,1],point[0]+x[i,0]] = this.dist[point[1],point[0]] + 1;
                    stack.Push(new int[] {point[0]+x[i,0],point[1]+x[i,1]});
                }
                if (flag != true) {
                    if (point[0]+x[i,0] == this.goal[0] && point[1]+x[i,1] == this.goal[1]) {
                        stack.Clear();
                        break;
                    }
                }   
            }
        }
        return this.dist;
    }

    public int[,] set_shortest_path() {
        int[] point;
        int[,] x = new int[,] {{0,-1},{1,0},{0,1},{-1,0}};
        point = this.goal;
        this.maze[point[1],point[0]] = '*';
        while (this.dist[point[1],point[0]] > 0) {
            for (int i = 0; i < x.GetLength(0); ++i) {
                if (this.dist[point[1],point[0]]-this.dist[point[1]+x[i,1],point[0]+x[i,0]] == 1) {
                    if (this.dist[point[1],point[0]] > 0) {
                        this.maze[point[1]+x[i,1],point[0]+x[i,0]] = '*';
                        point = new int[] {point[0]+x[i,0],point[1]+x[i,1]};   
                    }
                }
            }
        }
        return this.maze;
    }

    public void print_maze() {
        this.maze[this.start[1],this.start[0]] = 'S';
        this.maze[this.goal[1],this.goal[0]] = 'G';
        for (int y = 0; y < this.maze.GetLength(0); ++y) {
            for (int x = 0; x < this.maze.GetLength(1); ++x) {
                if (this.maze[y,x] == Maze.WALL) {
                    Console.Write('#');
                } else if (this.maze[y,x] == Maze.PATH) {
                    Console.Write(' ');
                } else if (this.maze[y,x] == 'S') {
                    Console.Write('S');
                } else if (this.maze[y,x] == 'G') {
                    Console.Write('G');
                } else if (this.maze[y,x] == '*') {
                    Console.Write('*');
                }
            }
            Console.WriteLine();
        }
    }
    
    public void print_dist() {
        for (int y = 0; y < this.dist.GetLength(0); ++y) {
            for (int x = 0; x < this.dist.GetLength(1); ++x) {
                if (this.dist[y,x] == -1) {
                    if (this.dist.Cast<int>().Max() == -1) {
                        Console.Write('#');
                    } else {
                        for (int i = 0; i < this.dist.Cast<int>().Max().ToString().Length; ++i) {
                            Console.Write('#');
                        }
                    }
                } else {
                    if (this.dist[y,x].ToString().Length == this.dist.Cast<int>().Max().ToString().Length) {
                        Console.Write(this.dist[y,x]);
                    } else {
                        for (int i = 0; i < this.dist.Cast<int>().Max().ToString().Length-this.dist[y,x].ToString().Length; ++i) {
                            Console.Write(' ');
                        }
                        Console.Write(this.dist[y,x]);
                    }
                }
            }
            Console.WriteLine();
        }
    }
}

再生ボタンを押してゲームを起動すると、迷路が生成されていることが確認できる。

タイトルとURLをコピーしました