• Главная
  • Блог
  • Пользователи
  • Форум

Вход на сайт

  • Регистрация
  • Забыли пароль?
  • Литературное творчество
  • Музыкальное творчество
  • Научно-техническое творчество
  • Художественно-прикладное творчество

«Программное приложение на Python – игра «Шахматы»»

Опубликовано Коркунова Наталья Ивановна вкл 15.04.2021 - 9:18
Коркунова Наталья Ивановна
Автор: 
Калин Егор

Цель проекта – Создать графический интерфейс на основе PyQt для игры в шахматы для 2 игроков

 

Скачать:

ВложениеРазмер
Файл proekt_shahmat.docx28.29 КБ

Предварительный просмотр:

Муниципальное образовательное учреждение Гимназия №6

г.о. Красноармейск

Муниципальная конференция «Шаг в профессию инженер»

Номинация: «Программирование»

Тема:

«Программное приложение на Python – игра «Шахматы»»

Автор работы: Калин Егор Олегович, 9класс

Научный руководитель: Коркунова Н.И.

Красноармейск

2021г.

Оглавление

  1. Оглавление..............................................................................                                                                                                    

1

  1. Введение..................................................................................

2

  1. Классы фигур.......................................................................

2-6

  1. Реализация доски.................................................................

6-8

  1. Таймер, Обработка событий мыши......................................

8

  1. Графический интерфейс........................................................

8

  1. Заключение.............................................................................

8

  1. Библиография.........................................................................

9

Введение

Python очень обширый язык программирования, на котором можно создать бесконечное множество разнообразных проектов. Свой первый проект я решил посвятить шахматам – одной из древнейших настольных игр с достаточно простыми правилами но в то же время заставляющей человека думать и планировать.

Актуальность выбранной темы проекта связана с актуальностью профессионального изучения информатики и программирования в современном мире.

Новизна проекта заключается в сочетании теории и практики, использовании различных ресурсов для написания кода.

Цель проекта – Создать графический интерфейс на основе PyQt для игры в шахматы для 2 игроков

Задачи проекта:

  1. Реализовать классы фигур, механики передвижения.
  2. Создать поле для игры, механику атаки
  3. Реализовать таймер, обработку событий мыши.
  4. С помощью PyQt создаем графический интерфейс

Основная часть

Классы фигур

Все фигуры имеют некоторые одинаковые механики, поэтому для начала создадим базовый класс, от которого будем наследовать другие.

Если представить доску в виде матрицы, то можно определять местоположение фигур с помощью координат х и у.

Пешка:

Пешка может двигаться на 1 клетку по вертикали (вверх если белая и вниз если черная), а также на 2 клетки, если её ещё ни разу не двигали. Исходя из этих данных создаем класс:

class Pawn(Piece):
   ch =
'P'

   
def can_move(self, board, row, col, row1, col1):
       
# Пешка может ходить только по вертикали
       # "взятие на проходе" не реализовано
       
if col != col1:
           
return False

       if not
self.is_path_clear(board, row, col, row1, col1):
           
return False

       
# Пешка может сделать из начального положения ход на 2 клетки
       # вперёд, поэтому поместим индекс начального ряда в start_row.
       
if self.color == WHITE:
           direction =
1
           
start_row = 1
       
else:
           direction = -
1
           
start_row = 6

       
# ход на 1 клетку
       
if row + direction == row1:
           
return True

       
# ход на 2 клетки из начального положения
       
if row == start_row and row + 2 * direction == row1:
           
return True

       return False

   def
can_attack(self, board, row, col, row1, col1):
       direction =
1 if (self.color == WHITE) else -1
       
return (row + direction == row1
               
and (col + 1 == col1 or col - 1 == col1))

Ладья:

Эта фигура может двигаться только по вертикали и горизонтали, т.е. должны совпадать координаты до передвижения и после лтбо по вертикали либо по горизонтали. Зная это, реализуем класс:

class Rook(Piece):
   ch =
'R'

   
def can_move(self, board, row, col, row1, col1):
       
# Невозможно сделать ход в клетку, которая не лежит в том же ряду
       # или столбце клеток.
       
if row != row1 and col != col1:
           
return False
       if not
self.is_path_clear(board, row, col, row1, col1):
           
return False

       return True

Конь:

Конь двигается буквой «Г», т.е. на 2 по вертикали и 1 по горизонтали и наоборот. При этом направление не важно, значит нужно использовать ф-цию abs(), т.е. модуль.

class Knight(Piece):
   ch =
'N'

   
def can_move(self, board, row, col, row1, col1):
       
# Конь двигается буквой Г (2 вертикально, 1 горизонтально)
       
if abs(row - row1) == 2 and abs(col - col1) == 1:
           
return True
       
# Конь двигается буквой Г (1 вертикально, 2 горизонтально)
       
if abs(row - row1) == 1 and abs(col - col1) == 2:
           
return True

       return False

Слон:

Слон двигается по диагонали т.е. его смещение по вертикали должно быть равно смещению по горизонтали:

class Bishop(Piece):
   ch =
'B'

   
def can_move(self, board, row, col, row1, col1):

       
if not self.is_path_clear(board, row, col, row1, col1):
           
return False

       
# Слон двигается по диагонали
       # Смещение по строка должно равняться смещению по столбцам
       
if abs(row - row1) == abs(col - col1):
           
return True

       return False

Королева(Ферзь):

Королева двигается по всем сторонам (по горизонтали, вертикали, диагонали). Копируем эти механики из слона и ладьи и получаем:

class Queen(Piece):
   ch =
'Q'

   
def can_move(self, board, row, col, row1, col1):

       
if not self.is_path_clear(board, row, col, row1, col1):
           
return False

       
# Ферзь двигается вертикально
       
if col == col1:
           
return True

       
# Ферзь двигается горизонтально
       
if row == row1:
           
return True

       
# Ферзь двигается по диагонали
       # Смещение по строка должно равняться смещению по столбцам
       
if abs(row - row1) == abs(col - col1):
           
return True

       return False

Король:

Король двигается в любую сторону на расстояние 1:

class King(Piece):
   ch =
'K'

   
def can_move(self, board, row, col, row1, col1):

       
if not self.is_path_clear(board, row, col, row1, col1):
           
return False

       
# Король двигается в любую клетку с рассотоянием равным 1
       
if max(abs(row - row1), abs(col - col1)) == 1:
           
return True

       return False

А теперь необходимо реализовать некоторые особые механики игры, например «Превращение пешки» и «Рокировка».

Когда пешка доходит до противоположного конца доски она может стать Ферзем, Ладьей, Слоном или Конем. Для этого мы можем просто изменить класс фигуры, в том месте, где стоит пешка.

Для рокировки нам нужно знать: двигались ли король и ладья, есть ли между ними фигуры, приведет ли рокировка к шаху короля. От этого будет зависеть успешность рокировки или её невозможность.

Реализация доски

Представим доску в виде матрицы на координатной оси. Тогда расположение фигур на доске будет записано в двухмерном списке. Записыаем стартовые значения матрицы:

self.field = [[None] * 8 for _ in range(8)]
self.field[0] = [
   Rook(WHITE)
, Knight(WHITE), Bishop(WHITE), Queen(WHITE),
   
King(WHITE), Bishop(WHITE), Knight(WHITE), Rook(WHITE)
]
self.field[1] = [
   Pawn(WHITE)
, Pawn(WHITE), Pawn(WHITE), Pawn(WHITE),
   
Pawn(WHITE), Pawn(WHITE), Pawn(WHITE), Pawn(WHITE)
]
self.field[6] = [
   Pawn(BLACK)
, Pawn(BLACK), Pawn(BLACK), Pawn(BLACK),
   
Pawn(BLACK), Pawn(BLACK), Pawn(BLACK), Pawn(BLACK)
]
self.field[7] = [
   Rook(BLACK)
, Knight(BLACK), Bishop(BLACK), Queen(BLACK),
   
King(BLACK), Bishop(BLACK), Knight(BLACK), Rook(BLACK)
]

Цвет фигуры определяют константы WHITE и BLACK.

Каждая клетка имеет свое значение, так белая пешка обозначена как «wP». В дальнейшем это обозначение определит графическую модель фигурки на доске.

В этом классе создаем ф-цию проверки возможности движения:

def check_move(self, row: int, col: int, row1: int, col1: int):
   
"""Проверка перемещения фигуру из точки (row, col) в точку (row1, col1).
   Если перемещение возможно, метод выполнит его и вернет True.
   Если нет --- вернет False"""
   
check = self.check()  # Есть ли шах к перед ходом
   
if not correct_coords(row, col) or not correct_coords(row1, col1):
       
return False
   if
row == row1 and col == col1:
       
return False  # нельзя пойти в ту же клетку
   
piece = self.field[row][col]
   target =
self.field[row1][col1]
   
if piece is None:
       
return False
   if
piece.get_color() != self.color:
       
return False

   if
isinstance(piece, King) and self.is_under_attack(row1, col1, opponent(self.current_player_color())):
       
return False

   if not
(piece.can_move(self.field, row, col, row1, col1) and target is None) and \
           
not (piece.can_attack(self.field, row, col, row1, col1) and
               
(target is not None and not isinstance(target, King)
                 
and target.get_color() == opponent(self.current_player_color()))):
       
return False

   
old_field = [x.copy() for x in self.field]  # Сохранить поле
   
self.field[row][col] = None  # Снять фигуру.
   
self.field[row1][col1] = piece  # Поставить на новое место.
   
if check and self.check():  # В результате хода избежать шаха не удалось
       # Возвращаемся в исходное состояние
       
self.field = old_field
       
return False
   
# Возвращаемся в исходное состояние
   
self.field = old_field
   
return True

Ф-ция проверяет сразу все факторы: выход за пределы доски, походила ли фигурка на свое же место, приведет ли ход короля к его шаху или мату и т.д.

Реализуем ф-цию движения в которой используется ф-ция проверки:

def move_piece(self, row, col, row1, col1):
   
"""Переместить фигуру из точки (row, col) в точку (row1, col1).
   Если перемещение возможно, метод выполнит его и вернет True.
   Если нет --- вернет False"""
   
if self.check_move(row, col, row1, col1):
       piece =
self.field[row][col]
       
self.field[row][col] = None  # Снять фигуру.
       
piece.moved()
       
self.field[row1][col1] = piece  # Поставить на новое место.
       
if self.check_promotion(piece, row1):
           
self.promotion = True
       
self.color = opponent(self.color)
       
self.change = True
       return True
   return False

Также здесь реализуем механику атаки:

def is_under_attack(self, row, col, color):
   
for row1 in range(8):
       
for col1 in range(8):
           
if self.field[row1][col1] is not None:
               
if self.field[row1][col1].get_color() == color and \
                       
self.field[row1][col1].can_attack(self.field, row1, col1, row, col):
                   
return True
   return False

Для короля мы должны реализовать «Шах» и «Мат». Это довольно таки сложно из-за того, что у короля пропадает много возможностей, например «Рокировка». Поэтому я все ещё не полностью смог воссоздать эту механику из шахмат. Но все же в случае шаха игроку будут недоступны ходы, которые приведут к мату.

Таймер и обработка событий мыши

Графический интерфейс

С помощью класса QtTimer от PyQt реализуем таймер для каждого игрока с механикой смены после окончания хода. Также с помощью механизма слотов и сигналов PyQt мы сможем обрабатывать события мыши для удобного взаимодействия с графическим интерфейсом.

Реализация графического интерфейса, пожалуй, одна из самых сложных задач проекта, так как PyQt я знаю ещё очень поверхностно. Но что есть – то есть. Создаем модели фигурок, а также модели иконок и изображение поля. Настраиваем механику обработки мыши под границы моделей клеток и иконок.

Дополняем последние детали в виде кнопок «Новая игра» и «Выйти».

Заключение

Проект завершен, создан рабочий вариант шахмат.

 Во время разработки проекта я узнал о многих механиках программирования, получил знания о классах объектов, познакомился с QT. Этот проект ждет ещё множество новых механик и нововведений: добавление ИИ, реализация более сложных механик, которыми пользуются проффесиональные игроки(прим.: «Взятие на проходе»). В дальнейшем я не собираюсь останавливаться на этом проекте, так как меня ждет ещё множество нереализованных идей, ждущих своего часа.

Библиография

  1. Pythonworld.ru
  2. Chessmatenok.ru
  3. Учебник PyQt5


Поделиться:

О падающих телах. Что падает быстрее: монетка или кусочек бумаги?

Скворечня

Весёлые польки для детей

Рисуем "Ночь в лесу"

Кактусы из сада камней