简体   繁体   English

当一只乌龟靠近另一只乌龟时,我怎样才能让它做点什么?

[英]How can I make a turtle do something when it gets close to another turtle?

Good afternoon,下午好,

I am simulating a virus outbreak with the use of turtles.我正在使用海龟模拟病毒爆发。 I have come up with the following code, my question will be after the code:我想出了以下代码,我的问题将在代码之后:

import turtle
import random
import time

def make_population(amount):
    """
    Creates a list representing a population with a certain amount of people.
    """
    population = []
    for person in range(amount):
        population.append(turtle.Turtle())
    for person in population:
        person.shape("circle")
        person.shapesize(0.2)
    return population

def random_move(person):
    """
    Makes a turtle move forward a random amount and then turn a random amount.
    """
    person.forward(random.randint(0,20))
    person.right(random.randint(-180,180))

def check_boundary(person):
    """
    Checks if a turtle is still within the given boundaries.
    """
    if -250 <= person.xcor() <= 250 and -250 <= person.ycor() <= 250:
        return
    person.setpos(random.randint(-200,200),random.randint(-200,200))

def infect_random(population):
    """
    Gets a random item from the population list and turns one red
    """
    infected = random.choice(population)
    infected.color("red")
    return infected

def infect_person(person):
    """
    Makes the turtle infected
    """
    infected_person = person.color("red")
    return infected_person

def simulation(amount, moves = 0):
    """
    Simulates a virus outbreak
    """
    border = 500
    window = turtle.Screen()
    turtle.setup(500,500)
    turtle.tracer(0)
    population = make_population(amount)
    for person in population:
        person.penup()
        person.setpos(random.randint(-250,250),random.randint(-250,250))
    turtle.update()
    infected = infect_random(population)
    for move in range(moves):
        turtle.tracer(0)
        for person in population:
            random_move(person)
            if person.distance(infected) < 50:
                infect_person(person)
            check_boundary(person)
        turtle.update()
        time.sleep(0.5)

    window.exitonclick()

So when the simulation starts I infect 1 random person, and if other turtles get close, eg within 50 pixels, they will get infected too and turn red.因此,当模拟开始时,我会感染 1 个随机人,如果其他海龟靠近,例如在 50 像素内,它们也会被感染并变成红色。 However, these newly 'infected' turtles won't infect other turtles since they are not 'infected' as compared to the initial turtle.然而,这些新“感染”的乌龟不会感染其他乌龟,因为与最初的乌龟相比,它们没有“感染”。 I have tried changing it to infected = infect_person(person) but this just gives me an error.我曾尝试将其更改为受感染的 = infect_person(person) 但这只会给我一个错误。 I am stuck for a while now and was wondering if there is anyone who can help.我现在被困了一段时间,想知道是否有人可以提供帮助。 I have also thought about making two lists: population and infected_population maybe that can solve my issue but I couldn't figure out how to implement that in the rest of my code.我还考虑过制作两个列表:人口和感染人口也许可以解决我的问题,但我无法弄清楚如何在我的代码的 rest 中实现它。

Thanks in advance提前致谢

I believe the solution is separating low level turtle operations into a Person subclass of Turtle from high level operations on people in the simulation:我相信解决方案是将低级海龟操作与模拟中对人的高级操作分离为TurtlePerson子类:

from turtle import Screen, Turtle
from random import randint, choice
from time import sleep

class Person(Turtle):
    population = []

    def __init__(self):
        super().__init__(shape='circle')

        self.shapesize(0.2)
        self.penup()
        self.setpos(randint(-250, 250), randint(-250, 250))

        Person.population.append(self)

    @classmethod
    def all_infected(cls):
        return [person for person in cls.population if person.infected()]

    def infect(self):
        self.color('red')

    def infected(self):
        return self.pencolor() == 'red'

    def random_move(self):
        """
        Makes a turtle move forward a random amount and then turn a random amount.
        """

        self.right(randint(-180, 180))
        self.forward(randint(0, 20))

        # checks if turtle is still within the given boundaries.

        if not (-250 < self.xcor() < 250 and -250 < self.ycor() < 250):
            self.undo()  # undo forward()

def make_population(amount):
    """
    Creates a list representing a population with a certain amount of people.
    """

    for _ in range(amount):
        Person()

def infect_random():
    """
    Gets a random item from the population list and turns one red
    """

    person = choice(Person.population)
    person.infect()

def simulation(amount=20, moves=100):
    """
    Simulates a virus outbreak
    """

    make_population(amount)

    infect_random()

    screen.update()

    for _ in range(moves):
        for person in Person.population:
            person.random_move()

            if not person.infected():
                for infected in Person.all_infected():
                    if person.distance(infected) < 50:
                        person.infect()

        screen.update()
        sleep(0.5)

screen = Screen()
screen.setup(500, 500)
screen.tracer(0)

simulation()

screen.exitonclick()

We could go further with turtle timer events to make the people more autonomous instead of the for _ in range(moves): loop.我们可以 go 进一步使用海龟计时器事件,以使人们更加自主,而不是for _ in range(moves):循环。

在此处输入图像描述

I believe you have made a small example but we miss information about data structure, is person a class?我相信你做了一个小例子,但我们错过了有关数据结构的信息,人是 class 吗?

You do not reassign the person as infected.您不会将该人重新指定为感染者。

When you infected the first people当你感染了第一批人

infected = infect_random(population)

you assign it as infected, but when you infect other persone you don't, you turn it in red return the person:您将其指定为已感染,但是当您感染其他人时,您没有将其变为红色,返回该人:

def infect_person(person):
    """
    Makes the turtle infected
    """
    infected_person = person.color("red")
    return infected_person

but hen In your code you don't assign it,但是在你的代码中你没有分配它,

infect_person(person)

I suggest either to use a way to know who is infected or who is not.我建议要么使用一种方法来了解谁被感染或谁没有被感染。 For example: If you have used POO:例如:如果您使用过 POO:

  • you can add a field is_infected你可以添加一个字段 is_infected

  • else use a list that keeps the indices of the person being infected?否则使用一个列表来保存被感染者的索引?

Doing that you will have to change the way you test if someone near is infected.如果附近有人被感染,那么您将不得不改变测试方式。 For all person near a person if one is infected then I am becoming infected...对于一个人附近的所有人,如果有人被感染,那么我就会被感染......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM