在if语句中永远变为False时设置为True的变量

时间:2016-07-27 22:25:23

标签: python list pygame iteration

我有一个矩形坐标列表,我正在迭代以测试每个坐标的碰撞。列表如下:self.rectangle_list = [(200, 30, 100, 10), (200, 60, 100, 10), (200, 90, 100, 10), (200, 120, 100, 10), (200, 150, 100, 10)]。我的for循环代码如下。

        mouse_x, mouse_y = event_obj.pos # mouse_x, mouse_y are the coordinates of the mouse.
        for rects in self.rectangle_list:
            x, y, w, h = rects
            if x <= mouse_x <= x + w and y <= mouse_y <= y + h:
                self.hovering = True
            else:
                self.hovering = False
        print(self.hovering)

当我打印出self.hovering时,唯一一次更改为True的时候是鼠标光标位于列表中最后一个矩形的坐标中。

当我在self.hovering语句下移动if时它会起作用,但在self.hovering条件不符合时,永远不会将if设置回False。

重现问题的示例代码如下:

import pygame as pg


class RenderRects:
    def __init__(self, surface, rects_to_render=0):
        self.surface = surface
        self.rects_to_render = rects_to_render
        self.rectangle_list = []
        self.hovering = False

    def render_rects(self):
        y_padding = 0
        for rects in range(self.rects_to_render):
            y_padding += 30
            menu_items_rect = (200, y_padding, 100, 10)
            pg.draw.rect(self.surface, (255, 0, 0), menu_items_rect)
            if len(self.rectangle_list) > 5:
                del self.rectangle_list[4:]
            self.rectangle_list.append(menu_items_rect)

    def check_for_rect_collision(self, event_obj):
       #-----------------Where problem is-----------#
        mx, my = event_obj.pos
        for rects in self.rectangle_list:
            x, y, w, h = rects
            if x <= mx <= x + w and y <= my <= y + h:
                self.hovering = True
            else:
                self.hovering = False
        print(self.hovering)
        #-----------------Where problem is-----------#

    def update_rects(self, event_obj):
        if event_obj.type == pg.MOUSEMOTION:
            self.check_for_rect_collision(event_obj)

def main():
    WIDTH = 800
    HEIGHT = 600
    display = pg.display.set_mode((WIDTH, HEIGHT))

    R = RenderRects(display, rects_to_render=5)

    running = True
    while running:
        for e in pg.event.get():
            if e.type == pg.QUIT:
                running = False
                pg.quit()
                quit()

            R.update_rects(e)

        display.fill((255, 255, 255))
        R.render_rects()
        pg.display.flip()

if __name__ == '__main__':
    main()

3 个答案:

答案 0 :(得分:4)

在循环中为{em>列表中的每个矩形设置self.hovering。这意味着,在循环之后,self.hovering的值对应于&#34;悬停状态&#34;只有最后矩形。

我认为你想在循环之前设置self.hovering = False,如果其中一个矩形符合你的条件,在循环中将它设置为True。这样,只有当您的矩形中至少有一个符合您的条件时,self.hovering == True才会成立。

这是一个简单的问题示例:

numbers = [2,3,4]
contains_odd = False
for number in numbers:
    if number % 2 == 0:
        contains_odd = False # this is wrong!
    else:
        contains_odd = True
# contains_odd == (numbers[2] % 2 == 1) == False

解决方案是:

numbers = [2,3,4]
contains_odd = False
for number in numbers:
    if number % 2 == 1:
        contains_odd = True

# contains_odd == True

答案 1 :(得分:2)

您的if声明存在问题:

if x <= mouse_x <= x + w and y <= mouse_y <= y + h:
                self.hovering = True

您不能像在x <= mouse_x <= x + w中那样链接小于/大于。这真的被翻译成:

if x <= (mouse_x <= x + w) ....

True == 1False == 0以来,这意味着如果mouse_x <= x + wTrue,则x <= (mouse_x <= x + w)真正成为x <= 1


修改 - 添加了其他问题说明 (感谢Michael Hoff建议)

你的循环也有问题。在循环中,每个矩形对的 ,设置变量self.hovering。这意味着您将使用当前矩形的状态不断覆盖self.hovering的值 - 而不是任何矩形正在悬停。

相反,既然你关心self.hovering永远 True,你应该只设置True案例中的值:

self.hovering = False # assume it's not hovering at first
for rects in self.rectangle_list:
    x, y, w, h = rects
    if x <= mouse_x and mouse_x <= x + w and y <= mouse_y  and mouse_y <= y + h:
        self.hovering = True # now it will always be True

虽然这解决了循环问题,但它仍然有点效率低下,因为即使找到一个产生self.hovering = True的对,它也会继续循环对。当你找到一个好的&#34;时停止循环。对,您可以使用break,它只是过早地结束循环。

self.hovering = False # assume it's not hovering at first
for rects in self.rectangle_list:
    x, y, w, h = rects
    if x <= mouse_x and mouse_x <= x + w and y <= mouse_y  and mouse_y <= y + h:
        self.hovering = True # now it will always be True
        break # exit the loop, since we've found what we're looking for

答案 2 :(得分:1)

代码遍历列表并且每个步骤后self.hovering都会发生变化。因此,最后一个矩形确定打印哪个值,因为它是影响它的唯一值,因为打印函数被称为循环的外部

更新
如果你希望它是真的,如果任何的矩形适合,你可以使用:

any([x <= mouse_x <= x + w and y <= mouse_y <= y + h for x,y,w,h in self.rectangle_list])

Any是一个内置函数,它被赋予一个可迭代的参数。只要iterable中的任何值为True,它就返回True,否则返回False。在这种情况下,给出一个由所谓的列表推导创建的列表。列表理解等同于以下内容:

lis = []
for x, y, w, h in self.rectangle_list:
    lis.append(x <= mouse_x <= x + w and y <= mouse_y <= y + h)

但是,它不需要先创建一个空列表,因此更紧凑。