0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【農家はReplace()されました】迷路を再帰関数を用いた深さ優先探索で解いてみる

0
Posted at

はじめに

迷路を解く方法として、公式では壁伝いに移動する方法が紹介されていて記事もそれに倣ったものが多いので、今回は別の方法として再帰関数を用いた深さ優先探索で攻略してみる。
※再配置による連続の探索は考慮していません。

ソースコード

#
# 深さ優先探索で迷路を攻略する関数
#	direction: 移動方向
#
def depth_first_search(direction=None):
	if direction:
		move(direction)
	
	# 今いる場所が宝箱の真上なら収穫してTrueを返す
	if get_entity_type() == Entities.Treasure:
		harvest()
		return True

	# 指定した方角に移動可能かつ元の場所に戻らない場合次のステップへ
	if can_move(North) and direction != South:
		if depth_first_search(North):
			return True
		move(South)
	
	if can_move(South) and direction != North:
		if depth_first_search(South):
			return True
		move(North)
	
	if can_move(East) and direction != West:
		if depth_first_search(East):
			return True
		move(West)
	
	if can_move(West) and direction != East:
		if depth_first_search(West):
			return True
		move(East)
	
	# 行き止まりもしくはその先に宝箱がない場合Falseを返す
	return False


# 迷路の生成
clear()
plant(Entities.Bush)
substance = get_world_size() * 2**(num_unlocked(Unlocks.Mazes) - 1)
use_item(Items.Weird_Substance, substance)

# 迷路探索開始
depth_first_search()

解説

depth_first_search()の動作イメージを解説していく。

maze.png

1. スタートマス

def depth_first_search(direction=None):
	if direction:
		move(direction)
	
	# 今いる場所が宝箱の真上なら収穫してTrueを返す
	if get_entity_type() == Entities.Treasure:
		harvest()
		return True

	# 指定した方角に移動可能かつ元に戻る方角でない場合次のステップへ
	if can_move(North) and direction != South:
		if depth_first_search(North): # <- 再帰的に関数を呼び出す
			return True
		move(South)

引数はNoneのためどこにも移動せず、宝箱マスでもないためスルー。
北方向へ移動するため関数を再帰呼び出しする。

2. スタートマスから(1, 0)マスへ

def depth_first_search(direction=None):

	# 指定した方角に移動可能かつ元に戻る方角でない場合次のステップへ
	if can_move(North) and direction != South:
		if depth_first_search(North): # <- 再帰的に関数を呼び出す
			return True
		move(South)

スタートマスから北に移動する。
宝箱マスではないためスルー。
まだ北方向へ移動できるため関数を再帰呼び出しする。

3. (1, 0)マスから(2, 0)マスへ

def depth_first_search(direction=None):

	# 指定した方角に移動可能かつ元に戻る方角でない場合次のステップへ
	if can_move(North) and direction != South:
		if depth_first_search(North): # <- 再帰的に関数を呼び出す
			return True
		move(South)

上記と同様。

4. (2, 0)マスへから(3, 0)マスへ

def depth_first_search(direction=None):
    
	# 行き止まりなのでFalseを返す
	return False

(3, 0)マスではどの方向へも移動できないためFalseを返す。

5. (3, 0)マスへから(2, 0)マスへ

def depth_first_search(direction=None):

	# 指定した方角に移動可能かつ元に戻る方角でない場合次のステップへ
	if can_move(North) and direction != South:
		if depth_first_search(North): # <- Falseが返ってくる
			return True
		move(South)


	if can_move(East) and direction != West:
		if depth_first_search(East): # <- 再帰的に関数を呼び出す
			return True
		move(West)

3. の再帰呼び出しでFalseが返ってくるためif文はスキップし南【(3, 0)から(2, 0)】へ移動する。
次に東へ移動できるので関数を再帰呼び出しする。

7. 繰り返し

以降、上記の手順を宝箱が見つかるまで繰り返す。

おわりに

壁伝いに移動する方法と比べて、視点がぐるぐる動かないぶん理解しやすいかなという印象。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?