Как использовать черепаху.distance(x) для членов списка черепах?

Я пытаюсь выполнить обнаружение столкновений среди членов списка черепах, чтобы переменная возвращала логическое значение, чтобы разорвать цикл while true. Это работает с ОДНОЙ из черепах, но не с остальными. Он также печатает расстояние (для отладки) только для того, с которым работает столкновение. Что сбивает с толку, так это то, что тот же синтаксис, который используется в функции столкновения, отлично работает в циклах обнаружения столкновений шара и стены.

import turtle
from turtle import Screen
import random
from random import randrange

screen = turtle.Screen()
screen.setup(500, 500)
screen.title('Balls Bounce')

friend = turtle.Turtle()
friend.shape('turtle')
friend.color('green')
friend.turtlesize(3)

def friendUp():
    friend.setheading(90)
    friend.forward(45)

def friendDown():
    friend.setheading(270)
    friend.forward(45)

def friendRight():
    friend.setheading(0)
    friend.forward(45)

def friendLeft():
    friend.setheading(180)
    friend.forward(45)

screen.onkey(friendUp, "Up")
screen.onkey(friendLeft, "Left")
screen.onkey(friendRight, "Right")
screen.onkey(friendDown, "Down")
screen.listen()

def createBall():
    ball = turtle.Turtle(shape = "circle")
    ball.penup()
    ball.color("Red")
    ball.turtlesize(3)
    ball.setheading(randrange(361))
    ball.forward(5)
    return ball

balls = []
for i in range(5):
    b = createBall()
    balls.append(b)

bodySize = 80
halfBodySize = bodySize / 2
collisionDistance = 5
isCollision = False

def collision(balls, friend):
    distance = 0
    for b in balls:
        distance = b.distance(friend)
        print(distance // 1)
        if distance < halfBodySize:
            print('Collision!')
            global isCollision
            isCollision = True
            break
        return isCollision

while True:
    collision(balls, friend)
    if isCollision == True:
        break
    for b in balls:
        b.forward(5)
        xPos = b.position()[0]
        yPos = b.position()[1]
        if xPos > 250 or xPos < -250:
            b.forward(-5)
            b.setheading(randrange(361))
        if yPos > 250 or yPos < -250:
            b.forward(-5)
            b.setheading(randrange(361))

screen.mainloop()

Я пробовал использовать карту и перечисление, но они продолжают возвращать проблемы, которые я не могу понять. Например, использование enumerate возвращает проблемы с кортежами, и я не уверен, что правильно настроил для него синтаксис. Карта имеет аналогичные проблемы.

Пожалуйста, отредактируйте вопрос, чтобы ограничить его конкретной проблемой и указать достаточно подробностей, чтобы найти адекватный ответ.

Сергей Кох 09.06.2024 06:06

Пожалуйста, внимательно подумайте над логикой. Когда должно произойти return isCollision: после того, как цикл завершил проверку шаров, или в конце каждого прохода цикла? Следовательно, должен ли этот код находиться внутри цикла или снаружи? Это там, где должно быть?

Karl Knechtel 09.06.2024 08:27

Или посмотрите на это по-другому: у вас есть список balls, и вы хотите знать, верно ли для любого из них утверждение «этот мяч сталкивается с игроком» — да? Итак, у этого есть много стандартных решений, и его достаточно легко исследовать (для этого я добавил отдельную дублирующую ссылку). Похоже, вам не повезло допустить ошибку в каждом из нескольких подходов. Но большая часть проблемы заключается в вашем общем понимании. Если вы описываете это как «использование перечисляемых возвращаемых кортежей», тогда вам необходимо изучить, что означают эти слова, как работают инструменты и как понимать ошибки.

Karl Knechtel 09.06.2024 08:32

(Аналогично: неправильный синтаксис может вызвать только SyntaxError или какой-либо его подтип, например IndentationError или TabError. Если вы получаете неправильный результат, это либо из-за неправильной логики, либо просто из-за непонимания того, как работает конкретный инструмент.)

Karl Knechtel 09.06.2024 08:34
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
4
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

return isCollision необходимо сделать на один уровень дальше, внутри if, который обнаруживает столкновение:

def collision(balls, friend):
    for b in balls:
        distance = b.distance(friend)
        print(distance // 1)

        if distance < halfBodySize:
            print('Collision!')
            return True

    return False

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

Нет необходимости в global — просто верните значение и используйте его непосредственно в вызывающем коде:

if collision(balls, friend):
    # there was a collision between a ball and friend

Вы также можете удалить свои вызовы print(), после чего рассмотрите возможность использования any:

def collision(balls, friend):
    return any(b.distance(friend) < halfBodySize for b in balls)

Вот минимальное доказательство правильности:

from random import randint
from turtle import Screen, Turtle


def check_collision(ball, balls):
    return any(b.distance(ball) < HALF_BODY_SIZE for b in balls)


def reposition():
    for t in turtles:
        t.goto(randint(-w, w), randint(-h, h))

    friend.color("green")

    if check_collision(friend, balls):
        friend.color("red")

    screen.update()


HALF_BODY_SIZE = 60
screen = Screen()
w, h = screen.screensize()
screen.tracer(0)
turtles = []

for _ in range(35):
    t = Turtle(shape = "circle")
    turtles.append(t)
    t.shapesize(3)
    t.penup()

friend, balls = turtles[-1], turtles[:-1]
reposition()
screen.onclick(lambda *_: reposition())
screen.mainloop()

Кроме того, используйте snake_case для функций и переменных, а не camelCase, согласно соглашению PEP-8.

Также предпочитайте from turtle import Screen, Turtle, чтобы не путать функциональные и ООП-интерфейсы. Ваш текущий код никогда не использует from turtle import Screen, который можно поймать с помощью линтера, такого как Flake 8.

Другие вопросы по теме