pygame制作打地鼠游戏时遇到的问题

大家好,我又双叒叕来提问了[doge]

最近在学pygame,学到制作打地鼠游戏时,我发现当我想通过点击来消除地鼠时,地鼠并不会消失

-------------------------------------------------------------下面是代码------------------------------------------------------------

import pygame
import random

pygame.init()
pygame.display.set_caption('打地鼠')
screen = pygame.display.set_mode((800, 600))
grass = pygame.image.load('D:\xxx\image\grass.png')
grass = pygame.transform.scale(grass, (800, 600))
hole = pygame.image.load('D:\xxx\image\hole.png')
mouse = pygame.image.load('D:\xxx\image\mouse.png')
hammer = pygame.image.load('D:\xxx\image\hammer.png')
mouse_list = []
mouse_list2 = []
rect_mouse = []
y = 3
x = 4

def new_mouse():
    while True:
        q = random.randint(0, x*y-1)
        abc = mouse_list[q]
        if mouse_list[q] not in mouse_list2:
            mouse_list2.append(abc)
            rect_mouse.append(pygame.Rect(abc[0], abc[1], 100, 112))
            break
        if len(mouse_list2) == x*y:
            break
    
#用户事件
EVENT = pygame.USEREVENT + 1
#计时器
pygame.time.set_timer(EVENT, 1000)
        
while True:
    pos = pygame.mouse.get_pos()
    
    hole_y = 200
    hole_x = 150
    screen.blit(grass, (0, 0))
    
    for i in range(y):
        hole_x = 150
        for o in range(x):
            mouse_list.append([hole_x, hole_y])
            screen.blit(hole, (hole_x, hole_y))
            hole_x += 150
        hole_y += 120
        
    for a in mouse_list2:
        screen.blit(mouse, [a[0], a[1]-40])
        
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
        if event.type == EVENT:
            new_mouse()
        if event.type == pygame.MOUSEBUTTONDOWN:
            for a in rect_mouse:
                if a.collidepoint(pos):
                    mouse_list2.remove([a[0], a[1]])
    
    screen.blit(hammer, [pos[0], pos[1]])

    pygame.display.update()
    pygame.time.Clock().tick(120)


-----------------------------------------下面是报错--------------------------------------

Traceback (most recent call last):
  File "D:\xxx\mouse.py", line 59, in <module>
    mouse_list2.remove([a[0], a[1]])
ValueError: list.remove(x): x not in list

希望大家给个解答,谢谢!

方案来自 梦想橡皮擦 狂飙组基于 GPT 编写的 “程秘”


你的代码中,当地鼠被点击时,虽然你使用了 collidepoint 方法来判断鼠标是否与地鼠重叠,但是你在移除地鼠时使用的是地鼠坐标的列表 [a[0], a[1]],而不是 rect_mouse 列表中的 Rect 对象。这样就导致了即使你点击了地鼠,它也不会被移除。

你可以将 rect_mouse 列表改成存储 Rect 对象,然后在移除地鼠时使用 remove 方法移除对应的 Rect 对象。修改后的代码如下:

import pygame
import random
 
pygame.init()
pygame.display.set_caption('打地鼠')
screen = pygame.display.set_mode((800, 600))
grass = pygame.image.load('D:\xxx\image\grass.png')
grass = pygame.transform.scale(grass, (800, 600))
hole = pygame.image.load('D:\xxx\image\hole.png')
mouse = pygame.image.load('D:\xxx\image\mouse.png')
hammer = pygame.image.load('D:\xxx\image\hammer.png')
mouse_list = []
mouse_list2 = []
rect_mouse = []
y = 3
x = 4
 
def new_mouse():
    while True:
        q = random.randint(0, x*y-1)
        abc = mouse_list[q]
        if mouse_list[q] not in mouse_list2:
            mouse_list2.append(abc)
            rect_mouse.append(pygame.Rect(abc[0], abc[1], 100, 112))
            break
        if len(mouse_list2) == x*y:
            break
    
#用户事件
EVENT = pygame.USEREVENT + 1
#计时器
pygame.time.set_timer(EVENT, 1000)
        
while True:
    pos = pygame.mouse.get_pos()
    
    hole_y = 200
    hole_x = 150
    screen.blit(grass, (0, 0))
    
    for i in range(y):
        hole_x = 150
        for o in range(x):
            mouse_list.append([hole_x, hole_y])
            screen.blit(hole, (hole_x, hole_y))
            hole_x += 150
        hole_y += 120
        
    for a in mouse_list2:
        screen.blit(mouse, [a[0], a[1]-40])
        
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
        if event.type == EVENT:
            new_mouse()
        if event.type == pygame.MOUSEBUTTONDOWN:
            for a in rect_mouse:
                if a.collidepoint(pos):
                    rect_mouse.remove(a)
                    mouse_list2.remove([a[0], a[1]])
    
    screen.blit(hammer, [pos[0], pos[1]])
 
    pygame.display.update()
    pygame.time.Clock().tick(120)

根据你的代码和报错信息,可以看出是因为尝试从列表 mouse_list2 中移除一个不存在的元素导致的错误。

具体来说,是因为在处理鼠标点击事件时,你尝试从 rect_mouse 中找到对应的地鼠矩形,并使用 remove 方法从 mouse_list2 中移除该地鼠,但是这里使用的元素 [a[0], a[1]] 并不是 mouse_list2 中的元素,而是 rect_mouse 中对应的矩形的坐标。因此在移除元素时出现了错误。

解决这个问题的方法有多种,以下是一种简单的方法:

在 new_mouse() 函数中创建一个 mouse_rects 列表,用于保存所有地鼠的矩形。
在 pygame.MOUSEBUTTONDOWN 事件处理中,遍历 mouse_rects 列表,找到与当前鼠标位置相交的矩形,并将对应的地鼠从 mouse_list2 中移除。
具体实现代码如下:

import pygame
import random

pygame.init()
pygame.display.set_caption('打地鼠')
screen = pygame.display.set_mode((800, 600))
grass = pygame.image.load('D:\xxx\image\grass.png')
grass = pygame.transform.scale(grass, (800, 600))
hole = pygame.image.load('D:\xxx\image\hole.png')
mouse = pygame.image.load('D:\xxx\image\mouse.png')
hammer = pygame.image.load('D:\xxx\image\hammer.png')
mouse_list = []
mouse_rects = []
y = 3
x = 4

def new_mouse():
    while True:
        q = random.randint(0, x*y-1)
        abc = mouse_list[q]
        if abc not in mouse_rects:
            mouse_rects.append(abc)
            break
        if len(mouse_rects) == x*y:
            break
    
#用户事件
EVENT = pygame.USEREVENT + 1
#计时器
pygame.time.set_timer(EVENT, 1000)
        
while True:
    pos = pygame.mouse.get_pos()
    
    hole_y = 200
    hole_x = 150
    screen.blit(grass, (0, 0))
    
    for i in range(y):
        hole_x = 150
        for o in range(x):
            mouse_list.append(pygame.Rect(hole_x, hole_y, 100, 112))
            screen.blit(hole, (hole_x, hole_y))
            hole_x += 150
        hole_y += 120
        
    for a in mouse_rects:
        screen.blit(mouse, [a[0], a[1]-40])
        
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
        if event.type == EVENT:
            new_mouse()
        if event.type == pygame.MOUSEBUTTONDOWN:
            for a in mouse_rects:
                if a.collidepoint(pos):
                    mouse_rects.remove(a)
    
    screen.blit(hammer, [pos[0], pos[1]])

    pygame.display.update()
    pygame.time.Clock().tick(120)

你的代码中,处理点击消除地鼠的部分似乎有点问题。你使用collidepoint()方法检测是否点击到了地鼠,但是你传递的是地鼠所在位置的列表 [a[0], a[1]],而不是 pygame.Rect 对象。

你可以尝试将 rect_mouse 列表中存储的 pygame.Rect 对象传递给 collidepoint() 方法,如下所示:

if event.type == pygame.MOUSEBUTTONDOWN:
    for a in rect_mouse:
        if a.collidepoint(pos):
            mouse_list2.remove([a[0], a[1]])
            rect_mouse.remove(a)


在这个例子中,当鼠标按下时,程序会遍历 rect_mouse 中的所有 pygame.Rect 对象,并使用 collidepoint() 方法检查鼠标点击是否在矩形内。如果点击在矩形内,则从 mouse_list2 和 rect_mouse 中删除对应的地鼠和矩形对象。

希望这可以解决你的问题!