我编写了一个程序来检查棋盘是否有效。在我的代码的一部分中,我测试了碎片的数量是否正确。
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
的冗长,你可以尝试创建一个虚拟字典,其中包含 king
、queen
的基本计数, rook
等,并使 max_counts
成为添加该列表的两个副本的结果,其中一个带有 'b'
前缀到每个键和另一个带有 'w'
。但如果这是整套作品,我认为没有必要。
另请考虑,这可能不是一种万无一失的棋盘验证方法。除了国王之外,兵可以晋升为任何其他类型的棋子,因此在技术上可以拥有一个以上的皇后或两个以上的车。
关于python - 我可以在 python 中对具有多个条件的 if-else 语句使用嵌套的 for 循环吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65189888/