python-3.x 问题与事件.MOUSEBUTTONDOWN在pygame故障时执行

wkyowqbh  于 2022-12-27  发布在  Python
关注(0)|答案(1)|浏览(165)

我试图用pygame库在python中创建一个井字游戏,并且在点击的网格中的每个矩形上画X,同时在该网格中的任何随机矩形中画圆圈,但这里的问题是,大多数情况下,当我启动程序并点击4个矩形时,只有三个圆圈出现,甚至只有两个出现,有时它工作得很好。
下面是我的代码:

import pygame
import random

white = (245, 243, 232)
hight = 3
width = 3
size = 167

screen = pygame.display.set_mode((500, 500))
pygame.display.set_caption("Tic Tac Toe")
screen.fill(white)

for i in range(0, hight):
    for j in range(0, width):
        pygame.draw.rect(screen, "Black", (i*size, j*size, size, size), 1) 

def rect(x, y):
# Return the Rect object created by the draw.rect method
    return pygame.draw.rect(screen, white, (x, y, 163, 163), 0)

rect1 = rect(2, 2)
rect2 = rect(169, 2)
rect3 = rect(336, 2)
rect4 = rect(2, 169)
rect5 = rect(169, 169)
rect6 = rect(336, 169)
rect7 = rect(2, 336)
rect8 = rect(169, 336)
rect9 = rect(336, 336)

def cross(x, y):
    pygame.draw.line(screen, "Black", (x, y), (x + 166, y + 166), 3)
    pygame.draw.line(screen, "Black", (x + 166, y-2), (x-2 , y + 166), 3)

    pygame.display.update()

    

def circle(x, y):
    pygame.draw.circle(screen, "Black", (x + 81.5, y + 81.5), 50, 3)

    pygame.display.update()

flag = False
flag_ = False
flag__ = False
flag___= False
flag____ = False
flag_____= False
flag______= False
flag_______= False
flag________= False
pygame.display.update()

rectch = [rect1, rect2, rect3, rect4, rect5, rect6, rect7, rect8, rect9]

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit() 
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            pos = pygame.mouse.get_pos()
            if rect1.collidepoint(pos) and not flag:
                cross(2,2)
                rectch.remove(rect1)
                chosen_rect = random.choice(rectch)
                x, y = chosen_rect.topleft
                circle(x, y)
                print("here")
                flag = True
            elif rect2.collidepoint(pos) and not flag_:
                cross(169,2)
                rectch.remove(rect2)
                chosen_rect = random.choice(rectch)
                x, y = chosen_rect.topleft
                circle(x, y)
                print("here")
                flag_ = True
            elif rect3.collidepoint(pos) and not flag__:
                cross(336,2)
                rectch.remove(rect3)
                chosen_rect = random.choice(rectch)
                x, y = chosen_rect.topleft
                circle(x, y)
                print("here")
                flag__ = True
            elif rect4.collidepoint(pos) and not flag___:
                cross(2,169)
                rectch.remove(rect4)
                chosen_rect = random.choice(rectch)
                x, y = chosen_rect.topleft
                circle(x, y)
                print("here")
                flag___ = True
            elif rect5.collidepoint(pos) and not flag____:
                cross(169,169)
                flag____ = True
            elif rect6.collidepoint(pos) and not flag_____:
                cross(336,169)
                flag_____ = True
            elif rect7.collidepoint(pos) and not flag______:
                cross(2,336)
                flag______ = True
            elif rect8.collidepoint(pos) and not flag_______:
                cross(169,336)
                flag_______ = True
            elif rect9.collidepoint(pos) and not flag________:
                cross(336,336)
                flag________ = True

现在你可能会在代码块中看到,我试图在while循环中的4个条件语句中打印"here",我试图这样做,这样我就可以看到当我点击那个certian rect和low时,是否调用了circle函数,看到其中4个在每次执行时都打印得很好,所以我不知道这里发生了什么。
我知道很难想象这个过程,所以这里有一些图片可以描述这个问题:
[一个月一次]
[this when i click on 4 rectangles and all 4 circles are produced and is working fine (please keep in mind that i did not change the code)]

jpfvwuh4

jpfvwuh41#

您的代码中有几个问题可能会导致您看到的问题。
首先,您使用了大量的if语句来检查每个单独矩形上的鼠标单击。这可能会使代码难以阅读和维护,也可能使代码更容易出错。相反,您可以使用一个if语句来检查任何矩形上的鼠标单击,然后使用一个单独的函数来根据单击的矩形来处理十字或圆的绘制。
例如,您可以定义一个函数handle_click(pos),该函数将鼠标单击的位置作为参数,并确定单击了哪个矩形,然后该函数可以调用cross或circle函数在屏幕上绘制相应的符号:

def handle_click(pos):
    if rect1.collidepoint(pos):
        cross(2,2)
        rectch.remove(rect1)
        chosen_rect = random.choice(rectch)
        x, y = chosen_rect.topleft
        circle(x, y)
    elif rect2.collidepoint(pos):
        cross(169,2)
        rectch.remove(rect2)
        chosen_rect = random.choice(rectch)
        x, y = chosen_rect.topleft
        circle(x, y)
    # ... and so on for the other rectangles

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit() 
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            pos = pygame.mouse.get_pos()
            handle_click(pos)

第二,您使用了大量的标志来跟踪每个矩形是否被单击过。这也会使代码难以阅读和维护。相反,您可以使用单个列表或集合来跟踪哪些矩形被单击过。
例如,您可以定义clicked_rects列表,并在单击每个矩形时将其添加到列表中。然后,您可以在绘制十字或圆之前检查矩形是否在clicked_rects列表中:

clicked_rects = []

def handle_click(pos):
    if rect1.collidepoint(pos) and rect1 not in clicked_rects:
        cross(2,2)
        rectch.remove(rect1)
        chosen_rect = random.choice(rectch)
        x, y = chosen_rect.topleft
        circle(x, y)
        clicked_rects.append(rect1)
    elif rect2.collidepoint(pos) and rect2 not in clicked_rects:
        cross(169,2)
        rectch.remove(rect2)
        chosen_rect = random.choice(rectch)
        x, y = chosen_rect.topleft
        circle(x, y)
        clicked_rects.append(rect2)
    # ... and so on for the other rectangles

为了提供帮助,我还重新编写了代码,给予之更好。下面是代码的修订版本,它解决了我前面提到的问题。在这个版本中,我定义了一个函数handle_click(pos)为了处理在矩形上的鼠标点击,以及跟踪哪些矩形被点击的单个列表Clicked_rects。我还对代码进行了重构,以使用更少的if语句和变量:

import pygame
import random

# Set up the screen
white = (245, 243, 232)
hight = 3
width = 3
size = 167
screen = pygame.display.set_mode((500, 500))
pygame.display.set_caption("Tic Tac Toe")
screen.fill(white)

# Draw the grid of rectangles
for i in range(0, hight):
    for j in range(0, width):
        pygame.draw.rect(screen, "Black", (i*size, j*size, size, size), 1) 

# Define the rectangles
def rect(x, y):
    return pygame.draw.rect(screen, white, (x, y, 163, 163), 0)

rect1 = rect(2, 2)
rect2 = rect(169, 2)
rect3 = rect(336, 2)
rect4 = rect(2, 169)
rect5 = rect(169, 169)
rect6 = rect(336, 169)
rect7 = rect(2, 336)
rect8 = rect(169, 336)
rect9 = rect(336, 336)

# Define the functions to draw crosses and circles
def cross(x, y):
    pygame.draw.line(screen, "Black", (x, y), (x + 166, y + 166), 3)
    pygame.draw.line(screen, "Black", (x + 166, y-2), (x-2 , y + 166), 3)
    pygame.display.update()

def circle(x, y):
    pygame.draw.circle(screen, "Black", (x + 81.5, y + 81.5), 50, 3)
    pygame.display.update()

# Define a function to handle mouse clicks on the rectangles
def handle_click(pos):
    clicked_rects = []
    rectch = [rect1, rect2, rect3, rect4, rect5, rect6, rect7, rect8, rect9]
    if rect1.collidepoint(pos) and rect1 not in clicked_rects:
        cross(2,2)
        rectch.remove(rect1)

希望这能有所帮助!

相关问题