基于Python Turtle的可控新冠病毒模拟项目技术问题咨询
解决你的Python Turtle新冠模拟控制与切换问题
我来帮你搞定这两个核心问题,咱们一步一步拆解修改:
问题1:分离控制逻辑,用方向键操控指定海龟
原来靠颜色标记控制状态的方式不够灵活,咱们给Person类加个专属属性跟踪控制状态,再绑定方向键事件精准控制目标个体:
- 先修改
Person类的初始化逻辑,添加控制状态属性:
class Person(Turtle): population = [] controlled_person = None # 类属性,全局跟踪当前被控制的海龟 def __init__(self): super().__init__(shape='circle') self.shapesize(0.4) self.penup() self.setpos(randint(-250, 250), randint(-250, 250)) self.is_controlled = False # 初始未被控制 self.color('black') # 明确健康状态为黑色 Person.population.append(self)
- 编写方向键控制函数,只让被控制的海龟响应:
def move_up(): if Person.controlled_person and not Person.controlled_person.infected(): Person.controlled_person.setheading(90) Person.controlled_person.forward(10) # 边界检测,防止海龟跑出屏幕 if not (-250 < Person.controlled_person.xcor() < 250 and -250 < Person.controlled_person.ycor() < 250): Person.controlled_person.undo() def move_down(): if Person.controlled_person and not Person.controlled_person.infected(): Person.controlled_person.setheading(270) Person.controlled_person.forward(10) if not (-250 < Person.controlled_person.xcor() < 250 and -250 < Person.controlled_person.ycor() < 250): Person.controlled_person.undo() def move_left(): if Person.controlled_person and not Person.controlled_person.infected(): Person.controlled_person.setheading(180) Person.controlled_person.forward(10) if not (-250 < Person.controlled_person.xcor() < 250 and -250 < Person.controlled_person.ycor() < 250): Person.controlled_person.undo() def move_right(): if Person.controlled_person and not Person.controlled_person.infected(): Person.controlled_person.setheading(0) Person.controlled_person.forward(10) if not (-250 < Person.controlled_person.xcor() < 250 and -250 < Person.controlled_person.ycor() < 250): Person.controlled_person.undo()
- 在屏幕初始化后绑定方向键监听:
screen = Screen() screen.setup(500,500) screen.tracer(0) screen.bgcolor(str(input("Enter desired background color: "))) # 绑定方向键事件 screen.onkeypress(move_up, "Up") screen.onkeypress(move_down, "Down") screen.onkeypress(move_left, "Left") screen.onkeypress(move_right, "Right") screen.listen() # 让屏幕开始监听键盘输入
问题2:被控制海龟感染后自动切换新健康个体
咱们需要在模拟循环中定期检查当前被控制者的状态,一旦感染就从健康人群里挑选新的控制对象:
- 修复原代码中的错误(比如重复的
all_infected方法,以及posess_random的无效逻辑):
# 修复重复的方法,改为判断被控制个体 @classmethod def all_possessed(cls): return [person for person in cls.population if person.possessed()] # 重写选被控制者的函数,加入状态重置逻辑 def posess_random(): # 筛选健康个体:未感染、未被控制 healthy_people = [p for p in Person.population if not p.infected() and not p.is_controlled] if healthy_people: # 先重置之前的被控制者状态 if Person.controlled_person: Person.controlled_person.color('black') Person.controlled_person.is_controlled = False # 选新的被控制者并标记 person = choice(healthy_people) person.posess() person.is_controlled = True Person.controlled_person = person
- 在模拟循环中加入状态检查,触发自动切换:
def simulation(): amount=int(input("Enter amount of people within the area: " )) moves=int(input("Enter the amount of moves these people will do: ")) print("Entered amount of people: ", amount) print("Entered amount of movements: ", moves) make_population(amount) infect_random() posess_random() screen.update() for _ in range(moves): # 检查当前被控制者是否感染,是则切换新个体 if Person.controlled_person and Person.controlled_person.infected(): posess_random() # 遍历所有人执行移动和感染检测(修复原代码的语法错误) for person in Person.population: # 只有未被控制的人才随机移动 if not person.is_controlled: person.random_move() # 健康个体的感染检测 if not person.infected(): for infected in Person.all_infected(): if person.distance(infected) < 30: person.infect() screen.update() sleep(0.1)
完整修改后的代码
把所有修改整合后,就是可以正常运行的版本:
from turtle import Screen, Turtle from random import randint, choice from time import sleep class Person(Turtle): population = [] controlled_person = None # 全局跟踪被控制的海龟 def __init__(self): super().__init__(shape='circle') self.shapesize(0.4) self.penup() self.setpos(randint(-250, 250), randint(-250, 250)) self.is_controlled = False self.color('black') # 健康状态为黑色 Person.population.append(self) @classmethod def all_infected(cls): return [person for person in cls.population if person.infected()] @classmethod def all_possessed(cls): return [person for person in cls.population if person.possessed()] def infect(self): self.color('red') def infected(self): return self.pencolor() == 'red' def posess(self): self.color('yellow') def possessed(self): return self.pencolor() == 'yellow' def random_move(self): self.right(randint(-180,180)) self.forward(randint(0,10)) if not (-250 < self.xcor() <250 and -250 < self.ycor() < 250): self.undo() def make_population(amount): for _ in range(amount): Person() def posess_random(): healthy_people = [p for p in Person.population if not p.infected() and not p.is_controlled] if healthy_people: # 重置之前的被控制者 if Person.controlled_person: Person.controlled_person.color('black') Person.controlled_person.is_controlled = False # 选择新的被控制者 person = choice(healthy_people) person.posess() person.is_controlled = True Person.controlled_person = person def infect_random(): person = choice(Person.population) person.infect() # 方向键控制函数 def move_up(): if Person.controlled_person and not Person.controlled_person.infected(): Person.controlled_person.setheading(90) Person.controlled_person.forward(10) if not (-250 < Person.controlled_person.xcor() < 250 and -250 < Person.controlled_person.ycor() < 250): Person.controlled_person.undo() def move_down(): if Person.controlled_person and not Person.controlled_person.infected(): Person.controlled_person.setheading(270) Person.controlled_person.forward(10) if not (-250 < Person.controlled_person.xcor() < 250 and -250 < Person.controlled_person.ycor() < 250): Person.controlled_person.undo() def move_left(): if Person.controlled_person and not Person.controlled_person.infected(): Person.controlled_person.setheading(180) Person.controlled_person.forward(10) if not (-250 < Person.controlled_person.xcor() < 250 and -250 < Person.controlled_person.ycor() < 250): Person.controlled_person.undo() def move_right(): if Person.controlled_person and not Person.controlled_person.infected(): Person.controlled_person.setheading(0) Person.controlled_person.forward(10) if not (-250 < Person.controlled_person.xcor() < 250 and -250 < Person.controlled_person.ycor() < 250): Person.controlled_person.undo() def simulation(): amount=int(input("Enter amount of people within the area: " )) moves=int(input("Enter the amount of moves these people will do: ")) print("Entered amount of people: ", amount) print("Entered amount of movements: ", moves) make_population(amount) infect_random() posess_random() screen.update() for _ in range(moves): # 检查被控制者是否感染,切换新个体 if Person.controlled_person and Person.controlled_person.infected(): posess_random() for person in Person.population: if not person.is_controlled: person.random_move() if not person.infected(): for infected in Person.all_infected(): if person.distance(infected) < 30: person.infect() screen.update() sleep(0.1) screen = Screen() screen.setup(500,500) screen.tracer(0) screen.bgcolor(str(input("Enter desired background color: "))) # 绑定方向键 screen.onkeypress(move_up, "Up") screen.onkeypress(move_down, "Down") screen.onkeypress(move_left, "Left") screen.onkeypress(move_right, "Right") screen.listen() simulation() screen.exitonclick()
额外优化说明
- 用类属性
controlled_person直接跟踪控制目标,比单独全局变量更整洁 - 被控制海龟不再随机移动,完全由方向键操控,符合需求
- 给方向键控制加入边界检测,防止海龟跑出屏幕
- 修复了原代码中
for person.infected in Person.population:的语法错误 - 修复了
posess_random函数中posessed+1的无效代码问题
内容的提问来源于stack exchange,提问作者WhitèBlue
相关产品推荐
相关产品推荐

