同学们,上一节课我们了解了破解迷宫的终极策略——“右手定则”。今天,我们要把这套理论翻译成无人机能听懂的 Python 代码。

这段代码看似很长,但逻辑极其严密。我们要像拆解机械表一样,把它分成三个部分来看。

🏗️ 第一阶段:召唤迷宫(准备工作)

要想走迷宫,我们得先有一个迷宫。在农场里,用“奇异物质”浇灌“灌木”,就能长出迷宫。

def solve_maze():
    # 1. 探测环境:我们在迷宫里吗?
    if get_entity_type() != Entities.Treasure and get_entity_type() != Entities.Hedge:
  • 解释:无人机低头看一眼,如果脚下既不是“宝藏(Treasure)”也不是“树篱(Hedge,也就是迷宫的墙)”,说明我们在一片空地上。那我们就得先从零开始种一个迷宫。

        # 2. 种下基础植物:灌木
        if get_ground_type() == Grounds.Grassland:
            till() # 把草地翻成泥土
        plant(Entities.Bush) # 种下灌木
  • 解释:这是我们的老套路了,确保有泥土,然后种下灌木。

        # 3. 计算魔法材料的用量
        mazes_unlocked = num_unlocked(Unlocks.Mazes)
        substance_needed = get_world_size() * (2 ** (mazes_unlocked - 1))
  • 解释:这是游戏官方给我们的计算公式。

    • num_unlocked:查一下我们把“迷宫科技”升级了多少次。

    • **:在 Python 里,两个星号代表乘方2 ** 3 就是 $2^3$(2的3次方)。随着科技升级,需要的材料呈指数级增长。

        # 4. 检查库存并召唤
        if num_items(Items.Weird_Substance) >= substance_needed:
            use_item(Items.Weird_Substance, substance_needed)
        else:
            return 
  • 解释:做事要谨慎。召唤前先看看背包里的奇异物质够不够。

    • 够(>=:使用物品,灌木瞬间变迷宫!

    • 不够(else:执行 return重点记住 return,它的意思是“罢工,直接退出整个函数”。如果材料不够还硬等,无人机会卡死,所以我们直接让它退出。

🧭 第二阶段:右手法则寻路(核心大脑)

迷宫生成了,无人机现在站在迷宫的入口。真正的考验开始了!

    # 1. 打造我们的“指南针”
    dirs = [North, East, South, West]
    current_dir_idx = 0 
  • 解释:我们建了一个列表 dirs(Directions的缩写),把四个绝对方向按顺时针排好:北(0)、东(1)、南(2)、西(3)。

  • current_dir_idx = 0:我们假定无人机一开始是面朝北方(第 0 个方向)的。

    # 2. 不拿宝藏誓不罢休!
    while get_entity_type() != Entities.Treasure:
  • 解释:只要脚下踩的不是宝藏,这个循环就会一直转下去。

        # 3. 相对方向的“数学魔法”
        right_idx = (current_dir_idx + 1) % 4
        left_idx = (current_dir_idx - 1) % 4
        back_idx = (current_dir_idx + 2) % 4
  • 解释:这是全篇最聪明的数学技巧!既然列表是顺时针排的,那么:

    • 右边就是当前索引 + 1。比如面朝北(0),右边就是东(1)。

    • 左边就是当前索引 - 1

    • 后边就是当前索引 + 2

    • 为什么要用 % 4(取余数)? 假设无人机面朝西(3),它的右边应该是北(0)。但是 $3 + 1 = 4$,列表里根本没有第 4 个东西(会报错)!用 % 4 就能让数字像时钟一样绕回 0。这就是循环索引的魔法!

🚦 关键:会说话的 move() 指令

        # 优先级 1:右边有路吗?
        if move(dirs[right_idx]):
            current_dir_idx = right_idx
  • 超级重点:在编程农场里,move() 不仅是一个动作,它还会汇报结果

    • 如果它成功走了一步,它会变成 True

    • 如果它撞墙了没动,它会变成 False

  • if move(...):这句话相当于无人机闭着眼睛往右撞一下。如果撞通了(返回 True),条件成立,然后执行 current_dir_idx = right_idx(告诉自己:我现在面向右边了)。

        # 优先级 2:右边撞墙了,那前面有路吗?
        elif move(dirs[current_dir_idx]):
            pass 
  • 解释:如果上面那个 if 撞墙了,就会来到 elif(否则如果)。无人机尝试往“正前方”撞一下。如果走通了,因为方向没变,我们用 pass(什么都不做,直接过)。

        # 优先级 3:右边和前面都是墙,左边有路吗?
        elif move(dirs[left_idx]):
            current_dir_idx = left_idx
  • 解释:继续尝试左边。如果通了,更新自己的朝向为左边。

        # 优先级 4:三面都是墙(死胡同),掉头!
        else:
            move(dirs[back_idx])
            current_dir_idx = back_idx
  • 解释:如果前面的 ifelif 全都撞墙了(返回 False),说明进了死胡同,就会执行 else。无人机往后退一步,并把自己的朝向更新为“后面”。


💰 第三阶段:拿到宝藏!

    # 离开 while 循环,说明我们踩到宝藏了!
    harvest()
  • 解释:当 while 循环结束时,意味着脚下踩着的终于不是树篱,而是宝藏了。毫不犹豫地呼叫 harvest(),把金币收入囊中!

def solve_maze():
	# ================= 1. 生成迷宫 =================
	# 如果脚下既不是宝藏也不是树篱,说明我们要种个新迷宫
	if get_entity_type() != Entities.Treasure and get_entity_type() != Entities.Hedge:
		# 确保脚下是耕地或草地可以种灌木
		if get_ground_type() == Grounds.Grassland:
			till()
			
		plant(Entities.Bush)
		
		# 计算需要的奇异物质数量 (按照游戏给的公式)
		mazes_unlocked = num_unlocked(Unlocks.Mazes)
		substance_needed = get_world_size() * (2 ** (mazes_unlocked - 1))
		
		# 生成迷宫!
		if num_items(Items.Weird_Substance) >= substance_needed:
			use_item(Items.Weird_Substance, substance_needed)
		else:
			return # 物质不够,直接退出防止卡死

	# ================= 2. 右手法则寻路 =================
	# 定义方向列表,按照顺时针排列 (右转就是 index+1,左转是 index-1)
	dirs = [North, East, South, West]
	current_dir_idx = 0 # 初始面向 North
	
	# 只要脚下不是宝藏,就一直找
	while get_entity_type() != Entities.Treasure:
		# 计算各个方向在列表中的索引 (% 4 确保索引在 0-3 之间循环)
		right_idx = (current_dir_idx + 1) % 4
		left_idx = (current_dir_idx - 1) % 4
		back_idx = (current_dir_idx + 2) % 4
		
		# 优先级 1:尝试向右走
		if move(dirs[right_idx]):
			current_dir_idx = right_idx # 成功向右,更新当前朝向
			
		# 优先级 2:右边有墙,尝试直走
		elif move(dirs[current_dir_idx]):
			pass # 方向不变
			
		# 优先级 3:右边和前面都有墙,尝试向左走
		elif move(dirs[left_idx]):
			current_dir_idx = left_idx
			
		# 优先级 4:进了死胡同,掉头向后走
		else:
			move(dirs[back_idx])
			current_dir_idx = back_idx
			
	# ================= 3. 拿到宝藏! =================
	harvest()

# 开始寻宝
while True:
	solve_maze()