スタートからゴールまでの距離を2次元配列で表現して、
最短経路の通路を「 」(半角スペース)から「*」に置き換えて出力する。
Canvas.tsx
import React, { useEffect } from 'react';
import p5 from 'p5';
import Maze from './maze';
const sketch = (p: p5) => {
p.setup = () => {
const maze1 = new Maze(p, 15, 15);
maze1.set_maze_boutaoshi();
maze1.set_start_goal([9,5], [7,11]);
maze1.set_shortest_path();
maze1.print_maze();
}
}
const Canvas: React.FC = () => {
useEffect(() => {
new p5(sketch)
})
return (
<React.Fragment>
</React.Fragment>
);
}
export default Canvas;
maze.ts
import p5 from 'p5';
type maze = number[][] | string[][];
class Maze {
p: p5;
PATH: number;
WALL: number;
width: number;
height: number;
maze: maze = [];
dist: number[][] = [];
start: number[] = [];
goal: number[] = [];
constructor(p: p5, width: number, height: number, seed: number = 0) {
this.p = p;
this.PATH = 0;
this.WALL = 1;
this.width = width;
this.height = height;
if (this.width < 5 || this.height < 5) {
return;
}
if (this.width%2 === 0) {
this.width++;
}
if (this.height%2 === 0) {
this.height++;
}
this.maze = [...Array(this.height)].map(() => Array(this.width).fill(0));
this.dist = [[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1, -1, 12, 11, 10, 9, 8, -1],
[-1, -1, -1, -1, -1, -1, -1, -1, -1, 13, -1, -1, -1, 7, -1],
[-1, -1, -1, -1, -1, 18, 17, 16, 15, 14, -1, -1, -1, 6, -1],
[-1, -1, -1, -1, -1, 19, -1, -1, -1, -1, -1, -1, -1, 5, -1],
[-1, -1, -1, -1, -1, 20, -1, -1, -1, 0, 1, 2, 3, 4, -1],
[-1, -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, 22, 23, 24, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, 26, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, 27, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, 28, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]];
this.start = [1, 1];
this.goal = [this.width-2, this.height-2];
p.randomSeed(seed);
}
set_outer_wall(): maze {
for (let y = 0; y < this.height; y++) {
for (let x = 0; x < this.width; x++) {
if (x === 0 || y === 0 || x === this.width-1 || y === this.height-1) {
this.maze[y][x] = this.WALL;
}
}
}
return this.maze;
}
set_inner_wall(): maze {
for (let y = 2; y <= this.height-3; y+=2) {
for (let x = 2; x <= this.width-3; x+=2) {
this.maze[y][x] = this.WALL;
}
}
return this.maze;
}
set_maze_boutaoshi(): maze {
let cell_x: number, cell_y: number, direction: number;
this.set_outer_wall();
this.set_inner_wall();
for (let y = 2; y <= this.height-3; y+=2) {
for (let x = 2; x <= this.width-3; x+=2) {
while (true) {
cell_x = x;
cell_y = y;
if (y === 2) {
direction = this.p.floor(this.p.random(4));
} else {
direction = this.p.floor(this.p.random(3));
}
if (direction === 0) {
cell_x += 1;
} else if (direction === 1) {
cell_y += 1;
} else if (direction === 2) {
cell_x -= 1;
} else if (direction === 3) {
cell_y -= 1;
}
if (this.maze[cell_y][cell_x] !== this.WALL) {
this.maze[cell_y][cell_x] = this.WALL;
break;
}
}
}
}
return this.maze;
}
set_start_goal(start: number[], goal: number[]): maze {
if (this.maze[start[1]][start[0]] === this.PATH) {
this.start = start;
}
if (this.maze[goal[1]][goal[0]] === this.PATH) {
this.goal = goal;
}
return this.maze;
}
set_shortest_path(): maze {
let point: number[] = this.goal;
const x: number[][] = [[0,-1],[1,0],[0,1],[-1,0]];
this.maze[point[1]][point[0]] = '*';
while (this.dist[point[1]][point[0]] > 0) {
for (let i = 0; i < x.length; 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 = [point[0]+x[i][0],point[1]+x[i][1]];
}
}
}
}
return this.maze;
}
print_maze(): void {
let arr: string;
this.maze[this.start[1]][this.start[0]] = 'S';
this.maze[this.goal[1]][this.goal[0]] = 'G';
for (let row of this.maze) {
arr = '';
for (let cell of row) {
if (cell === this.WALL) {
arr += '#';
} else if (cell === this.PATH) {
arr += ' ';
} else if (cell === 'S') {
arr += 'S';
} else if (cell === 'G') {
arr += 'G';
} else if (cell === '*') {
arr += '*';
}
}
console.log(arr);
}
}
}
export default Maze;
今回は、以下のように出力される。
###############
# # *****#
# ### ###*###*#
# #*****# *#
# # #*# #####*#
# # #*# #S****#
# ###*##### ###
# # ***# #
# # # #*# # ###
# # # #*# # #
# #####*# ### #
# #G# # #
# ### ### # # #
# # # # # #
###############