Pygame 中的 Check 和 Checkmate

问题描述 投票:0回答:0

我正在尝试检测检查和将死,并通过拿走检查的棋子,移动到检查的棋子前面或将国王从检查中移开来阻止检查。

当我在黑色棋子上尝试时,Check 和 Checkmate 也不起作用。

这个photo是一个程序没有检测到将死的例子。程序说它是 check 但不是 checkmate

照片中的董事会状态:

chessboard = [
["  ", "BN", "BB", "  ", "BK", "  ", "BN", "  "],
["  ", "BP", "BP", "BP", "  ", "BP", "  ", "  "],
["  ", "  ", "  ", "  ", "BP", "  ", "  ", "BP"],
["BP", "  ", "  ", "  ", "  ", "  ", "BP", "  "],
["  ", "BB", "  ", "  ", "  ", "  ", "  ", "  "],
["  ", "  ", "  ", "  ", "  ", "  ", "  ", "  "],
["WP", "WP", "WP", "BQ", "  ", "BR", "  ", "WP"],
["WR", "  ", "  ", "  ", "WK", "BR", "  ", "  "]]

检查和将死的功能:

def is_king_in_check(chessboard, king_color):
    """
    Given a chessboard and the color of the king (either 'W' for white or 'B' for black),
    returns True if the king is in check, False otherwise.
    """
    # Find the king's location on the board
    for row in range(8):
        for col in range(8):
            piece = chessboard[row][col]
            if piece == king_color + 'K':
                king_location = (row, col)
                break

    # Check if any of the opponent's pieces can attack the king
    opponent_color = 'B' if king_color == 'W' else 'W'
    for row in range(8):
        for col in range(8):
            piece = chessboard[row][col]
            if piece[0] == opponent_color:
                if is_legal_pawn_move(row, col, king_location[0], king_location[1], chessboard):
                    # King is in check
                    return True
    # King is not in check
    return False

def is_checkmate(chessboard, king_color):
    """
    Given a chessboard and the color of the king (either 'W' for white or 'B' for black),
    returns True if the king is in checkmate, False otherwise.
    """
    # Find the king's location on the board
    for row in range(8):
        for col in range(8):
            piece = chessboard[row][col]
            if piece == king_color + 'K':
                king_location = (row, col)
                break

    # Check if the king can move to a safe square
    for i in range(king_location[0] - 1, king_location[0] + 2):
        for j in range(king_location[1] - 1, king_location[1] + 2):
            if (i, j) == king_location or i < 0 or i > 7 or j < 0 or j > 7:
                continue
            if is_legal_pawn_move(king_location[0], king_location[1], i, j, chessboard):
                # King can move to safety
                return False

    # Check if any of the king's pieces can capture the checking piece
    opponent_color = 'B' if king_color == 'W' else 'W'
    for row in range(8):
        for col in range(8):
            piece = chessboard[row][col]
            if piece[0] == king_color:
                if is_legal_pawn_move(row, col, king_location[0], king_location[1], chessboard):
                    # Another piece can capture the checking piece or block the check
                    return False

    # King is in 
    print('mate')
    return True

完整节目:

import pygame
import os
import sys
import pygame_gui

# Define some colors
BLACK = ('#B58863')
WHITE = ('#F0D9B5')

# Set the dimensions of the chessboard squares
WIDTH = 80
HEIGHT = 80

WK_moved = False
BK_moved = False
BR_moved = False 
WR_moved = False
BR_moved_1 = False 
WR_moved_1 = False

Move_History = []
check = 0

pygame.mixer.init()
move_sound = pygame.mixer.Sound("move.mp3")

# Initialize pygame
pygame.init()

# Set the size of the window and create it
size = (WIDTH * 8, HEIGHT * 8)
screen = pygame.display.set_mode(size)

# Draw the chessboard
# Define the initial state of the chessboard
chessboard = [
    ["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"]
]

# Load the piece images
piece_images = {}
for file_name in os.listdir("."):
    if file_name.endswith(".png"):
        piece_name = file_name.split(".")[0].upper()
        piece_images[piece_name] = pygame.image.load(file_name).convert_alpha()
        piece_images[piece_name] = pygame.transform.scale(piece_images[piece_name], (WIDTH, HEIGHT))

# Define a function to draw the chessboard
def redraw_board():
    for row in range(8):
        for column in range(8):
            if (row + column) % 2 == 0:
                color = WHITE
            else:
                color = BLACK
            pygame.draw.rect(screen, color, [WIDTH * column, HEIGHT * row, WIDTH, HEIGHT])

            # Color the square of the previously moved piece
            if row == prev_drag_row and column == prev_drag_col:
                if (row + column) % 2 == 0:
                    pygame.draw.rect(screen, ('#C9D868'), [WIDTH * column, HEIGHT * row, WIDTH, HEIGHT])
                else:
                    pygame.draw.rect(screen, ('#A4A937'), [WIDTH * column, HEIGHT * row, WIDTH, HEIGHT])
            # Color the square of the current moved piece
            if row == drag_row and column == drag_col:
                if (row + column) % 2 == 0:
                    pygame.draw.rect(screen, ('#C9D868'), [WIDTH * column, HEIGHT * row, WIDTH, HEIGHT])
                else:
                    pygame.draw.rect(screen, ('#A4A937'), [WIDTH * column, HEIGHT * row, WIDTH, HEIGHT])

            # Draw the row numbers
            if column == 0:
                font = pygame.font.SysFont('robotomedium', 15)
                if row % 2 == 0:
                    number_label = font.render(str(8 - row), True, BLACK)
                else:
                    number_label = font.render(str(8 - row), True, WHITE)
                screen.blit(number_label, (5, HEIGHT * row + 5))

            # Draw the column letters
            if row == 7:
                font = pygame.font.SysFont('robotomedium', 15)
                if column % 2 == 0:
                    letter_label = font.render(chr(97 + column), True, WHITE)
                else:
                    letter_label = font.render(chr(97 + column), True, BLACK)
                screen.blit(letter_label, (WIDTH * column + 68, HEIGHT * row + 60))

            # Draw the pieces
            piece = chessboard[row][column]
            if piece != "  ":
                img = piece_images[piece]
                screen.blit(img, (WIDTH * column, HEIGHT * row))



def check_promotion(legal_move_, start_row, start_col, end_col, end_row):
    global legal_move
    
    if piece[1] == "P" and (end_row == 0 or end_row == 7) and legal_move == True:
            legal_move = False
            # Promote the pawn
            promotion = input("Choose a piece to promote to (Q, R, B, or N): ")
            while promotion not in ["Q", "R", "B", "N"]:
                promotion = input("Invalid choice. Choose a piece to promote to (Q, R, B, or N): ")
            if piece[0] == "W":
                if promotion == "Q":
                    chessboard[end_row][end_col] = "WQ"
                    chessboard[start_row][start_col] = "  "
                elif promotion == "R":
                    chessboard[end_row][end_col] = "WR"
                    chessboard[start_row][start_col] = "  "
                elif promotion == "B":
                    chessboard[end_row][end_col] = "WB"
                    chessboard[start_row][start_col] = "  "
                else:
                    chessboard[end_row][end_col] = "WN"
                    chessboard[start_row][start_col] = "  "
            else:
                print(start_row,start_col)
                print(end_row,end_col)
                if promotion == "Q":
                    chessboard[end_row][end_col] = "BQ"
                    chessboard[start_row][start_col] = "  "
                elif promotion == "R":
                    chessboard[end_row][end_col] = "BR"
                    chessboard[start_row][start_col] = "  "
                elif promotion == "B":
                    chessboard[end_row][end_col] = "BB"
                    chessboard[start_row][start_col] = "  "
                else:
                    chessboard[end_row][end_col] = "BN"
                    chessboard[start_row][start_col] = "  "

def is_king_in_check(chessboard, king_color):
    """
    Given a chessboard and the color of the king (either 'W' for white or 'B' for black),
    returns True if the king is in check, False otherwise.
    """
    # Find the king's location on the board
    for row in range(8):
        for col in range(8):
            piece = chessboard[row][col]
            if piece == king_color + 'K':
                king_location = (row, col)
                break

    # Check if any of the opponent's pieces can attack the king
    opponent_color = 'B' if king_color == 'W' else 'W'
    for row in range(8):
        for col in range(8):
            piece = chessboard[row][col]
            if piece[0] == opponent_color:
                if is_legal_pawn_move(row, col, king_location[0], king_location[1], chessboard):
                    # King is in check
                    return True
    # King is not in check
    return False

def is_checkmate(chessboard, king_color):
    """
    Given a chessboard and the color of the king (either 'W' for white or 'B' for black),
    returns True if the king is in checkmate, False otherwise.
    """
    # Find the king's location on the board
    for row in range(8):
        for col in range(8):
            piece = chessboard[row][col]
            if piece == king_color + 'K':
                king_location = (row, col)
                break

    # Check if the king can move to a safe square
    for i in range(king_location[0] - 1, king_location[0] + 2):
        for j in range(king_location[1] - 1, king_location[1] + 2):
            if (i, j) == king_location or i < 0 or i > 7 or j < 0 or j > 7:
                continue
            if is_legal_pawn_move(king_location[0], king_location[1], i, j, chessboard):
                # King can move to safety
                return False

    # Check if any of the king's pieces can capture the checking piece
    opponent_color = 'B' if king_color == 'W' else 'W'
    for row in range(8):
        for col in range(8):
            piece = chessboard[row][col]
            if piece[0] == king_color:
                if is_legal_pawn_move(row, col, king_location[0], king_location[1], chessboard):
                    # Another piece can capture the checking piece or block the check
                    return False

    # King is in 
    print('mate')
    return True


def is_legal_pawn_move(start_row, start_col, end_row, end_col, chessboard):
    global WK_moved, BK_moved, WR_moved, WR_moved_1, BR_moved, BR_moved_1, legal_move
    piece = chessboard[start_row][start_col]
    legal_move = False
    # Check for legal pawn moves
    if piece == "WK" or piece == "BK":
        
    # Check for legal king moves, including castling
        if abs(start_row - end_row) <= 1 and abs(start_col - end_col) <= 1:
            if chessboard[end_row][end_col][0] != piece[0]:
                if piece == 'WK':
                    WK_moved = True
                elif piece == 'BK':
                    BK_moved = True  
                return True, BK_moved, WK_moved
            else:
                return False
        elif start_row == end_row and abs(start_col - end_col) == 2:
            # Castling move
            if piece == "WK" and start_row == 7 and WK_moved == False:
                if start_col == 4 and end_col == 6 and chessboard[7][5] == "  " and chessboard[7][6] == "  " and chessboard[7][7] == "WR" and WR_moved == False:
                    chessboard[7][5] = "WR"
                    chessboard[7][7] = "  "
                    WK_moved = True
                    return True
                elif start_col == 4 and end_col == 2 and chessboard[7][1] == "  " and chessboard[7][2] == "  " and chessboard[7][3] == "  " and chessboard[7][0] == "WR" and WR_moved_1 == False:
                    chessboard[7][3] = "WR"
                    chessboard[7][0] = "  "
                    WK_moved = True
                    return True
                else:
                    return False
            elif piece == "BK" and start_row == 0 and BK_moved == False:
                if start_col == 4 and end_col == 6 and chessboard[0][5] == "  " and chessboard[0][6] == "  " and chessboard[0][7] == "BR" and BR_moved == False:
                    chessboard[0][5] = "BR"
                    chessboard[0][7] = "  "
                    BK_moved = True  
                    return True
                elif start_col == 4 and end_col == 2 and chessboard[0][1] == "  " and chessboard[0][2] == "  " and chessboard[0][3] == "  " and chessboard[0][0] == "BR" and BR_moved_1 == False:
                    chessboard[0][3] = "BR"
                    chessboard[0][0] = "  "
                    BK_moved = True  
                    return True
                else:
                    return False
            else:
                return False
        else:
            return False

    elif piece == "WQ" or piece == "BQ":
        # Queen moves can be a combination of rook and bishop moves
        if start_row == end_row:
            # Horizontal move
            if start_col < end_col:
                # Moving right
                for col in range(start_col + 1, end_col):
                    if chessboard[start_row][col] != "  ":
                        return False
            else:
                # Moving left
                for col in range(start_col - 1, end_col, -1):
                    if chessboard[start_row][col] != "  ":
                        return False
            if chessboard[end_row][end_col][0] != piece[0] or chessboard[end_row][end_col] == "  ":
                return True
            else:
                return False

        elif start_col == end_col:
            # Vertical move
            if start_row < end_row:
                # Moving down
                for row in range(start_row + 1, end_row):
                    if chessboard[row][start_col] != "  ":
                        return False
            else:
                # Moving up
                for row in range(start_row - 1, end_row, -1):
                    if chessboard[row][start_col] != "  ":
                        return False
            if chessboard[end_row][end_col][0] != piece[0] or chessboard[end_row][end_col] == "  ":
                return True
            else:
                return False

        elif abs(start_row - end_row) == abs(start_col - end_col):
            # Diagonal move
            if start_row < end_row:
                # Moving down
                if start_col < end_col:
                    # Moving right
                    for i in range(1, end_row - start_row):
                        if chessboard[start_row + i][start_col + i] != "  ":
                            return False
                else:
                    # Moving left
                    for i in range(1, end_row - start_row):
                        if chessboard[start_row + i][start_col - i] != "  ":
                            return False
            else:
                # Moving up
                if start_col < end_col:
                    # Moving right
                    for i in range(1, start_row - end_row):
                        if chessboard[start_row - i][start_col + i] != "  ":
                            return False
                else:
                    # Moving left
                    for i in range(1, start_row - end_row):
                        if chessboard[start_row - i][start_col - i] != "  ":
                            return False
            if chessboard[end_row][end_col][0] != piece[0] or chessboard[end_row][end_col] == "  ":
                return True
            else:
                return False
    
    elif piece == "WR" or piece == "BR":
        if start_row == end_row:
            # Horizontal move
            if start_col < end_col:
                # Moving right
                for col in range(start_col + 1, end_col):
                    if chessboard[start_row][col] != "  ":
                        return False
            else:
                # Moving left
                for col in range(start_col - 1, end_col, -1):
                    if chessboard[start_row][col] != "  ":
                        return False
            if chessboard[end_row][end_col][0] != piece[0] or chessboard[end_row][end_col] == "  ":
                
                if start_row == end_row or start_col == end_col:
                    if piece[0] == 'W':
                        if start_row == 7 and start_col == 0:
                            WR_moved_1 = True
                        elif start_row == 7 and start_col == 7:
                            WR_moved = True
                        return True, WR_moved, BR_moved
                    else:
                        if start_row == 0 and start_col == 0:
                            BR_moved_1 = True
                        elif start_row == 0 and start_col == 7:
                            BR_moved = True
                return True, WR_moved, BR_moved
            else:
                return False

        elif start_col == end_col:
            # Vertical move
            if start_row < end_row:
                # Moving down
                for row in range(start_row + 1, end_row):
                    if chessboard[row][start_col] != "  ":
                        return False
            else:
                # Moving up
                for row in range(start_row - 1, end_row, -1):
                    if chessboard[row][start_col] != "  ":
                        return False
            if chessboard[end_row][end_col][0] != piece[0] or chessboard[end_row][end_col] == "  ":
                if start_row == end_row or start_col == end_col:
                    if piece[0] == 'W':
                        if start_row == 7 and start_col == 0:
                            WR_moved_1 = True
                        elif start_row == 7 and start_col == 7:
                            WR_moved = True
                        return True, WR_moved, BR_moved
                    else:
                        if start_row == 0 and start_col == 0:
                            BR_moved_1 = True
                        elif start_row == 0 and start_col == 7:
                            BR_moved = True
                return True, WR_moved, BR_moved
            else:
                return False
    
    elif piece == "WP":
        if start_col == end_col and end_row == start_row - 1 and chessboard[end_row][end_col] == "  ":
            legal_move = True
        elif start_col == end_col and start_row == 6 and end_row == 4 and chessboard[4][end_col] == "  " and chessboard[5][end_col] == "  ":
            legal_move = True
        elif abs(start_col - end_col) == 1 and end_row == start_row - 1 and chessboard[end_row][end_col] != "  " and chessboard[end_row][end_col][0] == "B":
            legal_move = True
        else:
            legal_move = False
            # Check if it is the pawn's first move
            if start_row == 6 and end_row == 4 and start_col == end_col and chessboard[4][end_col] == "  " and chessboard[5][end_col] == "  ":
                legal_move = True
        check_promotion(legal_move, start_row, start_col, end_col, end_row)
        
    elif piece == "BP":
        if start_col == end_col and end_row == start_row + 1 and chessboard[end_row][end_col] == "  ":
            legal_move = True
        elif start_col == end_col and start_row == 1 and end_row == 3 and chessboard[3][end_col] == "  " and chessboard[2][end_col] == "  ":
            legal_move = True
        elif abs(start_col - end_col) == 1 and end_row == start_row + 1 and chessboard[end_row][end_col] != "  " and chessboard[end_row][end_col][0] == "W":
            legal_move = True
        else:
            legal_move = False
            # Check if it is the pawn's first move
            if start_row == 1 and end_row == 3 and start_col == end_col and chessboard[3][end_col] == "  " and chessboard[2][end_col] == "  ":
                legal_move = True
        check_promotion(legal_move, start_row, start_col, end_col, end_row)
                
    elif piece == "WN" or piece == "BN":
        if (abs(start_row - end_row) == 2 and abs(start_col - end_col) == 1) or \
           (abs(start_row - end_row) == 1 and abs(start_col - end_col) == 2):
            # Knight moves two squares in one direction and one square perpendicular to that direction
            if chessboard[end_row][end_col][0] != piece[0] or chessboard[end_row][end_col] == "  ":
                legal_move = True
            else:
                legal_move = False
        else:
            legal_move = False
    elif piece == "BB" or piece == "WB":
        if abs(start_row - end_row) == abs(start_col - end_col):
            # Bishop moves diagonally
            if start_row < end_row:
                # Bishop moves down
                if start_col < end_col:
                    # Bishop moves down-right
                    for i in range(1, end_row - start_row):
                        if chessboard[start_row + i][start_col + i] != "  ":
                            return False
                else:
                    # Bishop moves down-left
                    for i in range(1, end_row - start_row):
                        if chessboard[start_row + i][start_col - i] != "  ":
                            return False
            else:
                # Bishop moves up
                if start_col < end_col:
                    # Bishop moves up-right
                    for i in range(1, start_row - end_row):
                        if chessboard[start_row - i][start_col + i] != "  ":
                            return False
                else:
                    # Bishop moves up-left
                    for i in range(1, start_row - end_row):
                        if chessboard[start_row - i][start_col - i] != "  ":
                            return False
            # Check if the bishop is taking an opponent's piece
            if chessboard[end_row][end_col][0] != piece[0] or chessboard[end_row][end_col] == "  ":
                return True
            else:
                return False
        else:
            return False    
    
    else:
        legal_move = False

    return legal_move

def save_move(start_row, start_col, end_row, end_col):
    global Move_History
    piece = chessboard[end_row][end_col]
    #os.system('cls')
    
    rows = {0: '8', 1: '7', 2: '6', 3: '5', 4: '4', 5: '3', 6: '2', 7: '1'}
    columns = {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h'}
    
    row = rows[end_row]
    col = columns[end_col]
    
    if piece[1] == 'P':
        move = col + row
    else:
        move = piece[1] + col + row
        
    if move == 'Kg1' or move == 'Kg8':
        move = 'O-O'
    if move == 'Kc1' or move == 'Kc8':
        move = 'O-O-O'
    
    Move_History.append(move)
    
    return move
    
# Main loop
running = True
dragging = False

prev_drag_row = -1
prev_drag_col = -1
drag_row = -1
drag_col = -1

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            mouse_x, mouse_y = event.pos
            row = mouse_y // HEIGHT
            col = mouse_x // WIDTH
            piece = chessboard[row][col]
            if piece != "  ":
                dragging = True
                drag_row = row
                drag_col = col
                img_path = os.path.join(f"{piece}.png")
                img = pygame.image.load(img_path)
                img = pygame.transform.scale(img, (WIDTH, HEIGHT))
        elif event.type == pygame.MOUSEBUTTONUP:
            if dragging:
                mouse_x, mouse_y = event.pos
                end_row = mouse_y // HEIGHT
                end_col = mouse_x // WIDTH
                if drag_row != end_row or drag_col != end_col:
                    if is_legal_pawn_move(drag_row, drag_col, end_row, end_col, chessboard):
                        chessboard[end_row][end_col] = chessboard[drag_row][drag_col]
                        chessboard[drag_row][drag_col] = "  "
                        move_sound.play()     
                        save_move(drag_row, drag_col, end_row, end_col)
                        #print('================================================','\n' + '#                                          Move:',save_move(drag_row, drag_col, end_row, end_col),
                        #      '\n'+'================================================')
                        #print(*chessboard, sep='\n')
                    print(is_king_in_check(chessboard,'W'))
                    print(is_checkmate(chessboard,'W'))
                    if is_king_in_check(chessboard,'W') == 'Check':
                        print('check')
                        
                    else:
                        # Illegal move
                        pass
                dragging = False
                pygame.mixer.Sound.play(move_sound)
        elif event.type == pygame.MOUSEMOTION and dragging:
            mouse_x, mouse_y = event.pos
            # Draw the dragged piece
            img_rect = img.get_rect(center=(mouse_x, mouse_y))
            screen.fill(BLACK)
            redraw_board()
            screen.blit(img, img_rect)
            pygame.display.update()

    # Redraw the board only if not dragging
    if not dragging:
        screen.fill(BLACK)
        redraw_board()
        pygame.display.update()

pygame.quit()
sys.exit()

我尝试了多种检测将死的方法。但它总是检测到它是将军,但事实并非如此。

我也可能会尝试使用 Chess 库,以便使用

.is_checkmate()
函数更容易检测将死。

python pygame chess python-chess
© www.soinside.com 2019 - 2024. All rights reserved.