python - 我可以在 python 中对具有多个条件的 if-else 语句使用嵌套的 for 循环吗?

标签 python if-statement conditional-statements

我编写了一个程序来检查棋盘是否有效。在我的代码的一部分中,我测试了碎片的数量是否正确。

count是字典,是我要查的board的一个库存。例如(b代表黑色,w代表白色):

count = {'bking': 1, 'wking': 1, 'bpawn': 3, 'bbishop': 1, 'wrook': 1, 'wqueen': 1}

可能的颜色和部件在列表中可用:

colors = ['b', 'w']
pieces = ['queen', 'rook', 'knight', 'bishop', 'pawn']

我有以下带有多个条件的难看的 if-else 语句:

if count['bking'] == 1 and \
    count['wking'] == 1 and \
    count.get('bqueen', 0) <= 2 and \
    count.get('wqueen', 0) <= 2 and \
    count.get('bpawn', 0) <= 8 and \
    count.get('wpawn', 0) <= 8 and \
    count.get('brook', 0) <= 2 and \
    count.get('wrook', 0) <= 2 and \
    count.get('bknight', 0) <= 2 and \
    count.get('wknight', 0) <= 2 and \
    count.get('bbishop', 0) <= 2 and \
    count.get('wbishop', 0) <= 2 and \
    len(board) <= 32:
        return True
    else:
        return False

有没有办法用嵌套的 for 循环来简化这个 if-else 结构?我意识到带有 get() 方法的行非常重复。我的想法是制作一个迭代颜色的外部 for 循环和一个迭代片段的内部循环。 get() 调用中的第一个参数是颜色列表中的一项与件列表中的一项的串联。有办法吗?

是否有另一种方法可以使这个 if-else 语句更像 pythonic?

这是我的第一次尝试:

for c in colors:
   for p in pieces[:4]:
      if count.get(c + p, 0) <= 2:
   if count.get(c + pieces[-1], 0) <= 8:
      return = True
   else:
      return = False

但这不起作用,我收到 SyntaxError 或 IndentationError。

我的原始代码似乎有效如下:

# chessDictValidator.py

def boardInventory(board):
    # Makes an inventory of the board to be evaluated.
    count = {}
    for value in board.values():
        count.setdefault(value, 0)
        count[value] += 1
    return count

def boardCounter(board):
    # Checks if amounts of pieces are valid.
    count = boardInventory(board)
    if count['bking'] == 1 and \
    count['wking'] == 1 and \
    count.get('bqueen', 0) <= 2 and \
    count.get('wqueen', 0) <= 2 and \
    count.get('bpawn', 0) <= 8 and \
    count.get('wpawn', 0) <= 8 and \
    count.get('brook', 0) <= 2 and \
    count.get('wrook', 0) <= 2 and \
    count.get('bknight', 0) <= 2 and \
    count.get('wknight', 0) <= 2 and \
    count.get('bbishop', 0) <= 2 and \
    count.get('wbishop', 0) <= 2 and \
    len(board) <= 32:
        return True
    else:
        return False

def fieldValidator(board):
    # Checks if the board contains valid fields.
    fieldOK = 0
    for key in board.keys():
        if key[0] in fieldInt and key[1] in fieldChar:
            fieldOK += 1
        else:
            return False
    if fieldOK == len(board):
        return True

def pieceValidator(board):
    # Checks if the pieces are spelled correctly.
    pieceOK = 0
    for value in board.values():
        if value[0] in pieceColor and value[1:] in pieces:
            pieceOK += 1
        else:
            return False
    if pieceOK == len(board):
        return True

def boardValidator(board):
    # Checks if the board is valid, depending on the tests above. Prints an error message when board is invalid.
    valid = 'This is a valid chess board!'
    invalid = 'Invalid chess board!'
    wrong = 'There is a wrong {0} in your board!'
    numPieces = 'There is something wrong with the allowed amount of pieces!'
    if fieldValidator(board) and pieceValidator(board) and boardCounter(board):
        print(valid)
    elif fieldValidator(board) == False:
        print(invalid, wrong.format('field'))
    elif pieceValidator(board) == False:
        print(invalid, wrong.format('piece'))
    elif boardCounter(board) == False:
        print(invalid, numPieces)

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

fieldInt = ['1', '2', '3', '4', '5', '6', '7', '8']
fieldChar = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
pieceColor = ['b', 'w']
pieces = ['king', 'queen', 'knight', 'rook', 'bishop', 'pawn']

boardValidator(board)

最佳答案

首先,我建议将此检查外包给专门的职能部门。

其次,您可以使用带有预期最大值的字典,并使用带有 all() 的理解来更简洁地执行检查。

max_counts = {
    'bking': 1,
    'bqueen': 1,
    'brook': 2,
    'bknight': 2,
    'bbishop': 2,
    'bpawn': 8,
    'wking': 1,
    'wqueen': 1,
    'wrook': 2,
    'wknight': 2,
    'wbishop': 2,
    'wpawn': 8
}

def board_is_valid(count, board):
    return len(board) <= 32 and all(
               count[piece] <= ct 
               for (piece, ct) in max_counts.items()
           )

如果你想稍微减少 max_counts 的冗长,你可以尝试创建一个虚拟字典,其中包含 kingqueen 的基本计数, rook 等,并使 max_counts 成为添加该列表的两个副本的结果,其中一个带有 'b' 前缀到每个键和另一个带有 'w'。但如果这是整套作品,我认为没有必要。


另请考虑,这可能不是一种万无一失的棋盘验证方法。除了国王之外,兵可以晋升为任何其他类型的棋子,因此在技术上可以拥有一个以上的皇后或两个以上的车。

关于python - 我可以在 python 中对具有多个条件的 if-else 语句使用嵌套的 for 循环吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65189888/

相关文章:

python - Python 中元组到字​​符串的列表

python - pandas 中是否有相当于 python 内置函数 `all` 的函数?

c - 虽然有多个条件

python - 循环遍历列并在特定条件下停止(python)

python - 来自另一个数据框的 Pandas 多索引分配

python - 是否可以编写一个在每次测试时都不会关闭浏览器的单元测试脚本?

javascript - 如何降低 if/else 复杂度?

c++ - 将 array.size() 与负值进行比较时出现 if 条件的意外行为

c - 警告 : statement with no effect [-Wunused-value] with if statements

python - Python 2 中的格式化字符串文字