【发布时间】:2020-05-18 14:26:52
【问题描述】:
第一篇文章,编程新手,玩得开心!欢迎对这篇文章的所有反馈和我的问题。
我正在研究 Automate the Boring Stuff 并解决第 5 章的第一个问题Chess Dictionary Validator。
在本章中,我们使用了字典值 {'1h': 'bking', '6c': 'wqueen', '2g': 'bbishop', '5h': 'bqueen', '3e ': 'wking'} 表示棋盘。编写一个名为 isValidChessBoard() 的函数,它接受一个字典参数并根据棋盘是否有效返回 True 或 False。
一个有效的棋盘将恰好有一个黑王和一个白王。每个玩家最多只能有16个棋子,最多8个棋子,并且所有棋子必须在'1a'到'8h'的有效空间上;也就是说,一块不能在空间“9z”上。棋子名称以“w”或“b”开头,表示白色或黑色,然后是“pawn”、“knight”、“bishop”、“rook”、“queen”或“king”。此功能应检测错误何时导致棋盘不正确。
我的问题和代码:
- 通过这些 for 循环 + 多个 if 语句评估字典键/值是否是“最佳实践”?似乎有很多代码。如果在 for 循环中跟随另一个 if 语句,则更改为包含一些 elif 会导致问题。
- 第 23 行
if i[0] == 'b':出错,因为空字符串值的国际象棋空间在 i[0] 处没有字符。表达/评估空值的最佳方式是什么?如果是'',我是否应该在评估值==''的循环中添加前导条件,然后'继续'? - 为什么我不能将第 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
【问题讨论】:
-
在第 23 行的 for 循环之后放置一个条件,即
if i:围绕其他条件。这将删除索引超出范围错误。 -
只是快速浏览了一下,您可以从代码中删除一件事,即 RETURN 语句之后的 BREAK 语句。这些不是必需的,如果函数到达 RETURN 语句,它会自动中断,因此不需要 BREAK 语句。
-
如果 'bking' 不在 board.values() 中或 'wking' 不在 board.values() 中,您也可以使用 $$:$$
-
'bking' or 'wking' not in board.values()等价于( 'bking' ) or ( 'wking' not in board.values() ),它的计算结果始终为'bking',这是真的。正确的版本是'bking' not in board.values() or 'wking' not in board.values(),但较短的版本使用集合:not {'bking', 'wking'}.issubset(board.values())。
标签: python dictionary for-loop if-statement