R言語を使って生成させた迷路

R言語で迷路生成!棒倒し法のコードを初心者向けに解説!

この記事をシェアする
更新履歴
2017/04/03 コード解説追加(途中まで)
2017/03/17 タイトル変更。コード解説(途中まで)作成中。
2017/03/15 初版公開

みなさんこんにちは。

今日、R言語(Wikipedia)を使ってみようと思い立ちました。サンプルとして、迷路を作ってみましたのでコードを公開します。

 

R言語って何だろう

詳しい説明はWikipediaの説明を見て頂くとして、

私なりに解説すると、

データを用意して、解析・処理し、それを表示するのに適した言語

だと感じました。

データを用意する際に、既にあるデータを読み込んで使うことも、強力なデータ生成機能を使ってそれを使うこともできます。

解析において、通常の言語(C/C#/Java/etc)と比べて、中間的な値を記憶させる変数を用いる機会が少なりそうだと感じています。

 

採用した迷路を生成アルゴリズム

迷路を生成するには代表的な4つのアルゴリズムがあります。

今回は一番簡単な「棒倒し法」を採用しました。

※ 棒倒し法は今後解説予定です。

 

 

 

ソースコード

今回作成したソースコードを以下に示します。

 


#迷路の大きさは横幅(w)・縦幅(h)が11
w <- h <- 11

# 道(road)と壁(wall)を定義
road <- 0
wall <- 1

# 迷路の基礎を作成(全てを道にして外壁を作る)
matrix(road,h,w)->maze;
wall -> maze[1,] -> maze[,1] -> maze[h,] -> maze[,w];

# 棒倒し処理 ------------------------------------------------------
# 引数:y=迷路のY座標
direction <- function(y) {
  # 1~4の乱数を生成
  # ※迷路のY座標が3なら4方向(上の方向含む)、それ以外は3方向(上禁止)
  r <- floor(runif(1, 1, ifelse(y == 3, 5, 4)));

  # 乱数で得た1~4の値を、Y座標とX座標の増分(方向)へ変換
  dy <- switch(r,"1"=1,"2"=0,"3"=0,"4"=-1);
  dx <- (r %% 3) - 1;

  # Y座標とX座標の増分(方向)を返却
  return(list(x = dx, y = dy));
}

# 迷路生成処理 ----------------------------------------------------
# X座標繰り返し(2つ飛ばし)
for(x in seq(3, w - 2, 2)) {
  # Y座標繰り返し(2つ飛ばし)
  for(y in seq(3, h - 2, 2)) {
    # 壁を作る
    maze[y, x] <- wall;
    # 壁の無い方向を探しだす
    d <- direction(y);
    while(maze[y + d$y, x + d$x] == wall) d <- direction(y);
    # その方向へ壁を作る
    maze[y + d$y, x + d$x] <- wall;
  }
}

# 迷路をプロット ----------------------------------------------------
s <- 1; # size
plot(1:ifelse(w>h,w,h) * s);
for(x in 1:w) {
  for(y in 1:h) {
    rect(x * s - s / 2, y * s - s / 2,
         x * s + s / 2, y * s + s / 2,
         col = ifelse(maze[y, x] == wall, "red", "black"));
  }
}

 

 

コード解説

サンプルコードの概要

まず、今回のサンプルの概要を解説します。

 

R言語は行末に「;」(セミコロン)を付ける必要はありませんが、私はメインとしてC#を利用しているため付けています。

 

また、R言語では、

変数 <- 値(処理結果)

または

値(処理結果) -> 変数

で代入を表します。

どちらの記述でも、別段違いはありません。

 

迷路の実体(以降、迷路空間として解説します)は「maze(迷路)」という変数です。行列(matrix)で定義されています。

また、迷路空間は、格子状に(≒縦横に)区切られたマスで作られています。
このマスの内容は、「wall(壁)」と、「road(道)」で定義されます。

迷路の大きさは「w(width、横幅)」と「h(height、縦幅)」であらわされています。

プログラムの根幹は「迷路生成処理」と書かれた処理です。

 

 

サンプルコードの詳細解説

それでは、より詳細にプログラムの内容を解説していきます。

定数定義

以下の記述で迷路空間の大きさを定義しています。
※本来は定数の意味合いで定義していますが、このサンプルでは変数を定数的に使用しています。

#迷路の大きさは横幅(w)・縦幅(h)が11
w <- h <- 11

 

また、以下の記述で道(road)、と壁(wall)の実態を定義しています。

# 道(road)と壁(wall)を定義
road <- 0
wall <- 1

 

 

迷路初期化処理

以下の記述で迷路空間を作っています。この時の迷路空間は、全て道だけとなっています。

matrix(road,h,w)->maze;
最初に、迷路空間「maze」を作る。この時、全て道だけの状態で作られる。
最初に、迷路空間「maze」を作る。この時、全て道だけの状態で作られる。

 

 

 

 

続けて、以下の記述で最外壁(外側の壁)を作っています。

wall -> maze[1,] -> maze[,1] -> maze[h,] -> maze[,w];
続けて、迷路空間の最外壁(外側の壁)を作ります。
続けて、迷路空間の最外壁(外側の壁)を作ります。

 

迷路空間に壁を作るのは、迷路空間「maze」の特定の座標に、壁を代入することで実現しています。

 

例えば、

wall -> maze[6,6]

という処理を記述すると、

真ん中に壁が作られるといった具合です。

これは、例えば「Y座標6・X座標6」の位置(この例では真ん中)に壁を作る場合の解説です。(クリックで拡大)
これは、例えば「Y座標6・X座標6」の位置(この例では真ん中)に壁を作る場合の解説です。(クリックで拡大)

 

 

迷路を実際に作り出す

実際に迷路を生み出すからくりは、コードの中で「棒倒し処理」と書かれている部分と、「迷路生成処理」と書かれている部分です。

中心的な処理(≒実際に迷路生成を行っている処理)は、「迷路生成処理」です。迷路生成処理から棒倒し処理を何度も何度も呼び出すことで、迷路を作っています。

迷路を作り出しているソースコード。「迷路生成処理」から「棒倒し処理(関数:direction)」を何度も呼び出すことで迷路が作られる。(クリックして拡大)
迷路を作り出しているソースコード。「迷路生成処理」から「棒倒し処理(関数:direction)」を何度も呼び出すことで迷路が作られる。(クリックして拡大)

 

 

 

(解説途中)

 

実行結果例

実行結果の例を以下に示します。

R言語で迷路を生成させた例。クリックで拡大。
R言語で迷路を生成させた例。クリックで拡大。

 

 

 

考察

このサンプル自体は、正直R言語でやる必要はありません。

R言語の良さを何一つ使っていないサンプルだからです。

 

ただし、

通常の手続き型言語と同じような着想でプログラムを書くことができる

と実感することができました。

 

また、

R言語はデータ(リスト・行列等)を強力に生成させ、それをグラフへプロットする機能が充実しています。

 

今回は単に矩形を描画させて描きましたが、

迷路生成をツリー構造を用いて作成したり、描画をポリラインで描いたり、

色々な応用ができるかもしれません。

 

 

最後に

大量のデータを解析し、それを分かりやすくプロット(表示)できる言語であるR言語はとても魅力的です。現在盛んに取りざたされている「ビッグデータ」の解析や、人工知能開発の躍進に恩恵をもたらしてくれそうだと感じています。

また、今回の内容は「Escape from the Grand Maze ― 巨大迷路からの脱出」に関係したものです。今後、この物語を進めるにつれて、どのように関係しているのか語られていくでしょう。

次回の更新をお待ちいただければ幸いです。

迷路
更新履歴 2017/04/19 START編公開。 2017/03/18 PROLOGUEの漫画版公開 2017/03/14 公開開始。PROLOGUE公開。 これは当サイ
教室
これは「Escape from the Grand Maze - 巨大迷路からの脱出」のコンテンツ(小説)です。 https://ganohr.net/escape-f

 

 

この記事をシェアする

AMPバージョンはこちら。

※ Google Chromeか、Android スマートフォンでご参照ください。

全体の最新記事!

  • 【メディバン】アルペン有料版・無料版を公開!【JUMPペイント】
  • 【SEO】タイトルの長さは38字に抑えろ!?3つの定石を解説!
  • 漫画フキダシに自由自在なシッポを追加する!アルペンのテスト始また
  • 【四コマ漫画】奄美と沖縄の違い!さしみ醬油編【奄美日記10】
  • 【メディペ・mdiapp+】漫画フキダシ用の銀ペン、Ver0.0.6の詳細
  • 【メディペ・mdiapp+】漫画フキダシ用の銀ペンが怒涛のアップデート!
  • SEO:編集中のテキストからキーワードを自動選定する方法!
  • 20分あれば10分眠れる!?効率的に作業をするための快眠法!
  • 【メディペ】漫画ペン入れに最適!?トキペンを公開!【コミラボ】
  • 【小説】プロットとはなにか。何をつくればよいのか
  • デジタルお習字に最適!?mdiapp+で3つのブラシを試す!
  • 【銀ペン】Ver0.0.3は銀座ペンを追加。オマケあり
  • 【ワードプレス】AMPプラグインでエラー発生!した時の対処法【WpX】
  • ワコム製ペンタブの挙動がおかしくなった時の対処法!
  • 【サイト情報】コメント欄メルアド不要へ。過去コメントからもメルアドを除去
  • ブログランキング退会・HTTPSへ完全移行しました【サイト情報】
  • 読書をすべき3つの理由。人工知能に負けないための再認識。
  • レンジ不要のカレーメシがうまい!簡単アレンジも!
  • 不意のフリーズも怖くない!?秀丸のオートセーブを有効化する方法
  • 【DM200】ポメラでブログ!?階層付きテキストを秀丸でHTML化する方法
  • 投稿者:

    Ganohr

    https://twitter.com/garnot1 https://twitter.com/ganohr 私は小学4年からプログラミングを初め、ITエンジニアとしても10年の実績のある個人SEです。ハンドルは「ガノー」で、通常の綴は「Garnot」です。「Ganohr」はガノーという音と、「Gan=ガン(目)、Ohr=オール(耳、ドイツ語)=目と耳」という意味を込めたものです。 目と耳に届く情報を大切にしたい! 目と耳で楽しめるゲームやコンテンツを作りたい、発信したい! そういう思いで当サイトを運営しています。

    コメントを残す

    気楽にコメントをお願いします!

    SPAM対策が施されています。投稿に失敗すると1時間ロックされます。