我正在使用 pygame 制作一款国际象棋游戏,大多数问题和错误都有望得到解决,但只有一个让我烦恼。在国际象棋中,国王不能移动到其他国王的相邻方格。我有一个名为 in_check 的函数,如果使用提供的移动,国王将受到检查,它基本上返回 False,我实际上希望它也能像国王的移动一样工作,但它只适用于任何其他棋子。所以我升级了它并添加了更多代码,如下所示:
def in_check(self, piece: Piece, move: Move):
virtual_piece, virtual_board = deepcopy(piece), deepcopy(self) # saves a copy of the board and piece
virtual_board.move(virtual_piece, move, True) # moves the copied piece on the copied board so it won't actually move the real one, because we wanna check if the king will be in check, and then deny the move
for row in range(ROWS): # going through each row
for col in range(COLS): # going through each column
l = virtual_board.squares[row][col] # saving the square in a variable
p = l.piece # saving the piece in that square in another variable
if l.has_enemy_piece(piece.color): # if that square contains enemy piece
virtual_board.calculate_moves(p, row, col, False) # we recalculate the moves for the enemy piece to update the moves(we always update the moves everytime a piece has moved)
# -----------------------------
if isinstance(piece, King) and isinstance(p, King): # if both pieces were kings
for m in p.moves: # going through each move for each piece
for M in virtual_piece.moves: # going through each move for each piece(here i go through the virtual_piece moves since it was recently updated)
if m.final == M.final: piece.moves.remove(M) # if both end up on the same square, we remove the move from the ACTUAL piece so it won't be able to move there
# ----------------------------- These are the lines i've added to fix the bug
for m in p.moves: # going through the moves for the enemy piece(in this part we return True if the piece's move will let enemy to capture the king)
if isinstance(m.final.piece, King): # if the final square of the piece is a king
if not INSTANT_CHECKMATE: return True # this INSTANT_CHECKMATE is just a game mode that'll let players to actually capture the kings and end the game right there
return False # we reach here only if INSTANT_CHECKMATE is enabled which means we return False so the move will be valid
return False # after all the checks if we found out that the move isn't gonna put the friendly king in a check, return False so we'll accept the move as valid
添加这些行后,乍一看我认为它修复了错误: 图片1 图片2 图片3 但经过其他一些动作后,我看到了这些(我也跨越了应该无效的动作):问题1问题2问题3 如最后三个屏幕截图所示,始终有 1 个方格是无效的移动。我尝试了很多不同的选项(说实话,我已经连续三天这样做了)将相同的代码添加到程序的不同部分,而不是删除用于仅返回 False 但不起作用的移动,只有这么多选项和没用。这段代码只是我想出的最好的代码。
终于做到了。问题一直在我眼前,我一直以错误的方式看待它。因为如果函数
in_check
获取每一步并对其进行分析,那么为什么我要从国王中删除每一步呢?关键是,我们必须检查敌人和棋子是否都是国王,如果棋子的移动在另一个国王的移动中,则忽略添加移动,并且我们必须检查另一个是否实际上是对手国王,因为该棋子(另一个国王)仍然可以移动到敌方拥有的格子中,例如在敌方棋子前面。
def in_check(self, piece: Piece, move: Move):
virtual_piece, virtual_board = deepcopy(piece), deepcopy(self)
virtual_board.move(virtual_piece, move, True)
for row in range(ROWS):
for col in range(COLS):
l = virtual_board.squares[row][col]
p = l.piece
if l.has_enemy_piece(piece.color):
virtual_board.calculate_moves(p, row, col, False)
# -------------------------
if isinstance(piece, King) and isinstance(p, King):
for m in p.moves:
if m.final == move.final: return True
# -------------------------------------------
for m in p.moves:
if isinstance(m.final.piece, King):
if not INSTANT_CHECKMATE: return True
return False
return False
如你所见,我只需要检查另一位国王是否与另一位国王共享一个图块(方块),如果是这样,我们返回
True
,最终忽略该移动。