如何在Pygame中生成第二次单击的位置?

时间:2014-10-07 18:54:23

标签: python pygame

我正在制作河内之塔。

它应该是这样的:你点击第一个塔,你想要一个磁盘移动的位置,然后点击你希望磁盘移动到的第二个塔。磁盘应从第一个塔(列表)移动到第二个塔(另一个列表)。

我的问题是,当您第一次单击时,代码会生成位置,在此之后您应该再次单击以确定磁盘的位置,但代码会自动获取第一次单击的位置。

以下是我的代码示例:

import pygame, sys
from pygame.locals import *

pygame.init()

DISPLAYSURF = pygame.display.set_mode((500, 400))
pygame.display.set_caption("Tower of Hanoi")

block_red = pygame.image.load('red.png')
block_blue = pygame.image.load('blue.png')
block_green = pygame.image.load('green.png')

rod1 = [block_red, block_blue, block_green]
rod2 = []
rod3 = []

WHITE = (255, 255, 255)

while True:

    DISPLAYSURF.fill(WHITE)

    # get the position of the mouse click
    for event in pygame.event.get():
        if event.type == MOUSEBUTTONDOWN:
            mousex, mousey = pygame.mouse.get_pos()
            click1 = mousex, mousey

            # first in the left part of the screen
            if (mousex > 0) and (mousex < 166) and (mousey > 0) and (mousey < 400):

                if len(rod1) == 0:
                    print "not valid"

                elif len(rod1) == 1 or 2 or 3:
                    disk1 = rod1[-1]
                    rod1.remove(disk1)

                    # click again in a other part of the screen
                    if event.type == MOUSEBUTTONDOWN:
                        mousex, mousey = pygame.mouse.get_pos()   
                        click2 = mousex, mousey

                        if (mousex > 166) and (mousex < 333) and (mousey > 0) and (mousey < 400):
                            rod2.append(disk1)
                        elif (mousex > 333) and (mousex < 500) and (mousey > 0) and (mousey < 400):
                            rod3.append(disk1)
                        else: 
                            rod1.append(disk1)

    # if statement fot the middle part
    # if statement for the right part                        

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    pygame.display.update()

3 个答案:

答案 0 :(得分:1)

我认为这一行不符合您的预期:

elif len(rod1) == 1 or 2 or 3:

在解释器中测试它不评估为True,而是总是评估为2。

您可能打算做以下事情:

elif len(rod1) in (1, 2, 3):

甚至:

elif len(rod1) > 0:

此外,您仍然可以选择一系列“或”语句来满足您的需求:

[不推荐]

elif len(rod1) == 1 or len(rod1) == 2 or len(rod1) == 3:

如果任何一个语句的计算结果为True,则条件语句也将为True。

答案 1 :(得分:1)

请记住,您的代码会循环运行,因此您必须跟踪游戏的状态

点击第一个塔改变游戏的状态:现在选择了一个塔,点击塔现在做了不同的事情(它从第一个塔移动到第二个塔)

在您的示例中,您只需要跟踪当前是否选择了塔的事实(当然,每个塔都有块)。不要害怕单词 state ,一个简单的变量就足够了。

看一下下面的代码(注意评论)。它只是跟踪变量selected中的选定杆,然后检查它是否设置为决定是否需要移动块。

import pygame
from collections import namedtuple

pygame.init()
screen = pygame.display.set_mode((500, 400))

# create a named tuple to keep track of the size/location of the rods and their blocks
Rod = namedtuple('Rod', ['rect', 'items'])

# first rod has 4 items. The just use a number to keep track of the size of the blocks 
rods = (Rod(pygame.rect.Rect((100, 150, 25, 250)), [6, 5, 4, 3, 2, 1]),
        Rod(pygame.rect.Rect((225, 150, 25, 250)), []),
        Rod(pygame.rect.Rect((350, 150, 25, 250)), []))

# keep track of the currently selected rod
selected = None

while True:
    if pygame.event.get(pygame.QUIT): break

    screen.fill(pygame.color.Color('white'))

    # draw the rods. It's easy since every rod has a rect which we can use with pygame.draw.rect
    for rod in rods:
        # if a rod is selected, we draw it yellow instead of black
        pygame.draw.rect(screen, pygame.color.Color('yellow' if selected == rod else 'black'), rod.rect)    
        # draw each block of each rod
        for i, item in enumerate(rod.items):
            r = pygame.rect.Rect(rod.rect.x - item * 8, 375 - 25 * i, 25 + item * 16, 25) 
            pygame.draw.rect(screen, pygame.color.Color('green' if selected == rod else 'darkgreen'), r)    

    for e in pygame.event.get():
        if e.type == pygame.MOUSEBUTTONDOWN:
            # check if we clicked a rod. It's easy since every rod has a rect
            rod = next((r for r in rods if r.rect.collidepoint(pygame.mouse.get_pos())), None)
            if rod:
                if selected:
                    # if there's already a rod selected, move block from one the selected
                    # rod to the clicked rod
                    rod.items.append(selected.items.pop())
                    selected = None
                elif rod.items:
                    # if no rod is selected, selected the currently clicked one (if it has blocks)
                    selected = rod
            else:
                selected = None

    pygame.display.flip()   

结果:

enter image description here

答案 2 :(得分:0)

我个人会做的是围绕你的代码循环......

clicklocations = []
for clicknumber in range(0,1):
    # get the position of the mouse click
    for event in pygame.event.get():
        if event.type == MOUSEBUTTONDOWN:
            mousex, mousey = pygame.mouse.get_pos()
            clicklocations.append([mousex, mousey])

 # code for left part of the screen
 if clicklocations[0] in left part of screen, do stuff etc. etc.
 # code for middle part of the screen
 # code for right part of the screen

像这样。

然后,您将同时存储两个点击位置,而不必重写您的点击代码两次。