在编写一个地牢探索者游戏时,需要对游戏中的角色和怪物在游戏地图中的移动进行编程。地图可以看作一个笛卡尔坐标网格,角色的位置用包含 x 和 y 值的元组 (x,y) 来表示。游戏以回合制进行,在一个回合中,角色只能向上、下、左或右移动一格。
在游戏中,设计了一种简单的移动系统,其中角色将在每个回合根据情况做出移动决策。本质上,这是一种“健忘”的移动系统。基本流程图如下:
- 找到目标方向
- 根据方向创建移动优先级列表,例如“('r','u','d','l')”表示角色先尝试向右移动,然后尝试向上、向下和向左移动。
- 按照优先级顺序尝试每个可能的移动。如果第一个移动失败(例如遇到障碍物),则会依次尝试其他移动,直到找到第一个成功的移动。然后停止移动。
在步骤 3 中,尝试实现移动方式如下:
def move(direction, location):
http://www.jshk.com.cn/mb/reg.asp?kefu=xiaoding;//爬虫IP免费获取;
try:
# 尝试移动,如果无法向该方向移动,则引发 Movementerror 异常
-snip-
return 1 # 表示移动成功
except Movementerror:
return 0 # 表示移动不成功(因此角色尚未移动)
priority_list = ('r','u','d','l')
if move('r', location):
pass
elif move('u', location):
pass
elif move('d', location):
pass
elif move('l', location):
pass
else:
pass
在 if/else 块中,程序将尝试优先级列表中的第一个移动。在 move 函数中,角色将尝试移动。如果角色没有遇到障碍物并成功移动,则函数返回 1,导致程序继续执行 pass 并停止。如果角色遇到障碍物,函数返回 0,然后尝试下一个移动。
然而,这种方法导致了两个问题:
- 如何在函数内部编辑函数中传递的变量,同时返回编辑是否成功?
- 如何根据优先级列表的顺序更改 if/else 语句的顺序?需要在运行时进行更改,因为优先级列表可能会发生变化,从而导致尝试移动的不同顺序。
解决方案
问题 1 的解决方案
要编辑函数中传递的变量,需要在函数内部对其进行更改,然后将更改后的值返回。但是,如果直接对变量进行更改,那么将不会真正更改变量的值,而只是让函数内的变量引用其他内容,而原始变量保持不变。因此,解决方案是返回该值,然后将变量分配给返回值。
def move(direction, location):
try:
-snip-
return True, new_location
except Movementerror:
return False, location
priority_list = ('r','u','d','l')
for direction in priority_list:
success, new_location = move(direction, location)
if success:
break
else:
new_location = location
问题 2 的解决方案
将相对较大的 if/elif 树结构更改为一个简单的循环即可解决这个问题:
priority_list = ('r','u','d','l')
for direction in priority_list:
if move(direction, location):
break
这种方法更简洁、更容易重用,并且可以自动“遵循优先级列表”的顺序,而无需更改代码本身。