首页 » 父与子的编程之旅:与小卡特一起学Python » 父与子的编程之旅:与小卡特一起学Python全文在线阅读

《父与子的编程之旅:与小卡特一起学Python》26.2 创建一个 Python Battle 机器人

关灯直达底部

我们来创建一个机器人,以便与 CircleAI 和 RandomAI 战斗。第一步是制定一个策略。因为这是我们创建的第一个 Python Battle 机器人,所以我们最好从一个简单的策略开始。

1. 如果面对着一个敌人,那么我应该攻击它。

2. 如果面对着墙,则我应该转弯。

3. 否则,我继续向前走。

尽管这不是最高级的策略,但它可能刚好可以打败 CircleAI。如果它打不过,我们还可以再回来改进它。

第二步是开始编码机器人。创建一个新 Python 文件(我把它叫作 better_than_circleai.py),然后输入以下代码:

class AI:    def __init__(self):pass    def turn(self):pass  

这是所有机器人都必须具备的基础代码。在游戏开始时创建机器人,此时 __init__ 函数会被调用。turn 函数会在每一回合被调用,并决定机器人做什么。这个类必须叫作 AI,否则 Python Battle 游戏不知道你的 AI 代码在哪里。

编写机器人的下一步是添加能让机器人执行我们制定的策略的代码。你将使用以下函数来控制机器人的移动:

  • self.robot.lookInFront

  • self.robot.turnRight

  • self.robot.turnLeft

  • self.robot.goForth

  • self.robot.attack

这些函数需要采用 self.robot.xx 的形式调用,因为 self 指向 AI 对象本身,而不是 AI 控制的机器人。AI 对象是不会移动或者攻击的,它只负责告知机器人需要做什么,具体的移动和攻击是由机器人对象来执行的。

我们来编写 turn 方法。移除代码中的 pass,添加下面的代码:

self.robot.goForth  

如果你现在测试一下这个机器人,会看到每一回合它都会尝试向前移动。这会导致它很快撞到游戏边界处的“墙”。如果敌人挡住了它的路,则它只会停止移动而已。你可以使用 self.robot.lookInFront 来修复这个问题。如果在正前方有一个可以攻击的敌人,则这个函数返回 "bot"。修改一下 turn 函数,像这样:

if self.robot.lookInFront == "bot":    self.robot.attackelse:    self.robot.goForth  

现在,如果在你的机器人前方有敌人挡路,则机器人会攻击它。但是如果机器人撞“墙”了,则它会停下来。如果前方是“墙”,则 self.robot.lookInFront 会返回 "wall"。将下面的代码加到 turn 函数中,放在 self.robot.attackelse 之间:

elif self.robot.lookInFront == "wall":    self.robot.turnRight  

现在,如果你运行代码,则机器人会开始转圈!当它撞到“墙”的时候会向右转,当它撞到下一堵“墙”时会再次向右转,一直这样运行下去。你更希望机器人在撞“墙”的时候能转身折返回去,而这需要两次右转才能完成。当机器人撞“墙”的时候,它需要右转一次,然后在一下回合中,再右转一次。也就是说,你需要机器人记住它现在是在做 U 型转身。你可以给 AI 设置一个新属性(变量)来记住它正在做什么。我们在 __init__ 函数中添加一行代码:

self.currentlyDoing = "forward"  

这将告诉机器人,当游戏开始时,它需要向前走。当机器人在做 U 型转身时,你可以将这个属性的值改为 "turnRight" 以便告知机器人它需要右转。修改之后的 turn 函数最终看起来像这样:

代码清单 26-1 完成的机器人 AI

class AI:    def __init__(self):self.currentlyDoing = "forward"    def turn(self):if self.robot.lookInFront == "bot":    self.robot.attackelif self.robot.lookInFront == "wall":    self.robot.turnRight    self.currentlyDoing = "turnRight"elif self.currentlyDoing == "turnRight":    self.robot.turnRight    self.currentlyDoing = "forward"else:    self.robot.goForth  

如果你运行这段代码,可能会发现这个 AI 有一定的缺陷。我们来修改一下以便我们的机器人可以打败 CircleAI。