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

Python очень обширый язык программирования, на котором можно создать бесконечное множество разнообразных проектов. Свой первый проект я решил посвятить шахматам – одной из древнейших настольных игр с достаточно простыми правилами но в то же время заставляющей человека думать и планировать.
Актуальность выбранной темы проекта связана с актуальностью профессионального изучения информатики и программирования в современном мире.
Новизна проекта заключается в сочетании теории и практики, использовании различных ресурсов для написания кода.
Цель проекта – Создать графический интерфейс на основе PyQt для игры в шахматы для 2 игроков
- Реализовать классы фигур, механики передвижения.
- Создать поле для игры, механику атаки
- Реализовать таймер, обработку событий мыши.
- С помощью 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
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
Конь двигается буквой «Г», т.е. на 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
Слон двигается по диагонали т.е. его смещение по вертикали должно быть равно смещению по горизонтали:
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
Королева двигается по всем сторонам (по горизонтали, вертикали, диагонали). Копируем эти механики из слона и ладьи и получаем:
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
Король двигается в любую сторону на расстояние 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
А теперь необходимо реализовать некоторые особые механики игры, например «Превращение пешки» и «Рокировка».
Когда пешка доходит до противоположного конца доски она может стать Ферзем, Ладьей, Слоном или Конем. Для этого мы можем просто изменить класс фигуры, в том месте, где стоит пешка.
Для рокировки нам нужно знать: двигались ли король и ладья, есть ли между ними фигуры, приведет ли рокировка к шаху короля. От этого будет зависеть успешность рокировки или её невозможность.
Представим доску в виде матрицы на координатной оси. Тогда расположение фигур на доске будет записано в двухмерном списке. Записыаем стартовые значения матрицы:
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. Этот проект ждет ещё множество новых механик и нововведений: добавление ИИ, реализация более сложных механик, которыми пользуются проффесиональные игроки(прим.: «Взятие на проходе»). В дальнейшем я не собираюсь останавливаться на этом проекте, так как меня ждет ещё множество нереализованных идей, ждущих своего часа.
- Pythonworld.ru
- Chessmatenok.ru
- Учебник PyQt5
Написание шахмат за 1 час с помощью СhatGPT
Цель этого эксперимента — проверить способности написания кода chatGPT.
Давайте посмотрим на диалог, который у меня был с chatGPT
Вопрос: Давай вместе напишем программу шахмат на Python
Ответ: Конечно, это звучит очень интересно! Прежде чем мы начнём, я должен упомянуть, что написание полнофункциональной шахматной программы является нетривиальной задачей и, вероятно, потребует значительного количества времени и усилий. Однако мы, безусловно, можем начать с обсуждения некоторых основных концепций и идей, которые были бы задействованы в таком проекте.
Для начала нам нужно было бы представить состояние шахматной доски в нашей программе. Это можно было бы сделать с помощью двумерного массива, где каждый элемент массива представляет собой один квадрат на шахматной доске. Нам нужно было бы сохранить тип фигуры, которая занимает каждый квадрат, а также любую другую соответствующую информацию, такую как переместилась ли фигура, угрожают ли ей какие-либо другие фигуры и т.д.
Как только у нас появится способ представить состояние шахматной доски, нам нужно будет внедрить правила шахмат. Это включало бы такие вещи, как обеспечение того, чтобы фигуры двигались только теми способами, которые им разрешены (например, слон может двигаться только по диагонали), предотвращение совершения игроками незаконных ходов (таких как перемещение фигуры на квадрат, который занят одной из их собственных фигур), и обработка специальных ходов, таких как рокировка и взятие на проходе.
Далее нам нужно было бы реализовать логику игры, которая включала бы отслеживание того, чья очередь, проверку окончания игры (например, когда игрок ставит мат) и обработку других аспектов игры, таких как продвижение пешки и захват фигур.
Наконец, нам нужно было бы реализовать какой-то пользовательский интерфейс, такой как интерфейс командной строки или графический пользовательский интерфейс, чтобы позволить игрокам взаимодействовать с программой и делать свои ходы.
В целом, при написании шахматной программы необходимо учитывать множество различных аспектов, и для её правильного выполнения потребуется хорошее понимание правил шахмат и тщательное планирование. Тем не менее, я думаю, что это был бы сложный и полезный проект для работы, и я с нетерпением жду возможности услышать больше о ваших идеях о том, как подойти к нему!
Вопрос: Начни с генерации кода шахматной доски
Ответ: Конечно, мы можем начать с внедрения шахматной доски. Как я упоминал ранее, одним из способов сделать это было бы использование двумерного массива, где каждый элемент массива представляет собой один квадрат на шахматной доске. Вот один из возможных способов сделать это:
Pygame шахматная доска 8х8
Короче я делаю что-то на подобии шахмат! и пытаюсь на пайгейм расчертить поле, но вот не задача, оно все время какое-то кривое и косое! Что делать с этим не знаю, перепробовал все что знаю! Код который снизу лучшее что вышло!
import pygame as pg pg.init() RES = WEDTH, HEIGHT = 800, 800 sc = pg.display.set_mode(RES) BLACK = (0, 0, 0) WHITE = (255, 255, 255) BLEDZOLOT =(238,232,170) OHRA = (160,82,45) FPS = 60 size = 100 y = 0 clock = pg.time.Clock() while True: for event in pg.event.get(): if event.type == pg.QUIT: pg.quit() quit() count = 0 for run in range(8): for x in range(8): if y % 2 == 0: x += 100 if count % 2 == 0: pg.draw.rect(sc, BLEDZOLOT, [size*x, size*y, size, size]) else: pg.draw.rect(sc, OHRA, [size*x, size*y, size, size]) count += 1 y += 1 pg.display.update() clock.tick(FPS)
Отслеживать
задан 5 фев 2022 в 13:14
91 7 7 бронзовых знаков
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
for x in range(8): for y in range(8): if (x + y) % 2 == 0: pg.draw.rect(sc, BLEDZOLOT, [size*x, size*y, size, size]) else: pg.draw.rect(sc, OHRA, [size*x, size*y, size, size])
Отслеживать
ответ дан 5 фев 2022 в 13:23
19.6k 6 6 золотых знаков 22 22 серебряных знака 56 56 бронзовых знаков
Условие
Заданы две клетки шахматной доски. Если они покрашены в один цвет, то выведите слово YES , а если в разные цвета — то NO . Программа получает на вход четыре числа от 1 до 8 каждое, задающие номер столбца и номер строки сначала для первой клетки, потом для второй клетки.
Решение
x1 = int(input()) y1 = int(input()) x2 = int(input()) y2 = int(input()) if (x1 + y1 + x2 + y2) % 2 == 0: print('YES') else: print('NO')
Комментарии
Аноним :
объясните пожалуйста задачу))
Аноним :
то есть решение
Аноним :
Если сумма всех цифр номеров строк и столбцов сложить ,то если цвета одинаковые,то число кратно 2,а иначе, т.е. если цвета разные,то число не кратно 2.