Created
April 19, 2020 21:41
-
-
Save LevBravE/e3ebec503128447d7a36a80e444b84f5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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