Евтим обнови решението на 26.11.2022 15:19 (преди почти 2 години)
+VALID_FIGURES = ['r', 'n', 'b', 'q', 'p', 'k', 'R', 'N', 'B', 'Q', 'K', 'P']
+WHITE_FIGURES = ['R', 'N', 'B', 'Q', 'K', 'P']
+BLACK_FIGURES = ['r', 'n', 'b', 'q', 'k', 'p']
+WHITE_KING = 'K'
+BLACK_KING = 'k'
+INVALID_KINGS_POSITION = (-1, -1)
+PAWNS = ['P', 'p']
+FIGURE_SCORE = {'r':5, 'n':3, 'b':3, 'q':9, 'k':4, 'p':1}
+TABLE_COLUMNS = {'A': 0, 'B': 1, 'C':2, 'D':3, 'E':4, 'F':5, 'G':6, 'H':7}
+
+class ChessException(Exception):
+ def __init__(self, message = 'CHESS PROBLEM OCCURED'):
При дефинране на стойност по подразбиране не се слагат интервали около равното.
Като цяло не е нужно да дефинираш __init__
тук. Един pass
е достатъчен.
+ self.message = message
+ super().__init__(self.message)
+
+
+class ChessPosition:
+ def __init__(self, fen):
+ self.fen = fen
+ self.build_table()
+ self.check_kings()
+ self.check_pawns()
+
+ def build_table(self):
+ self.table = []
+ figures_in_rows = self.fen.split('/')
+
+ for row in reversed(figures_in_rows):
+ current_row = []
+ for info_for_figure in row:
+ if info_for_figure in VALID_FIGURES:
+ current_row.append(info_for_figure)
+ elif info_for_figure.isnumeric():
+ empty_rows = [None] * int(info_for_figure)
+ current_row.extend(empty_rows)
+ self.table.append(current_row)
+
+ def check_kings(self):
+ position_of_white_king = INVALID_KINGS_POSITION
+ position_of_black_king = INVALID_KINGS_POSITION
+ for row_index, row in enumerate(self.table):
+ for column_index, column in enumerate(row):
+ figure = self.table[row_index][column_index]
+ if figure == WHITE_KING:
+ current_position_of_white_king = (row_index, column_index)
+
+ if self.king_already_exists(position_of_white_king):
+ raise ChessException('kings')
+ else:
+ position_of_white_king = current_position_of_white_king
+ elif figure == BLACK_KING:
+ current_position_of_black_king = (row_index, column_index)
+
+ if self.king_already_exists(position_of_black_king):
+ raise ChessException('kings')
+ else:
+ position_of_black_king = current_position_of_black_king
+
+ if self.check_kings_for_invalid_positions(position_of_white_king, position_of_black_king) or\
+ self.check_if_both_kings_exists(position_of_white_king, position_of_black_king):
+ raise ChessException('kings')
+
+ def check_pawns(self):
+ rows_to_check = [0, 7]
+
+ for row_to_check in rows_to_check:
+ for column_index, column in enumerate(self.table[row_to_check]):
+ figure = self.table[row_to_check][column_index]
+ if figure in PAWNS:
+ raise ChessException('pawns')
+
+ def get_white_score(self):
+ self.white_figures = []
+ self.white_figures = self.get_color_score(WHITE_FIGURES)
+ return ChessScore(self.white_figures)
Тези обекти ще са константни, така че можеш да ги добавиш като атрибути на инстанциите си, за да не ги реинициализираш при всяко извикване на текущата функция.
+
+ def get_black_score(self):
+ self.black_figures = []
+ self.black_figures = self.get_color_score(BLACK_FIGURES)
+ return ChessScore(self.black_figures)
+
+ def get_color_score(self, FIGURES_OF_THAT_COLOR):
Не използвай главни букви за аргумент на функции.
+ current_color_figures = []
+ for row_index, row in enumerate(self.table):
+ for column_index, column in enumerate(row):
+ figure = self.table[row_index][column_index]
+ if figure in FIGURES_OF_THAT_COLOR:
+ current_color_figures.append(figure)
+ return current_color_figures
+
+ def __str__(self):
+ return self.fen
+
+ def __len__(self):
+ number_of_figures = 0
+ for row_index, row in enumerate(self.table):
+ for column_index, column in enumerate(row):
+ figure = self.table[row_index][column_index]
+ if figure in BLACK_FIGURES or figure in WHITE_FIGURES:
+ number_of_figures += 1
+ return number_of_figures
+
+ def __getitem__(self, table_position):
+ row = int(table_position[1]) - 1
+ column = table_position[0]
+ return self.table[row][TABLE_COLUMNS[column]]
+
+ def white_is_winning(self):
+ return self.get_white_score() > self.get_black_score()
+
+ def black_is_winning(self):
+ return self.get_black_score() > self.get_white_score()
+
+ def is_eqaul(self):
+ return self.get_black_score() == self.get_white_score()
+
+ def king_already_exists(self, position_of_king):
+ return position_of_king != INVALID_KINGS_POSITION
+
+ def check_kings_for_invalid_positions(self, position_of_white_king, position_of_black_king):
+ return abs(position_of_white_king[0] - position_of_black_king[0]) <= 1 and\
Избягвай пренасяне на редове с \
на всяка цена. По-добре дефинирай 1-2 променливи на отделни редове. Ще е по-чисто и компактно.
+ abs(position_of_white_king[1] - position_of_black_king[1]) <= 1
+
+ def check_if_both_kings_exists(self, position_of_white_king, position_of_black_king):
+ return position_of_black_king == INVALID_KINGS_POSITION or position_of_white_king == INVALID_KINGS_POSITION
+
+
+class ChessScore:
+ def __init__(self, figures):
+ self.figures = list(map(str.lower,figures))
Липсва интервал след запетаята.
+
+ def get_score(self):
Това е константно. По-добре го дефинирай като атрибут на инстанцията и го използвай наготово.
+ score = 0
+ for figure in self.figures:
+ if figure in FIGURE_SCORE:
+ score += FIGURE_SCORE[figure]
+ return score
+
+ def __add__(self, other):
+ return self.get_score() + other.get_score()
+
+ def __sub__(self, other):
+ return self.get_score() - other.get_score()
+
+ def __lt__(self, other):
+ return self.get_score() < other.get_score()
+
+ def __gt__(self, other):
+ return self.get_score() > other.get_score()
+
+ def __le__(self, other):
+ return self.get_score() <= other.get_score()
+
+ def __ge__(self, other):
+ return self.get_score() >= other.get_score()
+
+ def __eq__(self, other):
+ return self.get_score() == other.get_score()
+
+ def __ne__(self, other):
+ return self.get_score() != other.get_score()
+
Прегледай условието. Губи ти се нещо, което може да коства доста тестове.
Тези обекти ще са константни, така че можеш да ги добавиш като атрибути на инстанциите си, за да не ги реинициализираш при всяко извикване на текущата функция.
Това е константно. По-добре го дефинирай като атрибут на инстанцията и го използвай наготово.