Перейти к содержимому

Как написать шахматы на python

  • автор:

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

Коркунова Наталья Ивановна

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

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

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

Saved searches

Use saved searches to filter your results more quickly

Cancel Create saved search

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

Шахматы на Python

SergeyLebidko/PyChess

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Switch branches/tags
Branches Tags
Could not load branches
Nothing to show
Could not load tags
Nothing to show

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Cancel Create

  • Local
  • Codespaces

HTTPS GitHub CLI
Use Git or checkout with SVN using the web URL.
Work fast with our official CLI. Learn more about the CLI.

Sign In Required

Please sign in to use Codespaces.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

Latest commit message
Commit time

README.md

Простая шахматная программа. Написана на python 3.7 (с использованием библиотеки pygame 1.9.6). Для начала новой партии необходимо запустить файл start_white.pyw (играть белыми) или start_black.pyw (играть черными). Файлы пакета game_pack:

  • game.py Функции, входящие в файл необходимы для создания и работы интерфейса. Они отрисовывают доску, фигуры, доступные ходы, сообщения, выводимые пользователю, принимают и обрабатывают щелчки мышкой.
  • params.py Параметры игры: цветовые константы, типы ходов, список приоритетов фигур и т.д.
  • figures.py Файл содержит классы, описывающие шахматные фигуры. Все они унаследованы от одного общего класса Figure (в свою очередь унаследованного от pygame.sprite.Sprite), содержащего код, необходимый для хранения координат фигур и их перерисовки. Каждый класс фигуры, содержит метод get_actions, который возвращает список клеток, на которые могла бы походить фигура.
  • boards.py Содержит классы, необходимые для представления игрового поля (Board), ходов (Move) и селектора фигур (SelectorBoard), используемого при выборе фигуры, на которую следует заменить пешку, дошедшую до края поля. Самый сложный и функциональный из них — Board. Он представляет игровое поле и действия на нём. Board содержит методы для получения списка доступных на поле ходов, применения ходов и их отката, а так же оценки текущей позиции. При получении списка доступных ходов учитывается возможность рокировки (как левой, так и правой), взятия пешки на проходе, конверсии пешки в другую фигуру. Также ходы фильтруются и отбрасываются те, которые ведут к шаху собственному королю (например, ходы, открывающие удар дальнобойным фигурам противника). При получении оценки текущей позиции учитываются относительная сила отдельных фигур (конь ценнее пешки, ферзь ценнее коня), позиция фигур на доске (слонам предпочтительно занять главные диагонали, коням предпочтительно быть как можно ближе к центру поля и т.д.), защита своих фигур и атака на чужие (напрмер, чем больше фигур противника находится под ударом, тем сильнее ваша позиция).
  • ai.py В файле содержится код, необходимый для расчета ответного хода компьютера. Использован алгоритм минимакс с отсечением заведомо неудачных позиций. Для ускорения работы просчет ведется на 4 хода вперед (таким образом, на ответный ход компьютер тратит максимум несколько секунд на процессоре core i5-2500). Также оптимизирован порядок просчета ходов: вначале оцениваются ходы-взятия, которые заведомо быстрее ведут к значимым изменениям на доске и быстрее вызывают отсечение.

Скриншоты приведены ниже

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 бронзовых знаков

Шахматные задачки. Как ходят шахматные фигуры

python mathematics

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

Ход ладьи

Шахматная ладья ходит по горизонтали или вертикали. Даны две различные клетки шахматной доски, определите, может ли ладья попасть с первой клетки на вторую одним ходом. Программа получает на вход четыре числа от 1 до 8 каждое, задающие номер столбца и номер строки сначала для первой клетки, потом для второй клетки. Программа должна вывести YES , если из первой клетки ходом ладьи можно попасть во вторую или NO в противном случае.

Задача очень простая, чтобы решить достаточно представить себе ладью на шахматном поле и проанализировать ее ход. Ладья ходит только либо по вертикале вверх или вниз, либо по горизонтали влево или вправо. Становится ясно, что одна из координат клетки всегда остается неизменной, т.е. если ладья ходит по вертикале неизменна координата Х если по горизонтали то Y. Отсюда напишем условие при котором будем сравнивать если координаты X первой и второй клетки одинаковы или координаты Y первой и второй клетки одинаковы значит выводим YES – ладья может попасть с первой клетки на вторую, иначе – NO, не может.

x1 = int(input()) y1 = int(input()) x2 = int(input()) y2 = int(input()) if x1 == x2 or y1 == y2: print('YES') else: print('NO') 

Ход короля

Шахматный король ходит по горизонтали, вертикали и диагонали, но только на 1 клетку. Даны две различные клетки шахматной доски, определите, может ли король попасть с первой клетки на вторую одним ходом. Программа получает на вход четыре числа от 1 до 8 каждое, задающие номер столбца и номер строки сначала для первой клетки, потом для второй клетки. Программа должна вывести YES , если из первой клетки ходом короля можно попасть во вторую или NO в противном случае.

Задача посложнее. Проанализируем ход. Король может ходить вверх вниз, вправо влево и по диагонали но только на одну клетку. Т.е. если разность между координатами X и Y будет составлять 1 или -1 (в случае если переходит с меньшей координаты на большую) или разность одной из координат равна 0 то соответственно король может перейти с первой клетки на вторую.

x1 = int(input()) y1 = int(input()) x2 = int(input()) y2 = int(input()) if (x1-x2 == 1 or x1-x2 == -1 or x1-x2 == 0) and (y1-y2 == 1 or y1-y2 == -1 or y1-y2 == 0): print ('YES') else: print ('NO') 

Что не так с кодом? Все это можно было записать гораздо лаконичнее.

x1 = int(input()) y1 = int(input()) x2 = int(input()) y2 = int(input()) if -1  x1-x2  1 and -1  y1-y2  1: print ('YES') else: print ('NO') 

либо использовать функцию абсолютной величины (модуля) числа – abs()

x1 = int(input()) y1 = int(input()) x2 = int(input()) y2 = int(input()) if abs(x1-x2)  1 and abs(y1-y2)  1: print ('YES') else: print ('NO') 

Ход слона

Шахматный слон ходит по диагонали. Даны две различные клетки шахматной доски, определите, может ли слон попасть с первой клетки на вторую одним ходом.

Проанализируем ход. Двигая слона по шахматной клетки можно заметить, что слон всегда ходит по диагоналям квадрата, т.е. если по координате X он передвинется на 5 клеток то и по координате Y он передвинется на 5 клеток. Отсюда можем сделать вывод, что модуль разности координатов X1 и X2 и Y1 и Y2 всегда будет равен

x1 = int(input()) y1 = int(input()) x2 = int(input()) y2 = int(input()) if abs(x1 - x2) == abs(y1 - y2): print('YES') else: print('NO') 

Ход ферзя

Шахматный ферзь ходит по диагонали, горизонтали или вертикали. Даны две различные клетки шахматной доски, определите, может ли ферзь попасть с первой клетки на вторую одним ходом.

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

x1 = int(input()) y1 = int(input()) x2 = int(input()) y2 = int(input()) if abs(x1-x2)  1 and abs(y1-y2)  1 or x1 == x2 or y1 == y2: print ('YES') else: print ('NO') 

Ход коня

Шахматный конь ходит буквой “Г” — на две клетки по вертикали в любом направлении и на одну клетку по горизонтали, или наоборот. Даны две различные клетки шахматной доски, определите, может ли конь попасть с первой клетки на вторую одним ходом.

Самая интересная фигура. Проанализировав ход коня буквой «Г» можно увидеть что если конь ходит вниз или вверх буквой то его координата по X меняется на 1 а координата по Y на 2, если влево и вправо то наоборот X на 2 а Y на 1. Исходя из этого можно написать код, что если разность координат X1 и X2 уменьшилась или увеличилась на 1 и при этом разность координат Y1 и Y2 уменьшалась или увеличилась на 2 или если разность координат X1 и X2 уменьшилась или увеличилась на 2 и при этом разность координат Y1 и Y2 уменьшалась или увеличилась на 1 то выводим YES иначе NO

x1 = int(input()) y1 = int(input()) x2 = int(input()) y2 = int(input()) if (x1 - 1 == x2 or x1 + 1 == x2) and (y1 - 2 == y2 or y1 + 2 == y2): print ('YES') elif (x1 - 2 == x2 or x1 + 2 == x2) and (y1 - 1 == y2 or y1 + 1 == y2): print ('YES') else: print ('NO') 

Очень страшное решение на самом деле, но рабочее. Можно и нужно было применить модуль разницы координат и ввести дополнительные переменные.

x1 = int(input()) y1 = int(input()) x2 = int(input()) y2 = int(input()) dx = abs(x1 - x2) # модуль разницы координат X dy = abs(y1 - y2) # модуль разницы координат Y if dx == 1 and dy == 2 or dx == 2 and dy == 1: # если разность X1 и X2 равна одной клетке а Y1 и Y2 двум или наоборот X1 и Y1 # двум клектам а Y1 и Y2 одной клетке то выводим на экран YES print('YES') else: print('NO') 

Вот такие интересные были на мой взгляд задачи. Для меня они казались сложными по началу, но если хорошенько разобраться в условии и понять как должны происходить процессы в задаче то решение приходит само по себе. Главное быть внимательным и не спешить.

Опубликованно May 13th, 2018 by Aziz Madazimov

Поделитесь, если Вам понравилось!

Вам так же может понравиться:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *