管理 Python Turtle 何时检查事件



我正在开发一个使用 Python turtle 图形的 Connect 4 游戏。出现的主要问题是,当您使用诸如onkeyonclick之类的事件时,会立即检查它们,然后是代码的其余部分。有没有办法暂停代码直到事件发生,然后继续,循环后等待另一个事件发生?

在下面的代码中,设置游戏,然后运行play()函数。在play()函数中,程序侦听onkey()事件,这些事件允许用户更改它所在的列并在准备就绪时删除该列。然后,它开始水平、垂直或对角线连续检查 4。它会产生错误,因为列列表为空,直到我按向下键将棋子放入板的列中并将该棋子附加到该列。我可以创建已经填充了None''或零的列,但随后我必须更改我的 drop 函数的工作方式,因为它目前将删除位置的 y 值设置为列表中的项目数。有没有办法在每块掉落后只运行一次检查功能?

附言我对编码比较陌生,这是我第一次使用这个网站。我已经复制并粘贴了下面的代码:

import turtle
class Connect4:
"A connect 4 game"
def __init__(self):
self.pen = turtle.Turtle()
self.scr = turtle.Screen()
self.board = Connect4Board(self.pen, self.scr)
self.moves = 0
self.playing = True
self.piece = Connect4Piece(self.scr, self.board, self)
self.setup()
self.play()
def setup(self):
self.board.draw_board()
def play(self):
if self.moves == self.board.rows*self.board.columns:
game_over()
self.piece.st()
self.piece.goto(0, self.board.board_height/2)
while True:
self.scr.onkey(self.piece.prev_col, 'Left')
self.scr.onkey(self.piece.next_col, 'Right')
self.scr.onkey(self.piece.drop, 'Down')
self.scr.onkey(self.reset, 'r')
self.scr.listen()
self.check()
"Check if there is 4 pieces in a line horizontally, vertically or diagonally"
def check(self):
self.check_horizontal()
self.check_vertical()
self.check_diagonal()
def check_horizontal(self):
print("Checking horizontally")
for rows in range(self.board.rows):
for columns in range(self.board.columns - 3):
if self.board.squares[columns][rows] == 0:
continue
elif (self.board.squares[columns][rows] == self.board.squares[columns+1][rows] == self.board.squares[columns+2][rows] == self.board.squares[columns+3][rows]):
print(self.board.squares[columns][rows].color())
if self.board.squares[columns][rows].color() == ('red','red'):
print("Red wins!")
if self.board.squares[columns][rows].color() == ('black','black'):
print("Black wins!")
def check_vertical(self):
print("Checking vertically")
def check_diagonal(self):
print("Checking diagonally")
def reset(self):
self.board.reset()
self.piece.clear()
self.moves = 0
self.play()
def game_over(self):
self.pen.pu()
self.pen.goto(0, board_height/2 + 20)
self.pen.pd()
self.pen.write("Black wins!", align='center', font = ('Arial', 24, 'normal'))
self.pen.pu()
to.goto(0, board_height/2 + 10)
self.pen.write("Play Again?", align='center', font = ('Arial', 24, 'normal'))
self.playing = False
class Connect4Board:
def __init__(self, pen, screen):
#Used to create the board
self.square_size = 60
self.rows = 6
self.columns = 7
self.pen = pen
self.frame_color = 'blue'
self.board_length = self.square_size*self.columns
self.board_height = self.square_size*self.rows
self.squares = [[] for cols in range(self.columns)] 
"""for cols in range(self.columns):
empty = []
self.squares.append(empty)"""
self.pen.speed(0)
self.pen.ht()
def _draw_square(self, x, y):
self.pen.pu()
self.pen.goto(x-self.square_size/2, y-self.square_size/2)
self.pen.pd()
self.pen.fillcolor(self.frame_color)
self.pen.begin_fill()
for sides in range(4):
self.pen.fd(self.square_size)
self.pen.left(90)
self.pen.end_fill()
def _draw_circle(self, x, y):
self.pen.pu()
self.pen.goto(x, y)
self.pen.pd()
self.pen.fillcolor('white')
self.pen.begin_fill()
self.pen.circle(self.square_size/2)
self.pen.end_fill()
def draw_board(self):
for row in range(self.rows):
for col in range(self.columns):
x = col*self.square_size - self.board_length/2 + self.square_size/2
y = row*self.square_size - self.board_length/2
self._draw_square(x, y)
self._draw_circle(x, y - self.square_size/2)
def reset(self):
self.squares = []
for cols in range(self.columns):
empty = []
self.squares.append(empty)
class Connect4Piece(turtle.Turtle):
def __init__(self, screen, board, game):
turtle.Turtle.__init__(self, screen)
self.board = board
self.speed(0)
self.pu()
self.shape('turtle')
self.cnum = 3
self.game = game
self.ht()
"Moves the piece to the left and updates it's column number"
def prev_col(self):
if self.xcor() - self.board.square_size > -self.board.board_length/2:
self.setx(self.xcor() - self.board.square_size)
self.cnum -= 1
"Moves the piece to the right and updates it's column number"
def next_col(self):
if self.xcor() + self.board.square_size < self.board.board_length/2:
self.setx(self.xcor() + self.board.square_size)
self.cnum += 1
def drop(self):
"Make sure the column isn't full. If it's not then move the turtle to the next available space in the row."
if len(self.board.squares[self.cnum]) != self.board.rows:
self.sety(len(self.board.squares[self.cnum])              *self.board.square_size - self.board.board_height/2 - self.board.square_size/2 )
"Stamp an image of the turtle to represent placing a piece"
self.stamp()
self.board.squares[self.cnum].append(self.color())
"Move the piece back above the middle column and set it's column back to 3"
self.goto(0, self.board.board_height/2)
self.cnum = 3
"Change the piece's color"
if self.color() == ('red','red'):
self.color('black')
else:
self.color('red')
self.game.moves += 1
print(self.game.moves, "moves")
game = Connect4()

您的程序结构不正确,如以下循环所示:

while True:
self.scr.onkey(self.piece.prev_col, 'Left')
self.scr.onkey(self.piece.next_col, 'Right')
self.scr.onkey(self.piece.drop, 'Down')
self.scr.onkey(self.reset, 'r')
self.scr.listen()
self.check()

首先,while True:在像这样的事件驱动环境中没有立足之地。 其次,这些onkey调用只需要在初始化期间执行一次- 它们在运行时不执行任何操作。 (同上listen()(

我已经将下面的代码重组为基于事件。 您需要添加(返回(检查代码以确定是否有赢家:

from turtle import Turtle, Screen
class Connect4:
"A connect 4 game"
def __init__(self, screen):
self.pen = Turtle()
self.scr = screen
self.board = Connect4Board(self.pen)
self.moves = 0
self.playing = False
self.piece = Connect4Piece(self.board, self)
self.scr.tracer(False)
self.board.draw_board()
self.scr.tracer(True)
self.scr.onkey(self.piece.prev_col, 'Left')
self.scr.onkey(self.piece.next_col, 'Right')
self.scr.onkey(self.piece.drop, 'Down')
self.scr.onkey(self.reset, 'r')
self.scr.listen()
def play(self):
self.piece.showturtle()
self.piece.goto(0, self.board.board_height/2)
self.playing = True
def check(self):
"Check if there are 4 pieces in a line horizontally, vertically or diagonally"
if self.moves == self.board.rows * self.board.columns:
self.game_over()
if self.check_horizontal():
self.game_over()
if self.check_vertical():
self.game_over()
if self.check_diagonal():
self.game_over()
def check_horizontal(self):
print("Checking horizontally")
# implement this correctly
return False
def check_vertical(self):
print("Checking vertically")
# implement this
return False
def check_diagonal(self):
print("Checking diagonally")
# implement this
return False
def reset(self):
self.playing = False
self.board.reset()
self.piece.clear()
self.moves = 0
self.play()
def game_over(self):
self.playing = False
self.pen.penup()
self.pen.goto(0, self.board.board_height/2 + 20)
self.pen.pendown()
self.pen.write("Black wins!", align='center', font=('Arial', 24, 'normal'))
self.pen.penup()
self.pen.goto(0, self.board.board_height/2 + 10)
self.pen.write("Play Again?", align='center', font=('Arial', 24, 'normal'))
class Connect4Board:
def __init__(self, pen):
# Used to create the board
self.square_size = 60
self.rows = 6
self.columns = 7
self.pen = pen
self.frame_color = 'blue'
self.board_length = self.square_size * self.columns
self.board_height = self.square_size * self.rows
self.squares = [[] for _ in range(self.columns)]
self.pen.speed('fastest')
self.pen.hideturtle()
def _draw_square(self, x, y):
self.pen.penup()
self.pen.goto(x - self.square_size/2, y - self.square_size/2)
self.pen.pendown()
self.pen.fillcolor(self.frame_color)
self.pen.begin_fill()
for _ in range(4):
self.pen.forward(self.square_size)
self.pen.left(90)
self.pen.end_fill()
def _draw_circle(self, x, y):
self.pen.penup()
self.pen.goto(x, y)
self.pen.pendown()
self.pen.fillcolor('white')
self.pen.begin_fill()
self.pen.circle(self.square_size/2)
self.pen.end_fill()
def draw_board(self):
for row in range(self.rows):
for col in range(self.columns):
x = col * self.square_size - self.board_length/2 + self.square_size/2
y = row * self.square_size - self.board_length/2
self._draw_square(x, y)
self._draw_circle(x, y - self.square_size/2)
def reset(self):
self.squares = [[] for _ in range(self.columns)]
class Connect4Piece(Turtle):
def __init__(self, board, game):
super().__init__(shape='turtle', visible=False)
self.board = board
self.game = game
self.speed('fastest')
self.penup()
self.cnum = 3
def prev_col(self):
"Moves the piece to the left and updates it's column number"
if self.xcor() - self.board.square_size > -self.board.board_length/2:
self.setx(self.xcor() - self.board.square_size)
self.cnum -= 1
def next_col(self):
"Moves the piece to the right and updates it's column number"
if self.xcor() + self.board.square_size < self.board.board_length/2:
self.setx(self.xcor() + self.board.square_size)
self.cnum += 1
def drop(self):
"Make sure the column isn't full. If it's not then move the turtle to the next available space in the row."
if len(self.board.squares[self.cnum]) != self.board.rows:
self.sety(len(self.board.squares[self.cnum]) * self.board.square_size - self.board.board_height/2 - self.board.square_size/2)
# Stamp an image of the turtle to represent placing a piece
self.stamp()
self.board.squares[self.cnum].append(self.color())
# Move the piece back above the middle column and set it's column back to 3
self.goto(0, self.board.board_height/2)
self.cnum = 3
# Change the piece's color
self.color('black' if self.pencolor() == 'red' else 'red')
self.game.moves += 1
print(self.game.moves, "moves")
self.game.check()
screen = Screen()
game = Connect4(screen)
game.play()
screen.mainloop()

图形的行为符合预期,但是当您放下时,您会看到存根检查函数被调用并且玩家切换。

另外,请阅读 Python 注释与文档字符串 - 您正在将它们混合在一起。

最新更新