【问题标题】:How do I prevent program misinterpreting input in pygame?如何防止程序误解 pygame 中的输入?
【发布时间】:2018-02-17 00:43:15
【问题描述】:

我正在 pygame 中为我的学校项目制作一个简单的井字游戏。我设法整理了一些代码(对不起,如果它有点乱,它可能是我试图用来解决我当前问题的代码的剩余部分),这在某种程度上按预期工作。然而,我确实遇到了一个奇怪的错误,我不知道为什么,但似乎我的程序无法处理快速的用户输入(如果用户点击得很快),而不是放一个圆圈,然后是一个十字,它可能会放 2圆圈或 2 个十字。如果用户走得很慢,它工作正常,但我正在寻找一种方法来摆脱这个问题,如果有人能暗示我一些我会非常感激的事情。这是源代码:

import pygame
import sys
from pygame.locals import *

DISPLAY_WIDTH = 400
DISPLAY_HEIGHT = 400
BOX_SIZE = 50
BOARD_WIDTH = 3
BOARD_HEIGHT = 3


BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255,   0,   0)
BACKGROUND_COLOR = (198, 187, 133)
indexList = ["a1", "a2", "a3", "b1", "b2", "b3", "c1", "c2", "c3"]

gameFinished = False


def game_loop():
    global DISPLAY_WIDTH, DISPLAY_HEIGHT, displaySurface, gameFinished

    pygame.init()
    FPSCLOCK = pygame.time.Clock()

    displaySurface = pygame.display.set_mode((DISPLAY_WIDTH, DISPLAY_HEIGHT))
    pygame.display.set_caption("Tic Tac Toe")
    displaySurface.fill(BACKGROUND_COLOR)
    pygame.draw.line(displaySurface, BLACK, (140, 20), (140, 380), 10)
    pygame.draw.line(displaySurface, BLACK, (260, 20), (260, 380), 10)
    pygame.draw.line(displaySurface, BLACK, (20, 140), (380, 140), 10)
    pygame.draw.line(displaySurface, BLACK, (20, 260), (380, 260), 10)
    box1 = pygame.Rect(20, 20, 120, 120)
    box2 = pygame.Rect(140, 20, 120,120)
    box3 = pygame.Rect(260, 20, 120, 120)
    box4 = pygame.Rect(20, 140, 120, 120)
    box5 = pygame.Rect(140, 140, 120, 120)
    box6 = pygame.Rect(260, 140, 120, 120)
    box7 = pygame.Rect(20, 260, 120, 120)
    box8 = pygame.Rect(140, 260, 120, 120)
    box9 = pygame.Rect(260, 260, 120, 120)
    circle = pygame.image.load("circle.png")
    cross = pygame.image.load("cross.png")
    boardBoxes = [box1, box2, box3,  box4, box5, box6, box7, box8, box9]
    mouseY = 0
    mouseX = 0
    placesTaken = {0: False, 1: False, 2: False, 3: False, 4: False, 5: False, 6: False, 7: False, 8: False}

    turn = 1
    board = generate_boxes(0)
    print(repr(board))

    while not gameFinished:
        mouseClick = False
        for event in pygame.event.get():
            if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
                pygame.quit()
                sys.exit()
            elif event.type == MOUSEMOTION:
                mouseX, mouseY = event.pos
            elif event.type == MOUSEBUTTONUP:
                mouseClick = True
                mouseX, mouseY = event.pos
            if mouseClick is True and turn == 1:
                get_mouse_overbox(mouseX, mouseY, boardBoxes, turn, board)
                print("Player")
                turn += 1
            elif mouseClick is True and turn == 2:
                get_mouse_overbox(mouseX, mouseY, boardBoxes, turn, board)
                turn -= 1

        if board[0] == 1 and placesTaken[0] is False:
            put_image(circle, 20, 20)
            placesTaken[0] = True
        elif board[0] == 2 and placesTaken[0] is False:
            put_image(cross, 20, 20)
            placesTaken[0] = True
        if board[1] == 1 and placesTaken[1] is False:
            put_image(circle, 140, 20)
            placesTaken[1] = True
        elif board[1] == 2 and placesTaken[1] is False:
            put_image(cross, 140, 20)
            placesTaken[1] = True
        if board[2] == 1 and placesTaken[2] is False:
            put_image(circle, 260, 20)
            placesTaken[2] = True
        elif board[2] == 2 and placesTaken[2] is False:
            put_image(cross, 260, 20)
            placesTaken[2] = True
        if board[3] == 1 and placesTaken[3] is False:
            put_image(circle, 20, 140)
            placesTaken[3] = True
        elif board[3] == 2 and placesTaken[3] is False:
            put_image(cross, 20, 140)
            placesTaken[3] = True
        if board[4] == 1 and placesTaken[4] is False:
            put_image(circle, 140, 140)
            placesTaken[4] = True
        elif board[4] == 2 and placesTaken[4] is False:
            put_image(cross, 140, 140)
            placesTaken[4] = True
        if board[5] == 1 and placesTaken[5] is False:
            put_image(circle, 260, 140)
            placesTaken[5] = True
        elif board[5] == 2 and placesTaken[5] is False:
            put_image(cross, 260, 140)
            placesTaken[5] = True
        if board[6] == 1 and placesTaken[6] is False:
            put_image(circle, 20, 260)
            placesTaken[6] = True
        elif board[6] == 2 and placesTaken[6] is False:
            put_image(cross, 20, 260)
            placesTaken[6] = True
        if board[7] == 1 and placesTaken[7] is False:
            put_image(circle, 140, 260)
            placesTaken[7] = True
        elif board[7] == 2 and placesTaken[7] is False:
            put_image(cross, 140, 260)
            placesTaken[7] = True
        if board[8] == 1 and placesTaken[8] is False:
            put_image(circle, 260, 260)
            placesTaken[8] = True
        elif board[8] == 2 and placesTaken[8] is False:
            put_image(cross, 260, 260)
            placesTaken[8] = True

        FPSCLOCK.tick(60)
        pygame.display.update()


def put_image(image_name, x_cord, y_cord):
    global displaySurface
    displaySurface.blit(image_name, (x_cord, y_cord))


def generate_boxes(value):
    boxesFilled = []
    for i in range(9):
        boxesFilled.append(value)
    return boxesFilled


def board_getcircles(board):
    onlyCircleBoard = [0 if i == 2 else i for i in board]
    return onlyCircleBoard


def board_getcrosses(board):
    onlyCrossBoard = [0 if i == 2 else i for i in board]
    return onlyCrossBoard


def get_mouse_overbox(mouse_x, mouse_y, box_list, which_turn, boardlist):
    if which_turn == 1:
        for counter in range(len(box_list)):
            if box_list[counter].collidepoint(mouse_x, mouse_y):
                boardlist[counter] = 1
    elif which_turn == 2:
        for caunter in range(len(box_list)):
            if box_list[caunter].collidepoint(mouse_x, mouse_y):
                boardlist[caunter] = 2

game_loop()

【问题讨论】:

    标签: python input pygame logic


    【解决方案1】:

    pygame.event.get 将检索队列中的所有事件,以便您可以同时呈现多个更新。因为您在填写图像时不检查轮到谁,所以您有可能一次填写多个十字或圆圈。

    为什么会这样:

            elif event.type == MOUSEBUTTONUP:
                mouseClick = True
                mouseX, mouseY = event.pos
    

    在循环中mouseClick 第一次被设置为True,但是因为队列中有多个事件 event.get() 有另一个元素要处理,这次它再次运行循环mouseclick 是真的。但是这次我们仍然在循环中,因为event.get() 是一个以上的列表,所以:

            elif event.type == MOUSEMOTION:
                mouseX, mouseY = event.pos
    

    现在执行,但mouseClick 在这里处理它时错误地True,所以我们再次陷入另一个语句,这不是你想要的。

    【讨论】:

      【解决方案2】:

      如果有人有兴趣找到答案或只是遇到类似问题,这里是我更改后的代码(现在可以使用,感谢Shutter87的回答)

      import pygame
      import sys
      from pygame.locals import *
      
      DISPLAY_WIDTH = 400
      DISPLAY_HEIGHT = 400
      BOX_SIZE = 50
      BOARD_WIDTH = 3
      BOARD_HEIGHT = 3
      
      
      BLACK = (0, 0, 0)
      WHITE = (255, 255, 255)
      RED = (255,   0,   0)
      BACKGROUND_COLOR = (198, 187, 133)
      indexList = ["a1", "a2", "a3", "b1", "b2", "b3", "c1", "c2", "c3"]
      
      gameFinished = False
      
      
      def game_loop():
          global DISPLAY_WIDTH, DISPLAY_HEIGHT, displaySurface, gameFinished
      
          pygame.init()
          FPSCLOCK = pygame.time.Clock()
      
          displaySurface = pygame.display.set_mode((DISPLAY_WIDTH, DISPLAY_HEIGHT))
          pygame.display.set_caption("Tic Tac Toe")
          displaySurface.fill(BACKGROUND_COLOR)
          pygame.draw.line(displaySurface, BLACK, (140, 20), (140, 380), 10)
          pygame.draw.line(displaySurface, BLACK, (260, 20), (260, 380), 10)
          pygame.draw.line(displaySurface, BLACK, (20, 140), (380, 140), 10)
          pygame.draw.line(displaySurface, BLACK, (20, 260), (380, 260), 10)
          box1 = pygame.Rect(20, 20, 120, 120)
          box2 = pygame.Rect(140, 20, 120,120)
          box3 = pygame.Rect(260, 20, 120, 120)
          box4 = pygame.Rect(20, 140, 120, 120)
          box5 = pygame.Rect(140, 140, 120, 120)
          box6 = pygame.Rect(260, 140, 120, 120)
          box7 = pygame.Rect(20, 260, 120, 120)
          box8 = pygame.Rect(140, 260, 120, 120)
          box9 = pygame.Rect(260, 260, 120, 120)
          circle = pygame.image.load("circle.png")
          cross = pygame.image.load("cross.png")
          boardBoxes = [box1, box2, box3,  box4, box5, box6, box7, box8, box9]
          mouseY = 0
          mouseX = 0
          placesTaken = {0: False, 1: False, 2: False, 3: False, 4: False, 5: False, 6: False, 7: False, 8: False}
      
          turn = 1
          board = generate_boxes(0)
          print(repr(board))
      
          while not gameFinished:
              moveDone = False
              mouseClick = False
      
      
      
      
      
      
              for event in pygame.event.get():
                  if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
                      pygame.quit()
                      sys.exit()
                  elif event.type == MOUSEBUTTONUP:
                      mouseClick = True
                      mouseX, mouseY = event.pos
                  if mouseClick is True and turn == 1 and moveDone == False:
                      get_mouse_overbox(mouseX, mouseY, boardBoxes, turn, board)
                      print("Player1")
                      moveDone = True
                  elif mouseClick is True and turn == 2 and moveDone == False:
                      get_mouse_overbox(mouseX, mouseY, boardBoxes, turn, board)
                      print("Player2")
                      moveDone = True
      
                  if board[0] == 1 and placesTaken[0] is False:
                      put_image(circle, 20, 20)
                      placesTaken[0] = True
                      turn += 1
                  elif board[0] == 2 and placesTaken[0] is False:
                      put_image(cross, 20, 20)
                      placesTaken[0] = True
                      turn -= 1
                  if board[1] == 1 and placesTaken[1] is False:
                      put_image(circle, 140, 20)
                      placesTaken[1] = True
                      turn += 1
                  elif board[1] == 2 and placesTaken[1] is False:
                      put_image(cross, 140, 20)
                      placesTaken[1] = True
                      turn -= 1
                  if board[2] == 1 and placesTaken[2] is False:
                      put_image(circle, 260, 20)
                      placesTaken[2] = True
                      turn += 1
                  elif board[2] == 2 and placesTaken[2] is False:
                      put_image(cross, 260, 20)
                      placesTaken[2] = True
                      turn -= 1
                  if board[3] == 1 and placesTaken[3] is False:
                      put_image(circle, 20, 140)
                      placesTaken[3] = True
                      turn += 1
                  elif board[3] == 2 and placesTaken[3] is False:
                      put_image(cross, 20, 140)
                      placesTaken[3] = True
                      turn -= 1
                  if board[4] == 1 and placesTaken[4] is False:
                      put_image(circle, 140, 140)
                      placesTaken[4] = True
                      turn += 1
                  elif board[4] == 2 and placesTaken[4] is False:
                      put_image(cross, 140, 140)
                      placesTaken[4] = True
                      turn -= 1
                  if board[5] == 1 and placesTaken[5] is False:
                      put_image(circle, 260, 140)
                      placesTaken[5] = True
                      turn += 1
                  elif board[5] == 2 and placesTaken[5] is False:
                      put_image(cross, 260, 140)
                      placesTaken[5] = True
                      turn -= 1
                  if board[6] == 1 and placesTaken[6] is False:
                      put_image(circle, 20, 260)
                      placesTaken[6] = True
                      turn += 1
                  elif board[6] == 2 and placesTaken[6] is False:
                      put_image(cross, 20, 260)
                      placesTaken[6] = True
                      turn -= 1
                  if board[7] == 1 and placesTaken[7] is False:
                      put_image(circle, 140, 260)
                      placesTaken[7] = True
                      turn += 1
                  elif board[7] == 2 and placesTaken[7] is False:
                      put_image(cross, 140, 260)
                      placesTaken[7] = True
                      turn -= 1
                  if board[8] == 1 and placesTaken[8] is False:
                      put_image(circle, 260, 260)
                      placesTaken[8] = True
                      turn += 1
                  elif board[8] == 2 and placesTaken[8] is False:
                      put_image(cross, 260, 260)
                      placesTaken[8] = True
                      turn -= 1
      
      
              FPSCLOCK.tick(60)
              pygame.display.update()
      
      
      def get_mouse_overbox(mouse_x, mouse_y, box_list, which_turn, boardlist):
          if which_turn == 1:
              for counter in range(len(box_list)):
                  if box_list[counter].collidepoint(mouse_x, mouse_y) and which_turn == 1:
                      boardlist[counter] = 1
          elif which_turn == 2:
              for caunter in range(len(box_list)):
                  if box_list[caunter].collidepoint(mouse_x, mouse_y) and which_turn == 2:
                      boardlist[caunter] = 2
      
      
      def put_image(image_name, x_cord, y_cord):
          global displaySurface
          displaySurface.blit(image_name, (x_cord, y_cord))
      
      
      def generate_boxes(value):
          boxesFilled = []
          for i in range(9):
              boxesFilled.append(value)
          return boxesFilled
      
      
      def board_getcircles(board):
          onlyCircleBoard = [0 if i == 2 else i for i in board]
          return onlyCircleBoard
      
      
      def board_getcrosses(board):
          onlyCrossBoard = [0 if i == 2 else i for i in board]
          return onlyCrossBoard
      
      
      
      
      game_loop()
      

      作为对我所做工作的简短总结,我将大量 if 语句移到 for 循环中的事件中,并使其在图片实际放在桌子上而不是这样做时增加或减少 1当玩家点击时。我做的另一件事是我添加了一个 moveDone 变量,它跟踪更改板子状态的函数 (get_mouse_overbox) 是否已经在当前循环中启动。希望这对某人有所帮助,再次感谢您的帮助,shuttle87

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-11-13
        • 2011-06-16
        • 2015-08-30
        • 1970-01-01
        • 2021-12-11
        • 2019-12-18
        相关资源
        最近更新 更多