簡體   English   中英

在if語句永遠不會為False的情況下設置為True的變量

[英]variable that is set to True in if statement never becomes False

我有一個矩形坐標列表,正在迭代以測試與每個坐標的碰撞。 列表如下所示: 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。

當我在if語句下移動self.hovering ,它可以工作,但是在不滿足if條件時,請勿將self.hovering設置回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()

您可以為列表中的每個矩形在循環內設置self.hovering 這意味着,在循環之后, self.hovering的值self.hovering對應於最后一個矩形的“懸停狀態”。

我認為您想在循環之前設置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

您的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的對,它仍將繼續循環對。 要在找到“好”對時停止循環,可以使用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

代碼在列表中進行迭代,並且在每個步驟之后self.hovering都會更改。 因此,最后一個矩形決定打印哪個值,因為它是唯一影響它的值,因為在循環之外調用了打印功能。

更新
如果希望在任何矩形適合的情況下將其設置為True,則可以使用:

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。 在這種情況下,給它一個由所謂的列表理解創建的列表。 列表理解等效於以下內容:

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

但是,它不需要先創建一個空列表,因此更加緊湊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM