Skip to content

Instantly share code, notes, and snippets.

@LevBravE
Created April 19, 2020 21:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LevBravE/e3ebec503128447d7a36a80e444b84f5 to your computer and use it in GitHub Desktop.
Save LevBravE/e3ebec503128447d7a36a80e444b84f5 to your computer and use it in GitHub Desktop.
WHITE = 1
BLACK = 2
# Удобная функция для вычисления цвета противника
def opponent(color):
if color == WHITE:
return BLACK
else:
return WHITE
def print_board(board): # Распечатать доску в текстовом виде (см. скриншот)
print(' +----+----+----+----+----+----+----+----+')
for row in range(7, -1, -1):
print(' ', row, end=' ')
for col in range(8):
print('|', board.cell(row, col), end=' ')
print('|')
print(' +----+----+----+----+----+----+----+----+')
print(end=' ')
for col in range(8):
print(col, end=' ')
print()
def main():
# Создаём шахматную доску
board = Board()
# Цикл ввода команд игроков
while True:
# Выводим положение фигур на доске
print_board(board)
# Подсказка по командам
print('Команды:')
print(' exit -- выход')
print(' move <row> <col> <row1> <row1> -- ход из клетки (row, col)')
print(' в клетку (row1, col1)')
# Выводим приглашение игроку нужного цвета
if board.current_player_color() == WHITE:
print('Ход белых:')
else:
print('Ход чёрных:')
command = input()
if command == 'exit':
break
move_type, row, col, row1, col1 = command.split()
row, col, row1, col1 = int(row), int(col), int(row1), int(col1)
if board.move_piece(row, col, row1, col1):
print('Ход успешен')
else:
print('Координаты некорректы! Попробуйте другой ход!')
def correct_coords(row, col):
'''Функция проверяет, что координаты (row, col) лежат
внутри доски'''
return 0 <= row < 8 and 0 <= col < 8
class Board:
def __init__(self):
self.color = WHITE
self.field = []
for row in range(8):
self.field.append([None] * 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)
]
def current_player_color(self):
return self.color
def cell(self, row, col):
'''Возвращает строку из двух символов. Если в клетке (row, col)
находится фигура, символы цвета и фигуры. Если клетка пуста,
то два пробела.'''
piece = self.field[row][col]
if piece is None:
return ' '
color = piece.get_color()
c = 'w' if color == WHITE else 'b'
return c + piece.char()
def get_piece(self, row, col):
if correct_coords(row, col):
return self.field[row][col]
else:
return None
def move_piece(self, row, col, row1, col1):
'''Переместить фигуру из точки (row, col) в точку (row1, col1).
Если перемещение возможно, метод выполнит его и вернёт True.
Если нет --- вернёт False'''
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]
if piece is None:
return False
if piece.get_color() != self.color:
return False
if self.field[row1][col1] is None:
if not piece.can_move(self, row, col, row1, col1):
return False
elif self.field[row1][col1].get_color() == opponent(piece.get_color()):
if not piece.can_attack(self, row, col, row1, col1):
return False
else:
return False
self.field[row][col] = None # Снять фигуру.
self.field[row1][col1] = piece # Поставить на новое место.
self.color = opponent(self.color)
return True
class Rook:
def __init__(self, color):
self.color = color
def get_color(self):
return self.color
def char(self):
return 'R'
def can_move(self, board, row, col, row1, col1):
# Невозможно сделать ход в клетку, которая не лежит в том же ряду
# или столбце клеток.
if row != row1 and col != col1:
return False
step = 1 if (row1 >= row) else -1
for r in range(row + step, row1, step):
# Если на пути по горизонтали есть фигура
if not (board.get_piece(r, col) is None):
return False
step = 1 if (col1 >= col) else -1
for c in range(col + step, col1, step):
# Если на пути по вертикали есть фигура
if not (board.get_piece(row, c) is None):
return False
return True
def can_attack(self, board, row, col, row1, col1):
return self.can_move(board, row, col, row1, col1)
class Pawn:
def __init__(self, color):
self.color = color
def get_color(self):
return self.color
def char(self):
return 'P'
def can_move(self, board, row, col, row1, col1):
# Пешка может ходить только по вертикали
# "взятие на проходе" не реализовано
if col != 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
and board.field[row + direction][col] is None):
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 Knight:
'''Класс коня. Пока что заглушка, которая может ходить в любую клетку.'''
def __init__(self, color):
self.color = color
def get_color(self):
return self.color
def char(self):
return 'N' # kNight, буква 'K' уже занята королём
def can_move(self, board, row, col, row1, col1):
return True # Заглушка
def can_attack(self, board, row, col, row1, col1):
return self.can_move(self, board, row, col, row1, col1)
class King:
'''Класс короля. Пока что заглушка, которая может ходить в любую клетку.'''
def __init__(self, color):
self.color = color
def get_color(self):
return self.color
def char(self):
return 'K'
def can_move(self, board, row, col, row1, col1):
return True # Заглушка
def can_attack(self, board, row, col, row1, col1):
return self.can_move(self, board, row, col, row1, col1)
class Queen:
'''Класс ферзя. Пока что заглушка, которая может ходить в любую клетку.'''
def __init__(self, color):
self.color = color
def get_color(self):
return self.color
def char(self):
return 'Q'
def can_move(self, board, row, col, row1, col1):
return True # Заглушка
def can_attack(self, board, row, col, row1, col1):
return self.can_move(self, board, row, col, row1, col1)
class Bishop:
'''Класс слона. Пока что заглушка, которая может ходить в любую клетку.'''
def __init__(self, color):
self.color = color
def get_color(self):
return self.color
def char(self):
return 'B'
def can_move(self, board, row, col, row1, col1):
return True # Заглушка
def can_attack(self, board, row, col, row1, col1):
return self.can_move(self, board, row, col, row1, col1)
# __name__ -- специальная переменная, в которую python записывает имя
# файла (без .py), если этот файл импортирован из друго, и "__main__", если
# этот файл запущен как программа.
# Другими словами, следующие две строчки:
# запустят функцию main, если файл запущен как программа;
# не сделают ничего, если этот файл импортирован из другого.
# Второй случай реализуется, например, когда тестирующий скрипт импортирует
# классы из вашего скрипта. В этом случае функця main не будет работать
# и портить вывод теста.
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment