Как сделать управляемую симуляцию вируса с помощью turtle python - PullRequest
0 голосов
/ 30 мая 2020

Мне было поручено сделать управляемую симуляцию Covid-19 с использованием python черепахи для школьного проекта. Так что я сделал группу случайно движущихся черепах и случайно выбранных «одержимых» и случайно выбранных «зараженных» черепах. Я пытался сделать "одержимых" управляемыми клавишами со стрелками, а также выбирал другую "здоровую" черепаху, если предыдущая заразилась. Проблема в том, что я не знаю, как разделить элементы управления, поскольку все они были помечены как класс «Человек». Я также не знаю, как заставить его выбрать другую здоровую черепаху, когда та инфицирована. Вот запутанный код. Извините за плохой engli sh.

from turtle import Screen, Turtle
"""
This imports the screen and turtle from the turtle module
"""
from random import randint, choice
"""
This is to use the random integer function and the random choosing of the infected
"""
from time import sleep
posessed = 0
class Person(Turtle):
    population = []

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

        self.shapesize(0.4)
        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 all_infected(cls):
        return [person for person in cls.population if person.posessed()]

    def posess(self):
        self.color('yellow')

    def posessed(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() # this will undo forward()

def make_population(amount):

    for _ in range(amount):
        Person()

def posess_random():
    person = choice(Person.population)
    person.posess()
    posessed+1

def infect_random():
    person = choice(Person.population)
    person.infect()

def simulation():
    """ This will simulate the virus outbreak scenarios (quarantine, or not quarantine) """
    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):
        for person.infected in Person.population:
            person.random_move()

            if not person.infected():
                for infected in Person.all_infected():
                    if person.distance(infected) < 30:
                        person.infect()
                        #this is used to set distance to get infected. In this case I did 30

        screen.update()
        sleep(0.1)


screen = Screen()
screen.setup(500,500)
screen.tracer(0)
screen.bgcolor(str(input("Enter desired background color: ")))
simulation()

screen.exitonclick()
               #this should do it

Тысм перед рукой

1 Ответ

1 голос
/ 30 мая 2020

Итак, я сделал кучу беспорядочно движущихся черепах

Во-первых, этот код работает не так, как было опубликовано - мне пришлось исправить как минимум три ошибки, чтобы заставить его запустить. Удивительно, поскольку он содержит лишь незначительные изменения в моей переделке , в коде @ LST_2020 , первый из которых работает нормально. И нет никакой ссылки / ссылки на этот код! Продолжаем:

Ниже представлена ​​моя переработка нашего кода, чтобы исправить ваши введенные ошибки и сделать человека одержимого перемещаемым вручную. (Попутно исправив написание слова «одержимый».) И если одержимый вступает в контакт с инфицированным человеком, либо по собственному желанию, либо по движению инфицированного человека, одержимый становится зараженным и случайным образом здоровый человек, если таковой имеется, становится одержимым и может перемещаться вручную:

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

INFECTION_DISTANCE = 30
PERSON_RADIUS = 8
WIDTH, HEIGHT = 500, 500
CURSOR_SIZE = 20

possessed = 0

class Person(Turtle):
    population = []

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

        self.shapesize(PERSON_RADIUS / CURSOR_SIZE)
        self.penup()
        self.setpos(randint(-WIDTH/2, WIDTH/2), randint(-HEIGHT/2, HEIGHT/2))

        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'

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

    def possess(self):
        self.color('green')

    def possessed(self):
        return self.pencolor() == 'green'

    def random_move(self):
        self.right(randint(-90, 90))
        self.forward(randint(0, 10))

        x, y = self.position()

        if not (PERSON_RADIUS - WIDTH/2 < x < WIDTH/2 - PERSON_RADIUS and PERSON_RADIUS - HEIGHT/2 < y < HEIGHT/2 - PERSON_RADIUS):
            self.undo()  # this will undo forward()

def make_population(amount):
    for _ in range(amount):
        Person()

def possess_random():
    possessed = None

    healthy = Person.all_healthy()

    if healthy:
        possessed = choice(healthy)
        possessed.possess()

        screen.onkey(partial(move_up, possessed), 'Up')
        screen.onkey(partial(move_down, possessed), 'Down')
        screen.onkey(partial(move_right, possessed), 'Right')
        screen.onkey(partial(move_left, possessed), 'Left')

    return possessed

def infect_random():
    person = None

    healthy = Person.all_healthy()

    if healthy:
        person = choice(healthy)
        person.infect()

    return person

def check_infection(person):
    for infected in Person.all_infected():
        if person.distance(infected) < INFECTION_DISTANCE:
            is_possessed = person.possessed()

            person.infect()

            if is_possessed:
                possess_random()

def simulation(amount, moves):
    """ This will simulate the virus outbreak scenarios (quarantine, or not quarantine) """
    make_population(amount)

    infect_random()
    possess_random()
    screen.update()

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

            if not person.infected():
                check_infection(person)

        screen.update()
        sleep(0.1)

def move_up(possessed):
    y = possessed.ycor() + 10

    if y < HEIGHT/2 - PERSON_RADIUS:
        possessed.sety(y)
        check_infection(possessed)

def move_down(possessed):
    y = possessed.ycor() - 10

    if y > PERSON_RADIUS - HEIGHT/2:
        possessed.sety(y)
        check_infection(possessed)

def move_right(possessed):
    x = possessed.xcor() + 10

    if x < WIDTH/2 - PERSON_RADIUS:
        possessed.setx(x)
        check_infection(possessed)

def move_left(possessed):
    x = possessed.xcor() - 10

    if x > PERSON_RADIUS - WIDTH/2:
        possessed.setx(x)
        check_infection(possessed)

amount = int(input("Enter amount of people within the area: "))
moves = int(input("Enter the amount of moves these people will do: "))

screen = Screen()
screen.setup(WIDTH, HEIGHT)

screen.listen()
screen.tracer(False)

simulation(amount, moves)

screen.tracer(True)
screen.exitonclick()

Я изменил цвет одержимости на зеленый, так как не мог легко увидеть желтую точку на фоне цвета черепахи по умолчанию. И я переместил вводимые вопросы перед первым вызовом черепахи, чтобы пользователю не приходилось возвращаться в консоль, чтобы ответить на них.

Как я отмечал в своем оригинале, вам следует рассмотреть возможность использования событий таймера черепахи чтобы сделать людей более автономными, вместо for _ in range(moves): loop, которое также блокирует некоторые события с черепахами.

...