The program is supposed to print True or False depending on whether an arbitrary dictionary stored in a variable meets the criteria for a chess board. The criteria is as follows : A valid board will have exactly one black king and exactly one white king. Each player can only have at most 16 pieces, at most 8 pawns, and all pieces must be on a valid space from '1a' to '8h'; that is, a piece can’t be on space '9z'. The piece names begin with either a 'w' or 'b' to represent white or black, followed by 'pawn', 'knight', 'bishop', 'rook', 'queen', or 'king'. This function should detect when a bug has resulted in an improper chess board.
My program looks like this :
board = {'1h': 'bking', '6c': 'wqueen', '2g': 'bbishop',\
'5h': 'bqueen', '3e': 'wking'}
def isValidChessBoard(_board_):
gen_num=0
pawn_num=0
wking_num=0
bking_num=0
letters=['a','b','c','d','e','f','g','h']
pieces=['pawn','knight','bishop','rook','king','queen']
for v in _board_.values():
gen_num+=1
if gen_num > 16:
return False
for v in _board_.values():
if v.endswith('pawn'):
pawn_num+=1
if pawn_num > 8:
return False
for v in _board_.values():
if v =='wking':
wking_num+=1
if v =='bking':
bking_num+=1
if wking_num!=1 or bking_num!=1:
return False
for k in _board_.keys():
for i in range(1,9):
if not k.startswith(str(i)):
return False
for k in _board_.keys():
for i in letters:
if not k.endswith(i):
return False
for v in _board_.values():
if not v.startswith('b') or v.startswith('w'):
return False
for v in _board_.values():
for i in pieces:
if not v.endswith(i):
return False
return True
print(isValidChessBoard(board))
The dictionary seems to meet the given criteria. However, the program prints ''False'' every time I try to run it.
Is there something that I'm missing here ?
Thank you so much in advance, and I apologize if it is too basic or broad of a question.
The problem is with loops such as:
for i in range(1,9):
if not k.startswith(str(i)):
return False
It is insisting that it starts with all of these digits, rather than with any of them. The loop can be replaced with:
for i in range(1,9):
if k.startswith(str(i)):
break
else:
return False
Note that the condition is inverted. If there is a match, then it breaks from the loop. If no matches are found, then the else
block will be executed. Note the indentation here: the else
relates to the for
loop, not the if
block, and will execute if the for loop completed without being broken out of.
There were a couple of places with a similar issue.
You also had one place where parentheses were needed:
if not (v.startswith('b') or v.startswith('w')):
because the original without parentheses was equivalent to:
if (not v.startswith('b')) or v.startswith('w'):
because not
has higher operator precedence than binary boolean operators such as or
.
Putting these fixes together gives:
board = {'1h': 'bking', '6c': 'wqueen', '2g': 'bbishop',\
'5h': 'bqueen', '3e': 'wking'}
def isValidChessBoard(_board_):
gen_num=0
pawn_num=0
wking_num=0
bking_num=0
letters=['a','b','c','d','e','f','g','h']
pieces=['pawn','knight','bishop','rook','king','queen']
for v in _board_.values():
gen_num+=1
if gen_num > 16:
return False
for v in _board_.values():
if v.endswith('pawn'):
pawn_num+=1
if pawn_num > 8:
return False
for v in _board_.values():
if v =='wking':
wking_num+=1
if v =='bking':
bking_num+=1
if wking_num!=1 or bking_num!=1:
return False
for k in _board_.keys():
for i in range(1,9):
if k.startswith(str(i)):
break
else:
return False
for k in _board_.keys():
for i in letters:
if k.endswith(i):
break
else:
return False
for v in _board_.values():
if not (v.startswith('b') or v.startswith('w')):
return False
for v in _board_.values():
for i in pieces:
if v.endswith(i):
break
else:
return False
return True
print(isValidChessBoard(board))