乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

迷路

今回は迷路の自販機を
再現するコードの実装です。

解説動画はこちら




迷路の自販機

先日、テレビで迷路の自販機なるものを
特集していました。


こんな感じのものですね

お金を入れるとその分の長さの
迷路が生成されて
プリントされるというものです。

高いほど長くなる仕組みの様です。

迷路を自動生成する事ができれば
これを再現する事ができるんじゃ
ないかなと思います。

早速コードを見てみましょう。


迷路作成コード

迷路を作成する部分と
画像を生成する部分です。
import random
import sys
from PIL import Image
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
sys.setrecursionlimit(10**6)

# 迷路を作成する
def make_maze(size):

    def make(ny, nx,tmp_maze):
        ar = list(range(4)) 
        random.shuffle(ar)
        for i in ar:
            if ny+dy[i][1]<1 or ny+dy[i][1]>=size[0]:
                continue
            if nx+dx[i][1]<1 or nx+dx[i][1]>=size[1]:
                continue
            if tmp_maze[ny+dy[i][1]][nx+dx[i][1]]==0:
                continue
            for j in range(2):
                tmp_maze[ny+dy[i][j]][nx+dx[i][j]]=0
            make(ny+dy[i][1], nx+dx[i][1],tmp_maze)
    
    tmp_maze = [[1]*size[1] for _ in range(size[0])]
    dx,dy = [(1,2), (-1,-2), (0,0), (0,0)],[(0,0), (0,0), (1,2), (-1,-2)]
    make(1, 1,tmp_maze)
    tmp_maze[1][1],tmp_maze[size[0]-2][size[1]-2] = 2,3
    return tmp_maze

# 画像を作成する
def create_image_from_maze(maze, file_path,pixel_size=20):
    # 色のマッピング
    colors = {
        0: (255, 255, 255),  # 白
        1: (0, 0, 0),        # 黒
        2: (0, 0, 255),      # 青
        3: (0, 255, 0)       # 緑
    }
    width = len(maze[0]) * pixel_size
    height = len(maze) * pixel_size
    image = Image.new("RGB", (width, height), "white")
    pixels = image.load()
    for y in range(len(maze)):
        for x in range(len(maze[0])):
            color = colors.get(maze[y][x], (255, 255, 255))
            for dy in range(pixel_size):
                for dx in range(pixel_size):
                    pixels[x * pixel_size + dx, y * pixel_size + dy] = color
    image.save(file_path)
    return image

実行する際はコレ
# 迷路を作成する
size = (31, 101) # height , width
maze = make_maze(size)

# 画像を生成
image = create_image_from_maze(maze,"image.png")
plt.figure(figsize=(16,10))
plt.imshow(image, cmap='gray')
plt.axis('off')
plt.show()
download

こんな感じで迷路が出来上がります。

黒が壁で、白が通路
青がスタート、緑がゴールです。

いい感じで横長の迷路が
出来ているんじゃないでしょうか

縦は31ピクセル固定として
横は100円分で
31ピクセルとかにすれば
いい感じに再現出来るんじゃないかと。

もっと大きな迷路も
作成は出来ると思うので
サイズ変更して試してみて下さい。

Google Colabなどで
実行できると思います。


今回は迷路の自販機を再現する
迷路作成のコードについてでした。

それでは。

暇ですよねwww

そんな時はお金のかからない方法で
遊びを見つけてみよーじゃないですか

自作でプログラム作ればタダです。

ということで迷路を作るプログラムを作ってみました。
解説動画はこちら


今回のプログラムでは穴掘り法というアルゴリズムを使用しています。

どんな感じかというと

1.縦横それぞれ奇数個サイズのマス作る

2.縦横それぞれ奇数座標のマスをランダムに選択する

3.方向をランダムに選択し2マス先のマスを調べて
まだ通路でなければ通路に変える

4.ランダムに選択した方向の2マス先が通路の場合はここで一旦終了

5.新たに縦横奇数座標のマスをランダムに選択し
通路を延ばせるマスが無くなるまで繰り返す

6.スタートとゴールをつけてあげる

ソースコードはこちら
import random
import sys
sys.setrecursionlimit(10**6)

# 穴掘り法で迷路を作る
def make(ny, nx):
    ar = list(range(4)) 
    random.shuffle(ar)
    for i in ar:
        if ny+dy[i][1]<1 or ny+dy[i][1]>=size[0]:
            continue
        if nx+dx[i][1]<1 or nx+dx[i][1]>=size[1]:
            continue
        if maze[ny+dy[i][1]][nx+dx[i][1]]=="□":
            continue
        for j in range(2):
            maze[ny+dy[i][j]][nx+dx[i][j]] = "□"
        make(ny+dy[i][1], nx+dx[i][1])

#height , width    Enter with odd number
size = (101, 51)

maze = [["■"]*size[1] for _ in range(size[0])]
dx,dy = [(1,2), (-1,-2), (0,0), (0,0)],[(0,0), (0,0), (1,2), (-1,-2)]
make(1, 1)
maze[1][1],maze[size[0]-2][size[1]-2] = "す","ご"

for i in maze:
    print(*i)
ちゃんと確認はしてませんが動くはずです。

sizeの所に奇数で縦横のサイズを入れてください。
横はデカすぎるとダメですが、縦は大きくても問題ないです。

こんな感じになるはずです。

スクリーンショット 2020-05-09 15.03.14


黒いのが壁で白抜きが道。
右下にゴールがあります。

でかいサイズで作ったら
PDFとかにでもして
印刷すれば即席巨大迷路の完成です。

どこまで大きなサイズができるかは知りませんが
色々遊べると思うので
動かして遊んでみてくださいませ。

それでは。




このページのトップヘ