python - 如何在按下某个键时显示图片?

标签 python pygame

我正在尝试用 Python 制作 Tic-Tac-Toe,但遇到了问题。我不知道如何让玩家在棋盘上做出选择。我一直试图在棋盘左上角的方 block 中得到一个“X”。 “X”和“O”都是图像,而不是文本。背景也是图像。每次我运行我的代码时,窗口都会打开,板和标题都是它们的,但是当我按“1”键时,什么也没有发生。有谁知道该怎么办?我不确定我的代码的哪些部分是错误的,所以这里是全部:

import pygame
import os
import sys
from pygame.locals import *
pygame.init()

WIDTH, HEIGHT = 500, 500
P_WIDTH, P_HEIGHT = 100, 130
WIN = pygame.display.set_mode((WIDTH, HEIGHT))

main_font = pygame.font.SysFont("Comic sans", 40)
#color = (255, 255, 255)
#light_color = (170, 170, 170)
#dark_color = (100, 100, 100)


def redraw_window():
    BG = pygame.transform.scale(pygame.image.load(os.path.join("Board.jpg")).convert_alpha(), (WIDTH, HEIGHT))

    title_label1 = main_font.render("Tic", True, (0, 0, 0))
    title_label2 = main_font.render("Tac", True, (0, 0, 0))
    title_label3 = main_font.render("Toe", True, (0, 0, 0))

    Player_1 = pygame.transform.scale(pygame.image.load(os.path.join("X.jpg")).convert_alpha(), (P_WIDTH, P_HEIGHT))

    WIN.blit(BG, (0, 0))
    WIN.blit(title_label1, (10, 10))
    WIN.blit(title_label2, (10, 40))
    WIN.blit(title_label3, (10, 70))

    pygame.display.update()

def main():

    while True:
        redraw_window()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit(0)
            elif event.type == pygame.locals.KEYDOWN:
                if event.key == K_1:
                    WIN.blit(Player_1, (72, 35))


main()

另外,如果有人发现有什么可以改进的地方,你能指出来吗?

最佳答案

因此您收到了错误,最好在问题中包含此详细信息。

pygame 2.0.1 (SDL 2.0.14, Python 3.6.9)
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
  File "./bad_noughts.py", line 47, in <module>
    main()
  File "./bad_noughts.py", line 44, in main
    WIN.blit(Player_1, (72, 35))
NameError: name 'Player_1' is not defined

main() 函数中,Python 不知道 Player_1,因为它对于函数 redraw_window() 来说是“本地”的 -这意味着只有redraw_window()函数知道Player_1

那么如何解决这个问题呢?

最快、最简单的方法是将 Player_1 的定义移至主程序,赋予其“全局”作用域。

这修复了错误,但“X”仍然没有出现...为什么?下一个问题是,您仅在收到 1 事件时才绘制“X”。然后(几乎立即)再次重新绘制背景,将其覆盖。它只在屏幕上出现一瞬间。

解决此问题的一种方法是将板的状态与板的绘图分开。

让我们引入一个新的列表列表 board_state,它有 3 行,每行 3 个单元格,每个区域对应一个十字棋盘:

board_state = [ [ None, None, None ], 
                [ None, None, None ],
                [ None, None, None ] ]

使用它,我们可以设置并检查棋盘上棋子的布局,方法如下:board[0][0](左上角)和board[2 ][2](右下)。您刚刚意识到的一件重要的事情是列表是“零索引”的,这意味着第一个元素位于数字 0(而不是 1)

现在当玩家移动时,我们可以设置棋盘状态:

        elif event.type == pygame.locals.KEYDOWN:
            if event.key == K_1:
                board_state[0][0] = 'x'  # top-left

现在我们需要调整窗口绘制函数来查看棋盘状态,并绘制所需的内容:

def redraw_window():
    global board_state

    WIN.blit(BG, (0, 0))
    WIN.blit(title_label1, (10, 10))
    WIN.blit(title_label2, (10, 40))
    WIN.blit(title_label3, (10, 70))

    x_cursor = 0  # position on the board
    y_cursor = 0
    for row in ( 0, 1, 2 ):
        x_cursor = 0
        for col in ( 0, 1, 2 ):
            # if there's a move on the board, draw it
            if ( board_state[row][col] == 'x' ):
                WIN.blit( Player_1, ( x_cursor, y_cursor ) )
            elif ( board_state[row][col] == 'o' ):
                WIN.blit( Player_2, ( x_cursor, y_cursor ) )
            x_cursor += WIDTH//3                             # move the cursor across
        y_cursor += HEIGHT//3                                # move the cursor down

    pygame.display.update()

因此,循环会遍历 board_state 的行和列。在循环中使用 (0, 1, 2) 并不是最佳实践,但我试图保持简单。当循环穿过棋盘、穿过然后向下移动时,我们还维护一个应该绘制任何玩家移动的光标位置。

如果棋盘包含“x”或“o”,则绘制正确的位图。除了这段代码有点粗糙,所以坐标可能会有点偏差,但我没有你的位图,所以这是我们能做的最好的事情。

引用代码:

import pygame
import os
import sys
from pygame.locals import *
pygame.init()

WIDTH, HEIGHT = 500, 500
P_WIDTH, P_HEIGHT = 100, 130
WIN = pygame.display.set_mode((WIDTH, HEIGHT))

main_font = pygame.font.SysFont("Comic sans", 40)
#color = (255, 255, 255)
#light_color = (170, 170, 170)
#dark_color = (100, 100, 100)

BG = pygame.transform.scale(pygame.image.load(os.path.join("ox_board.png")).convert_alpha(), (WIDTH, HEIGHT))
Player_1 = pygame.transform.scale(pygame.image.load(os.path.join("ox_x.png")).convert_alpha(), (P_WIDTH, P_HEIGHT))
Player_2 = pygame.transform.scale(pygame.image.load(os.path.join("ox_o.png")).convert_alpha(), (P_WIDTH, P_HEIGHT))
title_label1 = main_font.render("Tic", True, (0, 0, 0))
title_label2 = main_font.render("Tac", True, (0, 0, 0))
title_label3 = main_font.render("Toe", True, (0, 0, 0))

# moves (or not) placed on the board
# None -> no move yet
# Or 'x', 'o'
board_state = [ [ None, None, None ],
            [ None, None, None ],
            [ None, None, None ] ]


def redraw_window():
    global board_state

    WIN.blit(BG, (0, 0))
    WIN.blit(title_label1, (10, 10))
    WIN.blit(title_label2, (10, 40))
    WIN.blit(title_label3, (10, 70))

    x_cursor = 0  # position on the board
    y_cursor = 0
    for row in ( 0, 1, 2 ):
    x_cursor = 0
    for col in ( 0, 1, 2 ):
        # if there's a move on the board, draw it
        if ( board_state[row][col] == 'x' ):
            WIN.blit( Player_1, ( x_cursor, y_cursor ) )
        elif ( board_state[row][col] == 'o' ):
            WIN.blit( Player_2, ( x_cursor, y_cursor ) )
        x_cursor += WIDTH//3                             # move the cursor across
    y_cursor += HEIGHT//3                                # move the cursor down

    pygame.display.update()


def main():

    while True:
    redraw_window()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit(0)
        elif event.type == pygame.locals.KEYDOWN:
            if event.key == K_1:
                board_state[0][0] = 'x'


main()

board_state 还允许您检查单元格中是否已进行移动。假设玩家按下 5(中心单元格),您只需检查 board_state[1][1] != None 来测试是否已在该单元格中放置了一个 Action 。

关于python - 如何在按下某个键时显示图片?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66234827/

相关文章:

python - Pygame 朝某个方向移动图像

python - 如何在 pygame 中使正方形和圆形之间发生碰撞来触发游戏结束?

python - 替换表面而不是位 block 传送到它

Pygame Midi libasound_module_conf_pulse.so 错误 + 无法打开从站

python - Pandas 意味着函数返回 NaN

python - 使用 python 根据 pandas 中的时间获取不同的值

javascript - heroku 不在 https 上加载 jquery

python - 缺少位置参数

python - 线程 django-main-thread 中的异常

python - 为什么我的散斑(Lee 滤镜)会增加噪音而不是减少噪音?