暂停后使用pygame时游戏冻结



我正在创建一个具有重置功能的国际象棋引擎。我还有一个功能,屏幕不允许用户在将死或相持后做出任何动作。

然而,如果我在这之后执行重置功能,我的游戏就会冻结。

我的代码中有两个文件,我的引擎和主文件。我很确定这与我的主文件有关,但我已经放入了引擎以备不时之需。

它们在这里:

Main(ChessMate.py(:

import pygame as p
import ChessEngine
WIDTH = HEIGHT = 512
DIMENSION = 8
SQ_SIZE = HEIGHT//DIMENSION
MAX_FPS = 15
IMAGES = {}

def loadImages():
pieces = ['wp', 'wR', 'wN', 'wB', 'wK',
'wQ', 'bp', 'bR', 'bN', 'bB', 'bK', 'bQ']
for piece in pieces:
IMAGES[piece] = p.transform.scale(
p.image.load('Chess/Images/' + piece + '.png'), (SQ_SIZE, SQ_SIZE))

def main():
p.init()
screen = p.display.set_mode((WIDTH, HEIGHT))
clock = p.time.Clock()
screen.fill(p.Color("white"))
gs = ChessEngine.GameState()
validMoves = gs.getValidMoves()
moveMade = False
animate = False
loadImages()
running = True
sqSelected = ()
playerClicks = []
gameOver = False
while running:
for e in p.event.get():
if e.type == p.QUIT:
running = False
elif e.type == p.MOUSEBUTTONDOWN:
if not gameOver:
location = p.mouse.get_pos()
col = location[0]//SQ_SIZE
row = location[1]//SQ_SIZE
if sqSelected == (row, col):
sqSelected = ()
playerClicks = []
else:
sqSelected = (row, col)
playerClicks.append(sqSelected)
if len(playerClicks) == 2:
move = ChessEngine.Move(
playerClicks[0], playerClicks[1], gs.board)
print(move.getChessNotation())
for i in range(len(validMoves)):
if move == validMoves[i]:
gs.makeMove(validMoves[i])
moveMade = True
animate = True
sqSelected = ()
playerClicks = []
if not moveMade:
playerClicks = [sqSelected]
elif e.type == p.KEYDOWN:
if e.key == p.K_z:
gs.undoMove()
moveMade = True
animate = False
if e.key == p.K_r:
gs = ChessEngine.GameState()
validMoves = gs.getValidMoves()
sqSelected = ()
playerClicks = []
moveMade = False
animate = False
checkMate = False
staleMate = False
if moveMade:
if animate:
animateMove(gs.moveLog[-1], screen, gs.board, clock)
validMoves = gs.getValidMoves()
moveMade = False
animate = False
drawGameState(screen, gs, validMoves, sqSelected)
if gs.checkMate:
gameOver = True
if gs.whitetoMove:
drawText(screen, ' Black wins by Checkmate')
else:
drawText(screen, ' White wins by Checkmate')
elif gs.staleMate:
gameOver = True
drawText(screen, 'Stalemate')
clock.tick(MAX_FPS)
p.display.flip()

def highlightSquares(screen, gs, validMoves, sqSelected):
if sqSelected != ():
r, c = sqSelected
if gs.board[r][c][0] == ('w' if gs.whitetoMove else 'b'):
s = p.Surface((SQ_SIZE, SQ_SIZE))
s.set_alpha(100)
s.fill(p.Color('blue'))
screen.blit(s, (c*SQ_SIZE, r*SQ_SIZE))
s.fill(p.Color('yellow'))
for move in validMoves:
if move.startRow == r and move.startCol == c:
screen.blit(s, (SQ_SIZE*move.endCol, SQ_SIZE*move.endRow))

def drawGameState(screen, gs, validMoves, sqSelected):
drawBoard(screen)
highlightSquares(screen, gs, validMoves, sqSelected)
drawPieces(screen, gs.board)

def drawBoard(screen):
global colors
colors = [p.Color("white"), p.Color("gray")]
for r in range(DIMENSION):
for c in range(DIMENSION):
color = colors[((r+c) % 2)]
p.draw.rect(screen, color, p.Rect(
c*SQ_SIZE, r*SQ_SIZE, SQ_SIZE, SQ_SIZE))

def drawPieces(screen, board):
for r in range(DIMENSION):
for c in range(DIMENSION):
piece = board[r][c]
if piece != "--":
screen.blit(IMAGES[piece], p.Rect(
c*SQ_SIZE, r*SQ_SIZE, SQ_SIZE, SQ_SIZE))

def animateMove(move, screen, board, clock):
global colors
dR = move.endRow - move.startRow
dC = move.endCol - move.startCol
framesPerSquare = 10
frameCount = (abs(dR) + abs(dC)) * framesPerSquare
for frame in range(frameCount + 1):
p.event.pump()
r, c = (move.startRow + dR * frame / frameCount,
move.startCol + dC*frame / frameCount)
drawBoard(screen)
drawPieces(screen, board)
color = colors[(move.endRow + move.endCol) % 2]
endSquare = p.Rect(move.endCol*SQ_SIZE,
move.endRow*SQ_SIZE, SQ_SIZE, SQ_SIZE)
p.draw.rect(screen, color, endSquare)
if move.pieceCaptured != '--':
screen.blit(IMAGES[move.pieceCaptured], endSquare)
screen.blit(IMAGES[move.pieceMoved], p.Rect(
c*SQ_SIZE, r*SQ_SIZE, SQ_SIZE, SQ_SIZE))
p.display.flip()
clock.tick(60)

def drawText(screen, text):
font = p.font.SysFont("Helvetica", 32, True, False)
textObject = font.render(text, 0, p.Color('Gray'))
textLocation = p.Rect(0, 0, WIDTH, HEIGHT).move(
WIDTH/2 - textObject.get_width()/2, HEIGHT/2 - textObject.get_height()/2)
screen.blit(textObject, textLocation)
textObject = font.render(text, 0,  p.Color("Black"))
screen.blit(textObject, textLocation.move(2, 2))

if __name__ == '__main__':
main()

我的引擎(ChessEngine.py(:

class GameState():
def __init__(self):
# 8x8 2d board, each element has 2 characters.
self.board = [
["bR", "bN", "bB", "bQ", "bK", "bB", "bN", "bR"],
["bp", "bp", "bp", "bp", "bp", "bp", "bp", "bp"],
["--", "--", "--", "--", "--", "--", "--", "--"],
["--", "--", "--", "--", "--", "--", "--", "--"],
["--", "--", "--", "--", "--", "--", "--", "--"],
["--", "--", "--", "--", "--", "--", "--", "--"],
["wp", "wp", "wp", "wp", "wp", "wp", "wp", "wp"],
["wR", "wN", "wB", "wQ", "wK", "wB", "wN", "wR"]]
self.moveFunctions = {'p': self.getPawnMoves,
'R': self.getRookMoves, 'N': self.getKnightMoves, 'B': self.getBishopMoves, 'Q': self.getQueenMoves, 'K': self.getKingMoves}
self.whitetoMove = True
self.moveLog = []
self.whiteKingLocation = (7, 4)
self.blackKingLocation = (0, 4)
self.checkMate = False
self.staleMate = False
self.enpassantPossible = ()
self.currentCastlingRight = CastleRights(True, True, True, True)
self.castleRightsLog = [CastleRights(
self.currentCastlingRight.wks, self.currentCastlingRight.wqs, self.currentCastlingRight.bks, self.currentCastlingRight.bqs)]
def makeMove(self, move):
self.board[move.startRow][move.startCol] = "--"
self.board[move.endRow][move.endCol] = move.pieceMoved
self.moveLog.append(move)
self.whitetoMove = not self.whitetoMove
if move.pieceMoved == 'wK':
self.whiteKingLocation = (move.endRow, move.endCol)
elif move.pieceMoved == "bK":
self.blackKingLocation = (move.endRow, move.endCol)
if move.isPawnPromotion:
self.board[move.endRow][move.endCol] = move.pieceMoved[0] + 'Q'
if move.isEnpassantMove:
self.board[move.startRow][move.endCol] = '--'
if move.pieceMoved[1] == 'p' and abs(move.startRow - move.endRow) == 2:
self.enpassantPossible = (
(move.startRow + move.endRow)//2, move.startCol)
else:
self.enpassantPossible = ()
if move.isCastleMove:
if move.endCol - move.startCol == 2:
self.board[move.endRow][move.endCol -
1] = self.board[move.endRow][move.endCol+1]
self.board[move.endRow][move.endCol+1] = '--'
else:
self.board[move.endRow][move.endCol +
1] = self.board[move.endRow][move.endCol-2]
self.board[move.endRow][move.endCol-2] = '--'
self.updateCastleRights(move)
self.castleRightsLog.append(CastleRights(
self.currentCastlingRight.wks, self.currentCastlingRight.wqs, self.currentCastlingRight.bks, self.currentCastlingRight.bqs))
def undoMove(self):
if len(self.moveLog) != 0:
move = self.moveLog.pop()
self.board[move.startRow][move.startCol] = move.pieceMoved
self.board[move.endRow][move.endCol] = move.pieceCaptured
self.whitetoMove = not self.whitetoMove
if move.pieceMoved == 'wK':
self.whiteKingLocation = (move.startRow, move.startCol)
elif move.pieceMoved == "bK":
self.blackKingLocation = (move.startRow, move.startCol)
if move.isEnpassantMove:
self.board[move.endRow][move.endCol] = '--'
self.board[move.startRow][move.endCol] = move.pieceCaptured
self.enpassantPossible = (move.endRow, move.endCol)
if move.pieceMoved[1] == 'p' and abs(move.startRow - move.endRow) == 2:
self.enpassantPossible = ()
self.castleRightsLog.pop()
newRights = self.castleRightsLog[-1]
self.currentCastlingRight = CastleRights(
newRights.wks, newRights.bks, newRights.wqs, newRights.bqs)
if move.isCastleMove:
if move.endCol - move.startCol == 2:
self.board[move.endRow][move.endCol +
1] = self.board[move.endRow][move.endCol-1]
self.board[move.endRow][move.endCol-1] = '--'
else:
self.board[move.endRow][move.endCol -
2] = self.board[move.endRow][move.endCol+1]
self.board[move.endRow][move.endCol+1] = '--'
def updateCastleRights(self, move):
if move.pieceMoved == 'wK':
self.currentCastlingRight.wks = False
self.currentCastlingRight.wqs = False
elif move.pieceMoved == 'bK':
self.currentCastlingRight.bks = False
self.currentCastlingRight.bqs = False
elif move.pieceMoved == 'wR':
if move.startRow == 7:
if move.startCol == 0:
self.currentCastlingRight.wqs = False
elif move.startCol == 7:
self.currentCastlingRight.wks = False
elif move.pieceMoved == 'bR':
if move.startRow == 0:
if move.startCol == 0:
self.currentCastlingRight.bqs = False
elif move.startCol == 7:
self.currentCastlingRight.bks = False
def getValidMoves(self):
tempEnpassantPossible = self.enpassantPossible
tempCastleRights = CastleRights(self.currentCastlingRight.wks, self.currentCastlingRight.bks,
self.currentCastlingRight.wqs, self.currentCastlingRight.bqs)
moves = self.getAllPossibleMoves()
if self.whitetoMove:
self.getCastleMoves(
self.whiteKingLocation[0], self.whiteKingLocation[1], moves)
else:
self.getCastleMoves(
self.blackKingLocation[0], self.blackKingLocation[1], moves)
for i in range(len(moves)-1, -1, -1):
self.makeMove(moves[i])
self.whitetoMove = not self.whitetoMove
if self.inCheck():
moves.remove(moves[i])
self.whitetoMove = not self.whitetoMove
self.undoMove()
if len(moves) == 0:
if self.inCheck():
self.checkMate = True
else:
self.staleMate = True
else:
self.checkMate = False
self.staleMate = False
self.enpassantPossible = tempEnpassantPossible
self.currentCastlingRight = tempCastleRights
return moves
def inCheck(self):
if self.whitetoMove:
return self.squareUnderAttack(self.whiteKingLocation[0], self.whiteKingLocation[1])
else:
return self.squareUnderAttack(self.blackKingLocation[0], self.blackKingLocation[1])
def squareUnderAttack(self, r, c):
self.whitetoMove = not self.whitetoMove
oppMoves = self.getAllPossibleMoves()
self.whitetoMove = not self.whitetoMove
for move in oppMoves:
if move.endRow == r and move.endCol == c:
return True
return False
def getAllPossibleMoves(self):
moves = []
for r in range(len(self.board)):
for c in range(len(self.board[r])):
turn = self.board[r][c][0]
if (turn == 'w' and self.whitetoMove) or (turn == 'b' and not self.whitetoMove):
piece = self.board[r][c][1]
self.moveFunctions[piece](r, c, moves)
return moves
def getPawnMoves(self, r, c, moves):
if self.whitetoMove:
if self.board[r-1][c] == "--":
moves.append(Move((r, c), (r-1, c), self.board))
if r == 6 and self.board[r-2][c] == "--":
moves.append(Move((r, c), (r-2, c), self.board))
if c - 1 >= 0:
if self.board[r-1][c-1][0] == 'b':
moves.append(Move((r, c), (r-1, c-1), self.board))
elif (r - 1, c - 1) == self.enpassantPossible:
moves.append(
Move((r, c), (r-1, c-1), self.board, enpassantPossible=True))
if c + 1 <= 7:
if self.board[r-1][c+1][0] == 'b':
moves.append(Move((r, c), (r-1, c+1), self.board))
elif (r - 1, c + 1) == self.enpassantPossible:
moves.append(
Move((r, c), (r-1, c+1), self.board, enpassantPossible=True))
else:
if self.board[r+1][c] == "--":
moves.append(Move((r, c), (r+1, c), self.board))
if r == 1 and self.board[r+2][c] == '--':
moves.append(Move((r, c), (r+2, c), self.board))
if c-1 >= 0:
if self.board[r+1][c-1][0] == 'w':
moves.append(Move((r, c), (r+1, c-1), self.board))
elif (r + 1, c - 1) == self.enpassantPossible:
moves.append(
Move((r, c), (r+1, c-1), self.board, enpassantPossible=True))
if c+1 <= 7:
if self.board[r+1][c+1][0] == 'w':
moves.append(Move((r, c), (r+1, c+1), self.board))
elif (r + 1, c + 1) == self.enpassantPossible:
moves.append(
Move((r, c), (r+1, c+1), self.board, enpassantPossible=True))
def getRookMoves(self, r, c, moves):
directions = ((-1, 0), (0, -1), (1, 0), (0, 1))
enemyColor = "b" if self.whitetoMove else "w"
for d in directions:
for i in range(1, 8):
endRow = r + d[0] * i
endCol = c + d[1] * i
if 0 <= endRow < 8 and 0 <= endCol < 8:
endPiece = self.board[endRow][endCol]
if endPiece == "--":
moves.append(
Move((r, c), (endRow, endCol), self.board))
elif endPiece[0] == enemyColor:
moves.append(
Move((r, c), (endRow, endCol), self.board))
break
else:
break
else:
break
def getKnightMoves(self, r, c, moves):
knightMoves = ((-2, -1), (-2, 1), (-1, -2), (-1, 2),
(1, -2), (1, 2), (2, -1), (2, 1))
allyColor = "w" if self.whitetoMove else "b"
for m in knightMoves:
endRow = r + m[0]
endCol = c + m[1]
if 0 <= endRow < 8 and 0 <= endCol < 8:
endPiece = self.board[endRow][endCol]
if endPiece[0] != allyColor:
moves.append(Move((r, c), (endRow, endCol), self.board))
def getBishopMoves(self, r, c, moves):
directions = ((-1, -1), (-1, 1), (1, -1), (1, 1))
enemyColor = "b" if self.whitetoMove else "w"
for d in directions:
for i in range(1, 8):
endRow = r + d[0] * i
endCol = c + d[1] * i
if 0 <= endRow < 8 and 0 <= endCol < 8:
endPiece = self.board[endRow][endCol]
if endPiece == "--":
moves.append(
Move((r, c), (endRow, endCol), self.board))
elif endPiece[0] == enemyColor:
moves.append(
Move((r, c), (endRow, endCol), self.board))
break
else:
break
else:
break
def getQueenMoves(self, r, c, moves):
self.getRookMoves(r, c, moves)
self.getBishopMoves(r, c, moves)
def getKingMoves(self, r, c, moves):
kingMoves = ((-1, -1), (-1, 0), (-1, 1),
(0, -1), (0, 1), (1, -1), (1, 0), (1, 1))
allyColor = "w" if self.whitetoMove else "b"
for i in range(8):
endRow = r + kingMoves[i][0]
endCol = c + kingMoves[i][1]
if 0 <= endRow < 8 and 0 <= endCol < 8:
endPiece = self.board[endRow][endCol]
if endPiece[0] != allyColor:
moves.append(Move((r, c), (endRow, endCol), self.board))
def getCastleMoves(self, r, c, moves):
if self.squareUnderAttack(r, c):
return
if (self.whitetoMove and self.currentCastlingRight.wks) or (not self.whitetoMove and self.currentCastlingRight.bks):
self.getKingsideCastleMoves(r, c, moves)
if (self.whitetoMove and self.currentCastlingRight.wqs) or (not self.whitetoMove and self.currentCastlingRight.bqs):
self.getQueensideCastleMoves(r, c, moves)
def getKingsideCastleMoves(self, r, c, moves):
if self.board[r][c+1] == '--' and self.board[r][c+2] == '--':
if not self.squareUnderAttack(r, c+1) and not self.squareUnderAttack(r, c+2):
moves.append(
Move((r, c), (r, c+2), self.board, isCastleMove=True))
def getQueensideCastleMoves(self, r, c, moves):
if self.board[r][c-1] == '--' and self.board[r][c-2] == '--' and self.board[r][c-3] == '--':
if not self.squareUnderAttack(r, c-1) and not self.squareUnderAttack(r, c-2):
moves.append(
Move((r, c), (r, c-2), self.board, isCastleMove=True))

class CastleRights():
def __init__(self, wks, bks, wqs, bqs):
self.wks = wks
self.bks = bks
self.wqs = wqs
self.bqs = bqs

class Move():
ranksToRows = {"1": 7, "2": 6, "3": 5,
"4": 4, "5": 3, "6": 2, "7": 1, "8": 0}
rowsToRanks = {v: k for k, v in ranksToRows.items()}
filesToCols = {"a": 0, "b": 1, "c": 2,
"d": 3, "e": 4, "f": 5, "g": 6, "h": 7}
colsToFiles = {v: k for k, v in filesToCols.items()}
def __init__(self, startSq, endSq, board, enpassantPossible=False, isCastleMove=False):
self.startRow = startSq[0]
self.startCol = startSq[1]
self.endRow = endSq[0]
self.endCol = endSq[1]
self.pieceMoved = board[self.startRow][self.startCol]
self.pieceCaptured = board[self.endRow][self.endCol]
self.isPawnPromotion = (self.pieceMoved == 'wp' and self.endRow == 0) or (
self.pieceMoved == 'bp' and self.endRow == 7)
self.isEnpassantMove = enpassantPossible
if self.isEnpassantMove:
self.pieceCaptured = 'wp' if self.pieceMoved == 'bp' else 'bp'
self.isCastleMove = isCastleMove
self.moveID = self.startRow * 1000 + 
self.startCol*100 + self.endRow*10 + self.endCol
def __eq__(self, other):
if isinstance(other, Move):
return self.moveID == other.moveID
return False
def getChessNotation(self):
return self.getRankFile(self.startRow, self.startCol) + self.getRankFile(self.endRow, self.endCol)
def getRankFile(self, r, c):
return self.colsToFiles[c] + self.rowsToRanks[r]

请帮忙,如果有人能确定问题可能在哪里,对我来说就足够了,因为我真的很困。谢谢

一旦gameOver设置为True,就没有代码路径可以使其再次成为False

可能您只需要将其添加到r重置处理程序:

elif e.type == p.KEYDOWN:
if e.key == p.K_z:
gs.undoMove()
moveMade = True
animate = False
if e.key == p.K_r:
gs = ChessEngine.GameState()
validMoves = gs.getValidMoves()
sqSelected = ()
playerClicks = []
moveMade = False
animate = False
checkMate = False
staleMate = False
gameOver  = False    ### <<-- HERE

最新更新