我正在尝试用 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/