Автоматизация скучных вещей - Глава 5 - Шахматный словарь валидатора - PullRequest
1 голос
/ 02 февраля 2020

Первый пост, новый для программирования и веселья! Все отзывы об этом посте и мои вопросы приветствуются.

Я работаю через Automation the Boring Stuff и атакую ​​первую проблему в главе 5 Шахматный словарь Validator .

В этой главе мы использовали значение словаря {'1h': 'bking', '6 c': 'wqueen', '2g': 'bbishop', '5h': 'bqueen', '3e' : 'wking'} для представления шахматной доски. Напишите функцию с именем isValidChessBoard (), которая принимает аргумент словаря и возвращает значение True или False в зависимости от того, действительна ли доска.

На действительной доске будет ровно один черный король и ровно один белый король. Каждый игрок может иметь не более 16 фигур, не более 8 пешек, и все фигуры должны находиться на допустимом расстоянии от «1а» до «8ч»; то есть кусок не может быть в пространстве '9z'. Имена фигур начинаются с «w» или «b» для обозначения белого или черного, за которыми следуют «пешка», «рыцарь», «епископ», «ладья», «королева» или «король». Эта функция должна определять, когда ошибка привела к неправильной шахматной доске.

мои вопросы и код:

  1. Оценивает словарные ключи / значения через эти циклы for + множественные операторы if "лучшая практика"? Кажется, много кода. Изменение включения некоторых вызванных elif проблем, если за ним следует другой оператор if в for for l oop.
  2. Строка 23 if i[0] == 'b':, ошибки из-за того, что у шахматных пробелов, которые являются пустыми строковыми значениями, нет символа в i [ 0]. Каков наилучший способ выразить / оценить пустые значения? Если это с '', я должен добавить ведущее условие в l oop, который оценивает значение == '', а затем 'продолжить'?
  3. Почему я не могу свернуть строку 15 в 11 так, чтобы я есть одно утверждение: if 'bking' or 'wking' not in board.values():? Если я попытаюсь это сделать, результатом утверждения будет True; тем не менее, словарь содержит оба значения, поэтому не должен ли он иметь значение False и поддерживать выполнение кода?
def isValidChessBoard(board):
    while True:
        blackPieces = 0
        whitePieces = 0
        wpawn = 0
        bpawn = 0
        letterAxis = ('a','b','c','d','e','f','g','h')
        pieceColour = ('b','w')
        pieceType = ('pawn','knight','bishop','rook','queen','king')

        #one black king and one white king
        if 'bking' not in board.values():
            print('KingError')
            return False
            break
        if 'wking' not in board.values():
            print('KingError')
            return False
            break

        #each player has <= 16 pieces
        for i in board.values():
            if i[0] == 'b':
                blackPieces+=1
            if i[0] == 'w':
                whitePieces+=1
            if whitePieces >= 17:
                print('TotalPieceError')
                return False
                break
            if blackPieces >= 17:
                print('TotalPieceError')
                return False
                break

        #each player has <= 8 pawns
        for i in board.values():
            if i == 'wpawn':
                wpawn+=1
            elif i == 'bpawn':
                bpawn+=1
            if wpawn or bpawn >= 9:
                print('PawnError')
                return False
                break

        #all pieces must be on valid space from '1a' to '8h'
        for i in board.keys():
            if int(i[0]) >= 9:
                print('SpacesError')
                return False
                break
            if i[1] not in letterAxis:
                print('yAxisError')
                return False
                break

        #piece names begin with 'w' or 'b'
        for i in board.values():
            if i[0] not in pieceColour:
                print('WhiteOrBlackError')
                return False
                break

        #piece names must follow with 'pawn', 'knight', 'bishop', 'rook', 'queen', 'king'
        for i in board.values():
            if i[1:] not in pieceType:
                print('PieceTypeError')
                return False
        return 'This board checks out'

board = {'1a': 'bking','2a': 'bqueen','3a': 'brook','4a': 'brook',
'5a': 'bknight','6a': 'bknight','7a':'bbishop','8a': 'bbishop',
'1b': 'bpawn','2b': 'bpawn','3b': 'bpawn','4b':'bpawn',
'5b': 'bpawn','6b': 'bpawn','7b': 'bpawn','8b': 'bpawn',
'1c': 'wking','2c': 'wqueen','3c': 'wrook','4c': 'wrook',
'5c': 'wbishop','6c': 'wbishop','7c': 'wknight','8c':'wknight',
'1e': 'wpawn','2e': 'wpawn','3e': 'wpawn','4e': 'wpawn',
'5e': 'wpawn','6e': 'wpawn','7e': 'wpawn','8e': 'wpawn',
'1f': '','2f': '','3f': '','4f': '','5f': '','6f': '','7f': '','8f': '',
'1g': '','2g': '','3g': '','4g': '','5g': '','6g': '','7g': '','8g': '',
'1h': '','2h': '','3h': '','4h': '','5h': '','6h': '','7h': '','8h': '',}

print(isValidChessBoard(board))

Error:
Traceback (most recent call last):
line 23, in isValidChessBoard
    if i[0] == 'b':
IndexError: string index out of range

Ответы [ 2 ]

0 голосов
/ 02 февраля 2020

Поскольку вы спросили, есть ли альтернатива, я представляю следующее.

Шаги

  • Определите набор всех шахматных фигур
  • Определите действительный диапазон количества штук по типу
  • Подсчитайте количество штук на доске
  • Проверьте количество штук в допустимом диапазоне
  • Убедитесь, что позиции действительны
  • Проверьте правильность названий штук

Код

def isValidChessBoard(board):
      """Validate counts and location of pieces on board"""

      # Define pieces and colors
      pieces = ['king','queen','rook', 'knight','bishop','knight', 'pawn']
      colors = ['b', 'w']
      # Set of all chess pieces
      all_pieces = set(color+piece for piece in pieces for color in colors)

      # Define valid range for count of chess pieces by type (low, high) tuples
      valid_counts = {'king': (1, 1),
                  'queen': (1, 1),
                  'rook': (0, 2),
                  'bishop': (0, 2),
                  'knight': (0, 2),
                  'pawn': (0, 8)}

      # Get count of pieces on the board
      piece_cnt = {}
      for v in board.values():
        if v in all_pieces:
          piece_cnt.setdefault(v, 0)
          piece_cnt[v] += 1

      # Check if there are a valid number of pieces
      for piece in all_pieces:
        cnt = piece_cnt.get(piece, 0)
        lo, hi = valid_counts[piece[1:]]
        if not lo <= cnt <= hi:   # Count needs to be between lo and hi
          if lo != hi:
            print(f"There should between {lo} and {hi} {piece} but there are {cnt}")
          else:
            print(f"There should be {lo} {piece} but there are {cnt})")
          return False

      # Check if locations are valid
      for location in board.keys():
        row = int(location[:1])
        column = location[1:]
        if not ((1 <= row <= 8) and ('a' <= column <= "h")):
          print(f"Invaid to have {board[location]} at postion {location}")
          return False

      # Check if all pieces have valid names
      for loc, piece in board.items():
        if piece:
          if not piece in all_pieces:
            print(f"{piece} is not a valid chess piece at postion {loc}")
            return False

      return True
0 голосов
/ 02 февраля 2020

Вот моя версия:

  • Уберите свой while True: l oop и все свои break

  • Используйте словарь для Упростите адреса черно-белых проверок (не нужно больше двух, если для каждого цвета)

  • Проверьте значение позиции в том же l oop проверочный элемент

  • Добавлена ​​проверка только для одного короля каждого цвета

  • Вы также можете легко проверить количество типов каждой фигуры, используя словарь с типом фигуры в качестве ключа.

def isValidChessBoard(board):
    piecesCount = {'b': 0, 'w': 0}
    pawnCount = {'b': 0, 'w': 0}
    hasKing = {'b': False, 'w': False}
    letterAxis = ('a','b','c','d','e','f','g','h')
    pieceColour = ('b','w')
    pieceType = ('pawn','knight','bishop','rook','queen','king')

    #each player has <= 16 pieces
    for pos, i in board.items():
        # check position value
        #all pieces must be on valid space from '1a' to '8h'
        if int(pos[0]) >= 9:
            print('SpacesError')
            return False

        if pos[1] not in letterAxis:
            print('yAxisError')
            return False

        # check piece data
        if i != "":
            #piece names begin with 'w' or 'b'
            if i[0] not in pieceColour:
                print('WhiteOrBlackError')
                return False

            thisPieceColour = i[0]
            piecesCount[thisPieceColour] += 1

            if piecesCount[thisPieceColour] >= 17:
                print('TotalPieceError')
                return False

            #piece names must follow with 'pawn', 'knight', 'bishop', 'rook', 'queen', 'king'
            thisPieceType = i[1:]

            if thisPieceType not in pieceType:
                print('PieceTypeError')
                return False

            elif thisPieceType == 'pawn':
                pawnCount[thisPieceColour] += 1

                #each player has <= 8 pawns
                if pawnCount[thisPieceColour] >= 9:
                    print('PawnError')
                    return False

            elif thisPieceType == 'king':
                # one black king and one white king
                if hasKing[thisPieceColour] == True:
                    print("AlreadyHasKingError")

                hasKing[thisPieceColour] = True

    if list(hasKing.values()) != [True, True]:
        print("MissingKingError")
        return False

    return 'This board checks out'

board = {'1a': 'bking','2a': 'bqueen','3a': 'brook','4a': 'brook',
'5a': 'bknight','6a': 'bknight','7a':'bbishop','8a': 'bbishop',
'1b': 'bpawn','2b': 'bpawn','3b': 'bpawn','4b':'bpawn',
'5b': 'bpawn','6b': 'bpawn','7b': 'bpawn','8b': 'bpawn',
'1c': 'wking','2c': 'wqueen','3c': 'wrook','4c': 'wrook',
'5c': 'wbishop','6c': 'wbishop','7c': 'wknight','8c':'wknight',
'1e': 'wpawn','2e': 'wpawn','3e': 'wpawn','4e': 'wpawn',
'5e': 'wpawn','6e': 'wpawn','7e': 'wpawn','8e': 'wpawn',
'1f': '','2f': '','3f': '','4f': '','5f': '','6f': '','7f': '','8f': '',
'1g': '','2g': '','3g': '','4g': '','5g': '','6g': '','7g': '','8g': '',
'1h': '','2h': '','3h': '','4h': '','5h': '','6h': '','7h': '','8h': '',}

print(isValidChessBoard(board))
  1. Посмотрите, как я изменил код

  2. Просто отметьте if i != "", прежде чем получить к нему доступ

  3. Ну, вы не можете сделать это так, потому что вы хотите сравнить два значения с несколькими другими. Это возможно, как, например, использование set.intersection, но в вашем случае кажется чрезмерным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...