简体   繁体   English

为什么我的循环仍在运行? (Python Zelle 图形)

[英]Why is my loop still running? (Python Zelle Graphics)

I'm trying to figure out why the while loop in one of my functions is still running even after the points in my graphics are equal, which is when I set it to stop.我试图弄清楚为什么我的一个函数中的while循环仍然在运行,即使我的图形中的点相等,这是我将它设置为停止的时候。 Is there anything I'm doing wrong?有什么我做错了吗? I've tried to switch other things around to get it to work but no luck.我试图切换其他东西以使其正常工作,但没有运气。 It's for a game--when the character reaches the endbox the loop needs to break, but it isn't doing that after I explicitly coded it to.这是一个游戏——当角色到达结束框时,循环需要中断,但在我明确编码后它并没有这样做。 It's in the second function I have:它在我的第二个功能中:

from graphics import *

def field():
    #creating the window
    win = GraphWin('The Field',400,400)
    win.setBackground('white')
    #drawing the grid
    boxlist = []
    for i in range(0,400,40):
        for j in range(0,400,40):
            box = Rectangle(Point(i,j),Point(i+40,j+40))
            box.setOutline('light gray')
            box.draw(win)
            boxlist.append(box)
    #creating other boxes
    startbox = Rectangle(Point(0,0),Point(40,40))
    startbox.setFill('lime')
    startbox.setOutline('light gray')
    startbox.draw(win)
    endbox = Rectangle(Point(360,360),Point(400,400))
    endbox.setFill('red')
    endbox.setOutline('light gray')
    endbox.draw(win)
    boxlist.append(startbox)
    boxlist.append(endbox)
    #creating Pete
    pete = Rectangle(Point(2,2),Point(38,38))
    pete.setFill('gold')
    pete.draw(win)
    return win,boxlist,pete

def move(win2,boxlist,pete,endbox):
    peteloc = pete.getCenter()
    #creating loop to move pete
    while peteloc != endbox.getCenter():
        click = win2.getMouse()
        x = click.getX()
        y = click.getY()
        peteloc = pete.getCenter()
        petex = peteloc.getX()
        petey = peteloc.getY()
        #moving pete
        if x>=petex+20 and y<=petey+20 and y>=petey-20:
            pete.move(40,0)
        elif x<=petex-20 and y<=petey+20 and y>=petey-20:
            pete.move(-40,0)
        elif y>=petey+20 and x<=petex+20 and x>=petex-20:
            pete.move(0,40)
        elif y<=petey-20 and x<=petex+20 and x>=petex-20:
            pete.move(0,-40)
        peteloc = pete.getCenter()

# The main function
def main():
    win2,boxlist,pete = field()
    endbox = boxlist[len(boxlist)-1]
    move(win2,boxlist,pete,endbox)

main()

I think maybe it is caused by precision of float.我想可能是由浮点精度引起的。 I guess pete.getCenter() and endbox.getCenter() are something like [float, float], you should avoid using != between float, such as 1.0000001 is not equal to 1.我猜 pete.getCenter() 和 endbox.getCenter() 有点像 [float, float],你应该避免在 float 之间使用!= ,比如 1.0000001 不等于 1。

So even if the character reaches the endbox, the position will still get a little float bias.所以即使字符到达endbox,位置仍然会有一点浮动偏差。

So you can change a != b to abs(a - b) > acceptable_error when the error is acceptable.因此,当错误可以abs(a - b) > acceptable_error时,您可以将a != b更改为abs(a - b) > acceptable_error acceptable_error。 Sample code is like:示例代码如下:

# while peteloc != endbox.getCenter():
while abs(peteloc.getX() - endbox.getCenter().getX()) > 0.01 and abs(peteloc.getY() - endbox.getCenter().getY()) > 0.01:

Hope that will help you.希望这会帮助你。

Zelle graphics Point objects don't appear to ever compare as equal: Zelle 图形Point对象似乎从来都不相等:

>>> from graphics import *
>>> a = Point(100, 100)
>>> b = Point(100, 100)
>>> a == b
False
>>> 

We have to extract coordinates and do our own comparison.我们必须提取坐标并进行自己的比较。 Although @recnac provides a workable solution (+1), I'm going to suggest a more general one.尽管@recnac 提供了一个可行的解决方案 (+1),但我将建议一个更通用的解决方案。 We'll create a distance() method that's valid for any object that inherits from _BBox , which includes Rectangle , Oval , Circle and Line :我们将创建一个distance()方法,该方法对任何继承自_BBox对象都有效,其中包括RectangleOvalCircleLine

def distance(bbox1, bbox2):
    c1 = bbox1.getCenter()
    c2 = bbox2.getCenter()

    return ((c2.getX() - c1.getX()) ** 2 + (c2.getY() - c1.getY()) ** 2) ** 0.5

We can now measure the distance between objects, horizontally, vertically and diagonally.我们现在可以水平、垂直和对角线测量物体之间的距离。 Since your boxes are moving twenty pixels at a time, we can assume that if they are withing 1 pixel of each other, they are in the same location.由于您的盒子一次移动 20 个像素,我们可以假设如果它们彼此相差 1 个像素,则它们位于同一位置。 Your code rewritten to use the distance() method and other tweaks:您的代码重写为使用distance()方法和其他调整:

from graphics import *

def field(win):
    # drawing the grid
    boxlist = []

    for i in range(0, 400, 40):
        for j in range(0, 400, 40):
            box = Rectangle(Point(i, j), Point(i + 40, j + 40))
            box.setOutline('light gray')
            box.draw(win)
            boxlist.append(box)

    # creating other boxes
    startbox = Rectangle(Point(0, 0), Point(40, 40))
    startbox.setFill('lime')
    startbox.setOutline('light gray')
    startbox.draw(win)
    boxlist.append(startbox)

    endbox = Rectangle(Point(360, 360), Point(400, 400))
    endbox.setFill('red')
    endbox.setOutline('light gray')
    endbox.draw(win)
    boxlist.append(endbox)

    # creating Pete
    pete = Rectangle(Point(2, 2), Point(38, 38))
    pete.setFill('gold')
    pete.draw(win)

    return boxlist, pete

def distance(bbox1, bbox2):
    c1 = bbox1.getCenter()
    c2 = bbox2.getCenter()

    return ((c2.getX() - c1.getX()) ** 2 + (c2.getY() - c1.getY()) ** 2) ** 0.5

def move(win, pete, endbox):
    # creating loop to move pete

    while distance(pete, endbox) > 1:

        click = win.getMouse()
        x, y = click.getX(), click.getY()

        peteloc = pete.getCenter()
        petex, petey = peteloc.getX(), peteloc.getY()

        # moving pete
        if x >= petex + 20 and petey - 20 <= y <= petey + 20:
            pete.move(40, 0)
        elif x <= petex - 20 and petey - 20 <= y <= petey + 20:
            pete.move(-40, 0)
        elif y >= petey + 20 and petex - 20 <= x <= petex + 20:
            pete.move(0, 40)
        elif y <= petey - 20 and petex - 20 <= x <= petex + 20:
            pete.move(0, -40)

# The main function
def main():
    # creating the window
    win = GraphWin('The Field', 400, 400)
    win.setBackground('white')

    boxlist, pete = field(win)
    endbox = boxlist[-1]

    move(win, pete, endbox)

main()

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

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