Решение на Шахматни фенове от Йолина Вълчева

Обратно към всички решения

Към профила на Йолина Вълчева

Резултати

  • 6 точки от тестове
  • 0 бонус точки
  • 6 точки общо
  • 11 успешни тест(а)
  • 6 неуспешни тест(а)

Код

class ChessException(Exception):
def __init__(self, message):
super(ChessException,self).__init__(message)
figure_points = {
('r', 'R'): 5,
('n', 'N'): 3,
('b', 'B'): 3,
('k', 'K'): 4,
('q', 'Q'): 9,
('p', 'P'): 1
}
board_letters = {'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7}
class ChessScore:
def __init__(self, figures_taken):
self.__figures_taken = figures_taken
self._score = self.__sum_points()
def __int__(self):
return self._score
def __add__(self, other):
return self._score + other._score
def __sub__(self, other):
return self._score - other._score
def __lt__(self, other):
return self._score < other._score
def __gt__(self, other):
return self._score > other._score
def __le__(self, other):
return self._score <= other._score
def __ge__(self, other):
return self._score >= other._score
def __eq__(self, other):
return self._score == other._score
def __sum_points(self):
result = 0
for figure in self.__figures_taken:
try:
result = result + figure_points[figure.lower(), figure.upper()]

Ако ключовете в речника ти са само с една бука, пак би могла да постигнеш същия резултат, но без излишни дублирания на lower и upper. Останалата част от кода може да подлежи на леки модификации, но все пак ще е по-добре.

except:
print("Figure:", figure, "not valid!")
return result
class ChessPosition:
def __init__(self, FEN):
try:
self.FEN = FEN
self.only_figures = self.__extract_onlyFigures()
if not self.__count_kings_correct():
raise ChessException('kings')
if not self.__king_position_correct():
raise ChessException('kings')
if not self.__pawns_place_correct():
raise ChessException('pawns')
except ChessException as ex:
print(ex)

Лош начин за справяне с грешка. Просто я скриваш и принтираш. Ако не я хванеш, тя пак ще се принтира, но дори друг код да използва класа ти, ще се манифестира, а няма да остане скрита.

def __pawns_place_correct(self):
column_count = 1
for element in self.FEN:
if element == ' ':

Не разбирам защо имаш това условие. не би трябвало да имаш празни итнервали в стринга. Това би било невалиден инпут, с който няма да тестваме.

break
if (element == 'p' or element == 'P') and (column_count == 1 or column_count == 8):
return False
if element == '/':
column_count += 1
return True
def __king_position_correct(self):
pass
def __count_kings_correct(self):
if self.only_figures.count('k') != 1 or self.only_figures.count('K') != 1:
return False
return True
def __extract_onlyFigures(self):
only_figures = []
for char in self.FEN:
if char == ' ':
break
if (char.lower(), char.upper()) in figure_points:
only_figures.append(char)
return only_figures
def __str__(self):
return self.FEN
def __len__(self):
return len(self.only_figures)
def __getitem__(self, str):

Доста методи използват едно и също обхождане на fen-а. Ако предварително го парснеш в друг вид данни - по-удобни за работа, ще си спестиш дублирането на код.

col, row = str
if col not in board_letters:
return None
col = board_letters[col]
row = 8 - int(row)
check = []
temp = []
print(self.FEN)
for element in self.FEN:
if element == ' ':
break
if element == '/':
check.append(temp)
temp = []
continue
if element >= '1' and element <='8':
for i in range(int(element)):
temp.append('e')
continue
temp.append(element)
check.append(temp)
if not check[row][col] == 'e':
return check[row][col]
return None
def get_white_score(self):
figures = []
for char in self.only_figures:
if char.isupper() and (char.lower(), char.upper()) in figure_points:
figures.append(char)
return ChessScore(figures)
def get_black_score(self):
figures = []
for char in self.only_figures:
if char.islower() and (char.lower(), char.upper()) in figure_points:
figures.append(char)
return ChessScore(figures)
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_equal(self):
return self.get_black_score == self.get_white_score

Лог от изпълнението

.EE...EE.E.E.....
======================================================================
ERROR: test_against_touching_kings (test.TestChessPosition)
Test for kings next to each other.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
Exception: No exception raised on: k7/K7/8/8/8/8/8/8

======================================================================
ERROR: test_black_is_winning (test.TestChessPosition)
Test black_is_winning.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
AttributeError: 'function' object has no attribute '_score'

======================================================================
ERROR: test_is_equal (test.TestChessPosition)
Test is_equal.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
Exception: Incorrect result for 8/8/8/k7/7K/8/8/8

======================================================================
ERROR: test_king_count (test.TestChessPosition)
Test for missing or multiple kings.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
Exception: No exception raised on: 8/8/8/8/8/8/8/8

======================================================================
ERROR: test_pawns_position (test.TestChessPosition)
Test for incorrect pawns.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
Exception: No exception raised on: p7/8/k7/8/7K/8/8/8

======================================================================
ERROR: test_validation_conflict (test.TestChessPosition)
Test for correct Exception on multiple validation fails.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/storage/deedee/data/rails/pyfmi-2022/releases/20221115154139/lib/language/python/runner.py", line 67, in thread
    raise result
Exception: No exception raised on: P7/K7/k7/8/8/8/8/8

----------------------------------------------------------------------
Ran 17 tests in 0.165s

FAILED (errors=6)

История (1 версия и 7 коментара)

Йолина обнови решението на 29.11.2022 12:54 (преди над 1 година)

+class ChessException(Exception):
+ def __init__(self, message):
+ super(ChessException,self).__init__(message)
+
+
+figure_points = {
+ ('r', 'R'): 5,
+ ('n', 'N'): 3,
+ ('b', 'B'): 3,
+ ('k', 'K'): 4,
+ ('q', 'Q'): 9,
+ ('p', 'P'): 1
+}
+
+
+board_letters = {'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7}
+
+
+class ChessScore:
+ def __init__(self, figures_taken):
+ self.__figures_taken = figures_taken
+ self._score = self.__sum_points()
+
+
+ def __int__(self):
+ return self._score
+
+
+ def __add__(self, other):
+ return self._score + other._score
+
+
+ def __sub__(self, other):
+ return self._score - other._score
+
+
+ def __lt__(self, other):
+ return self._score < other._score
+
+
+ def __gt__(self, other):
+ return self._score > other._score
+
+
+ def __le__(self, other):
+ return self._score <= other._score
+
+
+ def __ge__(self, other):
+ return self._score >= other._score
+
+
+ def __eq__(self, other):
+ return self._score == other._score
+
+
+ def __sum_points(self):
+ result = 0
+ for figure in self.__figures_taken:
+ try:
+ result = result + figure_points[figure.lower(), figure.upper()]

Ако ключовете в речника ти са само с една бука, пак би могла да постигнеш същия резултат, но без излишни дублирания на lower и upper. Останалата част от кода може да подлежи на леки модификации, но все пак ще е по-добре.

+ except:
+ print("Figure:", figure, "not valid!")
+ return result
+
+class ChessPosition:
+ def __init__(self, FEN):
+ try:
+ self.FEN = FEN
+ self.only_figures = self.__extract_onlyFigures()
+ if not self.__count_kings_correct():
+ raise ChessException('kings')
+ if not self.__king_position_correct():
+ raise ChessException('kings')
+ if not self.__pawns_place_correct():
+ raise ChessException('pawns')
+ except ChessException as ex:
+ print(ex)

Лош начин за справяне с грешка. Просто я скриваш и принтираш. Ако не я хванеш, тя пак ще се принтира, но дори друг код да използва класа ти, ще се манифестира, а няма да остане скрита.

+
+ def __pawns_place_correct(self):
+ column_count = 1
+ for element in self.FEN:
+ if element == ' ':

Не разбирам защо имаш това условие. не би трябвало да имаш празни итнервали в стринга. Това би било невалиден инпут, с който няма да тестваме.

+ break
+ if (element == 'p' or element == 'P') and (column_count == 1 or column_count == 8):
+ return False
+ if element == '/':
+ column_count += 1
+
+ return True
+
+
+ def __king_position_correct(self):
+ pass
+
+
+ def __count_kings_correct(self):
+ if self.only_figures.count('k') != 1 or self.only_figures.count('K') != 1:
+ return False
+ return True
+
+
+ def __extract_onlyFigures(self):
+ only_figures = []
+ for char in self.FEN:
+ if char == ' ':
+ break
+ if (char.lower(), char.upper()) in figure_points:
+ only_figures.append(char)
+ return only_figures
+
+
+ def __str__(self):
+ return self.FEN
+
+
+ def __len__(self):
+ return len(self.only_figures)
+
+
+ def __getitem__(self, str):

Доста методи използват едно и също обхождане на fen-а. Ако предварително го парснеш в друг вид данни - по-удобни за работа, ще си спестиш дублирането на код.

+ col, row = str
+ if col not in board_letters:
+ return None
+ col = board_letters[col]
+ row = 8 - int(row)
+
+ check = []
+ temp = []
+ print(self.FEN)
+ for element in self.FEN:
+ if element == ' ':
+ break
+ if element == '/':
+ check.append(temp)
+ temp = []
+ continue
+ if element >= '1' and element <='8':
+ for i in range(int(element)):
+ temp.append('e')
+ continue
+
+ temp.append(element)
+
+ check.append(temp)
+
+ if not check[row][col] == 'e':
+ return check[row][col]
+ return None
+
+
+ def get_white_score(self):
+ figures = []
+ for char in self.only_figures:
+ if char.isupper() and (char.lower(), char.upper()) in figure_points:
+ figures.append(char)
+
+ return ChessScore(figures)
+
+
+ def get_black_score(self):
+ figures = []
+ for char in self.only_figures:
+ if char.islower() and (char.lower(), char.upper()) in figure_points:
+ figures.append(char)
+
+ return ChessScore(figures)
+
+
+ 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_equal(self):
+ return self.get_black_score == self.get_white_score