понедельник, 29 июня 2026 г.

Пайтон графика шахматы

 

import pygame

import sys

import os


# Инициализация

pygame.init()

WIDTH, HEIGHT = 600, 600

BOARD_SIZE = 8

SQUARE_SIZE = WIDTH // BOARD_SIZE

screen = pygame.display.set_mode((WIDTH, HEIGHT))

pygame.display.set_caption("Шахматы с картинками (2 игрока)")


# Цвета доски

LIGHT_SQ = (240, 217, 181)

DARK_SQ = (181, 136, 99)

SELECTED_COLOR = (130, 151, 105)


# Кодировка фигур: первая буква - цвет (b/w), вторая - тип (R, N, B, Q, K, P)

initial_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"]

]


# Словарь для хранения загруженных картинок

IMAGES = {}


def load_images():

    """Загрузка картинок из папки images и их масштабирование под размер клетки"""

    pieces = ["wP", "wR", "wN", "wB", "wQ", "wK", "bP", "bR", "bN", "bB", "bQ", "bK"]

    for piece in pieces:

        path = os.path.join("images", f"{piece}.png")

        if os.path.exists(path):

            # Загружаем и масштабируем до размеров SQUARE_SIZE x SQUARE_SIZE

            IMAGES[piece] = pygame.transform.scale(

                pygame.image.load(path).convert_alpha(), 

                (SQUARE_SIZE, SQUARE_SIZE)

            )

        else:

            print(f"Предупреждение: Файл {path} не найден! Вместо него будет текст.")


def draw_board(selected_sq):

    """Отрисовка доски, выделения и фигур"""

    for r in range(BOARD_SIZE):

        for c in range(BOARD_SIZE):

            # Определяем цвет клетки

            color = LIGHT_SQ if (r + c) % 2 == 0 else DARK_SQ

            if selected_sq == (r, c):

                color = SELECTED_COLOR

            

            # Рисуем клетку

            pygame.draw.rect(screen, color, (c * SQUARE_SIZE, r * SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE))

            

            # Рисуем фигуру

            piece = initial_board[r][c]

            if piece:

                if piece in IMAGES:

                    # Если картинка успешно загружена — выводим её

                    screen.blit(IMAGES[piece], (c * SQUARE_SIZE, r * SQUARE_SIZE))

                else:

                    # Запасной текстовый вариант на случай отсутствия картинки

                    font = pygame.font.SysFont("Arial", 16, bold=True)

                    text_color = (0, 0, 0) if piece.startswith("w") else (255, 0, 0)

                    text = font.render(piece, True, text_color)

                    screen.blit(text, (c * SQUARE_SIZE + 20, r * SQUARE_SIZE + 25))


def main():

    load_images()  # Загружаем картинки перед стартом цикла

    selected_square = None

    clock = pygame.time.Clock()

    

    while True:

        for event in pygame.event.get():

            if event.type == pygame.QUIT:

                pygame.quit()

                sys.exit()

                

            elif event.type == pygame.MOUSEBUTTONDOWN:

                x, y = pygame.mouse.get_pos()

                col = x // SQUARE_SIZE

                row = y // SQUARE_SIZE

                

                if selected_square is None:

                    # Клик 1: Выбираем фигуру

                    if initial_board[row][col] != "":

                        selected_square = (row, col)

                else:

                    # Клик 2: Перемещаем фигуру

                    prev_row, prev_col = selected_square

                    if (prev_row, prev_col) != (row, col):

                        initial_board[row][col] = initial_board[prev_row][prev_col]

                        initial_board[prev_row][prev_col] = ""

                    selected_square = None

                    

        draw_board(selected_square)

        pygame.display.flip()

        clock.tick(60)


if __name__ == "__main__":

    main()



///////////////

import sys


BOARD_SIZE = 8


def parse_board(board_str):

    """Превращает строку из 64 элементов в матрицу 8х8"""

    elements = board_str.split(",")

    return [elements[i*8:(i+1)*8] for i in range(BOARD_SIZE)]


def serialize_board(matrix):

    """Превращает матрицу 8х8 обратно в плоскую строку"""

    flat = []

    for row in matrix:

        flat.extend(row)

    return ",".join(flat)


def validate_and_move(board, start_r, start_c, end_r, end_c):

    """

    Базовая валидация ходов. 

    Возвращает (True, новая_матрица) или (False, "описание ошибки")

    """

    piece = board[start_r][start_c]

    target = board[end_r][end_c]

    

    if not piece:

        return False, "Начальная клетка пуста."

        

    # Проверяем, что не бьем фигуру того же цвета (w - белые, b - черные)

    if target and target[0] == piece[0]:

        return False, "Нельзя брать фигуру своего цвета."


    piece_type = piece[1] # 'P' (пешка), 'R' (ладья), 'N' (конь) и т.д.

    

    # --- Логика для Ладьи (R) ---

    if piece_type == "R":

        if start_r != end_r and start_c != end_c:

            return False, "Ладья ходит только по прямым линиям."

            

    # --- Логика для Пешки (P) ---

    elif piece_type == "P":

        direction = -1 if piece.startswith("w") else 1 # Белые вверх, черные вниз

        

        # Обычный ход на 1 клетку вперед

        if start_c == end_c and end_r == start_r + direction and not target:

            pass

        # Взятие по диагонали на 1 клетку

        elif abs(start_c - end_c) == 1 and end_r == start_r + direction and target:

            pass

        else:

            return False, "Неверный ход пешкой."


    # Если проверка пройдена, делаем ход

    board[end_r][end_c] = piece

    board[start_r][start_c] = ""

    return True, board


def main():

    # Проверяем аргументы командной строки

    if len(sys.argv) < 3:

        print("ERROR: Передайте доску и ход.")

        sys.exit(1)

        

    board_str = sys.argv[1]

    move_str = sys.argv[2]

    

    try:

        # Парсим координаты (например, "6050" -> старт (6,0), финиш (5,0))

        start_r = int(move_str[0])

        start_c = int(move_str[1])

        end_r = int(move_str[2])

        end_c = int(move_str[3])

        

        board = parse_board(board_str)

        success, result = validate_and_move(board, start_r, start_c, end_r, end_c)

        

        if success:

            print(serialize_board(result))

        else:

            print(f"ERROR: {result}")

            

    except Exception as e:

        print(f"ERROR: Ошибка в работе движка: {str(e)}")


if __name__ == "__main__":

    main()


//////////////////////////

import pygame

import sys

import subprocess


pygame.init()

WIDTH, HEIGHT = 600, 650 # Добавили 50px снизу для вывода ошибок

BOARD_SIZE = 8

SQUARE_SIZE = WIDTH // BOARD_SIZE

screen = pygame.display.set_mode((WIDTH, HEIGHT))

pygame.display.set_caption("Шахматный GUI (Вызов внешнего движка)")


LIGHT_SQ = (240, 217, 181)

DARK_SQ = (181, 136, 99)

SELECTED_COLOR = (130, 151, 105)


# Стартовое состояние в виде плоской строки из 64 элементов

board_state = [

    "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"

]


def draw_board(selected_sq, error_msg=""):

    screen.fill((200, 200, 200)) # Фон для панели ошибок

    

    # Рисуем доску и фигуры

    for r in range(BOARD_SIZE):

        for c in range(BOARD_SIZE):

            color = LIGHT_SQ if (r + c) % 2 == 0 else DARK_SQ

            if selected_sq == (r, c):

                color = SELECTED_COLOR

            pygame.draw.rect(screen, color, (c * SQUARE_SIZE, r * SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE))

            

            piece = board_state[r * 8 + c]

            if piece:

                font = pygame.font.SysFont("Arial", 22, bold=True)

                # Белые фигуры — синие, Черные — красные (для наглядности без картинок)

                text_color = (0, 50, 150) if piece.startswith("w") else (150, 0, 0)

                text = font.render(piece, True, text_color)

                text_rect = text.get_rect(center=(c * SQUARE_SIZE + SQUARE_SIZE//2, r * SQUARE_SIZE + SQUARE_SIZE//2))

                screen.blit(text, text_rect)

                

    # Вывод сообщения об ошибке в нижнюю панель

    if error_msg:

        font_err = pygame.font.SysFont("Arial", 16, bold=True)

        text_err = font_err.render(error_msg, True, (200, 0, 0))

        screen.blit(text_err, (15, WIDTH + 15))


def send_to_engine(current_board, move_str):

    """Вызывает скрипт chess_engine.py через подпроцесс ОС"""

    board_arg = ",".join(current_board)

    

    # Выполняем команду: python chess_engine.py [доска] [ход]

    result = subprocess.run(

        [sys.executable, "chess_engine.py", board_arg, move_str],

        capture_output=True,

        text=True,

        encoding="utf-8"

    )

    return result.stdout.strip()


def main():

    global board_state

    selected_square = None

    error_message = ""

    clock = pygame.time.Clock()

    

    while True:

        for event in pygame.event.get():

            if event.type == pygame.QUIT:

                pygame.quit()

                sys.exit()

                

            elif event.type == pygame.MOUSEBUTTONDOWN:

                x, y = pygame.mouse.get_pos()

                

                # Игнорируем клики на нижней панели ошибок

                if y >= WIDTH:

                    continue

                    

                col = x // SQUARE_SIZE

                row = y // SQUARE_SIZE

                

                if selected_square is None:

                    # Клик 1: Выбираем фигуру

                    if board_state[row * 8 + col] != "":

                        selected_square = (row, col)

                        error_message = "" # Сброс старой ошибки

                else:

                    # Клик 2: Делаем ход

                    prev_row, prev_col = selected_square

                    if (prev_row, prev_col) != (row, col):

                        # Формируем строку аргумента хода, например "6050"

                        move_str = f"{prev_row}{prev_col}{row}{col}"

                        

                        # Запрос к движку

                        engine_response = send_to_engine(board_state, move_str)

                        

                        if engine_response.startswith("ERROR:"):

                            error_message = engine_response

                        else:

                            # Если всё ок, движок вернул новую строку доски — обновляем её

                            board_state = engine_response.split(",")

                            

                    selected_square = None

                    

        draw_board(selected_square, error_message)

        pygame.display.flip()

        clock.tick(60)


if __name__ == "__main__":

    main()


Комментариев нет:

Отправить комментарий