'Automate the Boring Stuff - Chapter 5 - Chess Dictionary Validator [closed]
First post, new to programming and having fun! All feedback on this post and my questions are welcome.
I'm working through Automate the Boring Stuff and attacking the first Chapter 5 problem Chess Dictionary Validator.
In this chapter, we used the dictionary value {'1h': 'bking', '6c': 'wqueen', '2g': 'bbishop', '5h': 'bqueen', '3e': 'wking'} to represent a chess board. Write a function named isValidChessBoard() that takes a dictionary argument and returns True or False depending on if the board is valid.
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 questions and code:
- Is evaluating dictionary keys/values through these for loops + multiple if statements the "best practice"? It seems like a lot of code. Changing to include some elif caused issues if it followed with another if statement in the for loop.
- Line 23
if i[0] == 'b':errors out because the chess spaces which are empty string values have no character at i[0]. What's the best way to express/evaluate empty values? If it is with '', should I add leading condition in the loop which evaluates value == '', and then 'continue'? - Why can I not collapse line 15 into 11 such that I have one statement:
if 'bking' or 'wking' not in board.values():? If I try that, the statement result is True; however the dictionary contains both values so shouldn't it evaluate to False and keep the code running?
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
Solution 1:[1]
Here is my version:
Remove your
while True:loop and all yourbreakUse dictionnary to easier address black and white checks (need no more two if for each color)
Check position value in the same loop checking piece
Added a check for only one king of each color
You can also easily check each piece type count using a dictionnary with piece type as key.
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))
See how I refactored the code
Just check
if i != ""before accessing itWell, you can't do it like that because you want to compare two values to several other ones. It is possible, like for example using set.intersection, but seems overkill in your case.
Solution 2:[2]
Promotion in chess is a rule that requires a pawn that reaches the eighth rank to be replaced by the player's choice of a bishop, knight, rook, or queen of the same color. The piece chosen cannot be another king nor another pawn. /Wikipedia
board = {'e3': 'wking', 'c6': 'wqueen',
'g2': 'bbishop', 'd2': 'bqueen', 'g3': 'bking',
'a1': 'bpawn', 'm1': 'bpawn', 'c1': 'bpawn', 'd1': 'bpawn',
'e1': 'bpawn', 'f1': 'bpawn', 'g1': 'bpawn', 'h1': 'bpawn',
'e2': 'bpawn', 'a2': 'bpawn'}
def isValidChessBoard(board):
wKing, bKing, wPieces, bPieces = 0, 0, 0, 0
wPawns, bPawns, spaces, check = 0, 0, [], True
for x in ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'):
for y in range(1,9):
spaces.append(x + str(y))
for space, piece in board.items():
if space not in spaces:
print('Space is wrong: ' + space + ' ' + piece)
check = False
if piece == 'wking':
wKing += 1
if piece == 'bking':
bKing += 1
if piece == 'wpawn':
wPawns += 1
if piece == 'bpawn':
bPawns += 1
if piece.startswith('w'):
wPieces += 1
if piece.startswith('b'):
bPieces += 1
if wKing != 1:
print('White king != 1 : ' + str(wKing))
check = False
if bKing != 1:
print('Black king != 1 : ' + str(bKing))
check = False
if wPieces > 16:
print('Total white pieces on board > 16: ' + str(wPieces))
check = False
if bPieces > 16:
print('Total black pieces on board > 16: ' + str(bPieces))
check = False
if wPawns > 8:
print('White pawns on board > 8: ' + str(wPawns))
check = False
if bPawns > 8:
print('Black pawns on board > 8: ' + str(bPawns))
check = False
if check:
return True
else:
return False
print(isValidChessBoard(board))
Solution 3:[3]
I'm also learning Python using the same book. I find the exercises to be sometimes a little vague in their requirements definition; that means that some assumptions have to be made.
My assumptions are:
The function to be written should only return False or True, not any additionally information regarding why the board doesn't validate.
The board verification is "stateless", meaning that the current board definition is checked, and not, for example, if chess rules are followed, etc.
Verification of spaces is not required. If a piece is not declared to be in a specific position, that position is empty, i.e. I'm following the rule of "explicit declaration" of the pieces present in the board.
Please, also note that it is not needed to check if the total number of pieces declared for a player/color is more than 16, because if the quantity of each piece is correct, also the total must be correct.
I added comments that should provide enough explanation what each part does, but there are three main sections:
- Constant definitions, to make this code a little more portable.
- Definition of an 'auxiliary' function that check if the quantity of each piece in the board is the one allowed.
- The function requested by the exercise.
The code is also my first attempt to follow PEP 8 recommendations/rules, so any feedback if I'm on the correct way is very welcome, or what is wrong, of course.
I also want to clarify that the code is clearly my creation, but I also tried to pick up some ideas from other contributions/posts/answers; at the end the scope of stackoverflow is to support mutual help and contribution.
The code was tested with some example of boards created for the scope and seems to work properly, but if you spot any error, please let me know in the comments.
Thanks.
PS Edited due to some grammar errors and for better explaining the third assumption.
#!/usr/bin/env python3
# Using lists instead of sets for COLORS and PIECES should work.
#
#
# However, because it is important to stress that those constant define
# a *set* of permitted values, using sets sounds more acceptable.
# Please, note that sets are not explained in the chapter this exercise
# was taken from.
COLORS = {'b', 'w'}
PIECES = {
'king',
'queen',
'rook',
'bishop',
'knight',
'pawn'
}
VALID_QUANTITY = {
'king': (1, 1),
'queen': (0, 1),
'rook': (0, 2),
'bishop': (0, 2),
'knight': (0, 2),
'pawn': (0, 8),
}
# The following constants can be easily made using set('12345678') and
# set('abcdefgh').
ROWS = {'1', '2', '3', '4', '5', '6', '7', '8'}
COLUMNS = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}
# This function verifies if black pieces or white pieces quantity
# is correct, comparing the total pieces of each kind in the board, with
# the acceptable values defined in VALID_QUANTITY.
def verify_quantity(pieces):
for piece, quantity in pieces.items():
low, high = VALID_QUANTITY[piece]
if low <= quantity <= high:
return True
else:
return False
# This is the main function object of the exercise.
def is_valid_chess_board(board):
black_pieces = {}
white_pieces = {}
for position, player_piece in board.items():
row, column = position
player = player_piece[0]
piece = player_piece[1:]
# First it is checked that the positions of the pieces, their
# kind and colors are the ones allowed.
if (row not in ROWS) or (column not in COLUMNS):
return False
if player not in COLORS:
return False
if piece not in PIECES:
return False
# The pieces present in the board are counted for each color.
if player == 'b':
black_pieces[piece] = black_pieces.get(piece, 0) + 1
else:
white_pieces[piece] = white_pieces.get(piece, 0) + 1
# The quantity is finally checked to see if it is the one
# allowed by the rules.
if not(verify_quantity(black_pieces) or verify_quantity(white_pieces)):
return False
return True
Solution 4:[4]
Here's how I solved this. I added criteria for the valid board condition that the book doesn't mention in this question. I check for a valid number of queen, knight, rook, and bishop to make it more accurate to how a chessboard should be.
def isValidChessBoard(board: dict) -> bool:
"""Return True or False depending on if a board is valid in chess."""
board_pieces = list(board.values()) #initiate variable for repeated use
all_pieces = ['king', 'queen', 'bishop','knight','rook','pawn']
blacks, whites = 0, 0 #variable to keep count of black/white pieces
def pCount(to_count: str) -> int:
"""Return count value of the piece"""
return board_pieces.count(to_count)
#check if board has one king and at most one queen for each side
if (pCount('bking') != 1) or (pCount('wking') != 1) or \
(pCount('bqueen') > 1) or (pCount('wqueen') > 1):
return False
#check if all pieces names are valid
for piece in board_pieces:
if piece[0] not in 'bw' or piece[1:] not in all_pieces:
return False
#check if the position is valid (between 1a and 8h)
for p in board.keys():
if p[0] not in '12345678' or p[1] not in 'abcdefgh':
return False
#check if each side has a valid number of pieces
for i in board_pieces:
if i[0] == 'b':
blacks += 1
elif i[0] == 'w':
whites += 1
if (blacks or whites) > 16:
return False
elif (pCount('bpawn') or pCount('wpawn')) > 8:
return False
elif (pCount('bbishop') or pCount('bknight') or pCount('brook')) > 2 \
or (pCount('wbishop') or pCount('wknight') or pCount('wrook')) > 2:
return False
return True
I do wonder if I could make the count for the rooks, knights, and bishops more efficient as opposed to checking all pieces individually.
To verify the code works as intended I made some test boards, as follow:
#more than 2 kings
test_1 = {'1a':'bking', '8f':'wking', '2a': 'bking', '5d':'wking'}
#more than 8 pawns for one side
test_2 = {'2a':'bpawn', '2b': 'bpawn', '2c':'bpawn', '2d': 'bpawn', '2e': 'bpawn',\
'2f': 'bpawn', '2g': 'bpawn', '2h': 'bpawn',\
'7a': 'bpawn', '7b': 'wpawn', '8e': 'wking', '1e': 'bking'}
#more than 16 pieces for one player
test_3 = {'2a':'bpawn', '2b': 'bpawn', '2c':'bpawn', '2d': 'bpawn', '2e': 'bpawn',\
'2f': 'bpawn', '2g': 'bpawn', '2h': 'bpawn',\
'1a': 'brook', '1b': 'bknight', '1c': 'bbishop', '1d': 'bqueen', \
'1e':'bking', '1f': 'brook', '1g': 'bknight', '1h': 'bbishop', \
'3a': 'bpawn', '7b': 'wking', '7c': 'wqueen'}
#invalid space 9d
test_4 = {'1a':'bking', '8f':'wking', '1b':'bqueen', '9d': 'wqueen'}
#names don't begin with 'w' or 'b'
test_5 = {'1a':'bking', '8f':'wking', '1b':'zqueen', '6d': 'wqueen'}
#pieces names
test_6 = {'1a':'bking', '8f':'wking', '1b':'bqueen', '6d': 'wqueen',\
'7b':'wknightt'}
#too many white rooks
test_7 = {'1a':'bking', '8f':'wking', '1b':'bqueen', '6d': 'wqueen', \
'5c': 'wrook', '8c':'wrook', '7d': 'wrook'}
#this board should be valid
test_8 = {'1a':'bking', '8f':'wking', '1b':'bqueen', '6d': 'wqueen', \
'5c': 'wrook'}
Solution 5:[5]
I took a different approach. I decided to compare the proper chess_board with provided test_board.
chess_board = {
"1a": "wrook", "1b": "wknight", "1c": "wbishop", "1d": "wqueen",
"1e": "wking", "1f": "wbishop", "1g": "wknight", "1h": "wrook",
"2a": "wpawn", "2b": "wpawn", "2c": "wpawn", "2d": "wpawn",
"2e": "wpawn", "2f": "wpawn", "2g": "wpawn", "2h": "wpawn",
"8a": "brook", "8b": "bknight", "8c": "bbishop", "8d": "bqueen",
"8e": "bking", "8f": "bbishop", "8g": "bknight", "8h": "brook",
"7a": "bpawn", "7b": "bpawn", "7c": "bpawn", "7d": "bpawn",
"7e": "bpawn", "7f": "bpawn", "7g": "bpawn", "7h": "bpawn",
}
# list keeps broken positions
results_b = []
# TODO: check if figures positions are correct
def isValidChessBoard(board_check):
for key in board_check:
if board_check[key] == chess_board[key]:
# this print is just for visualization
print(f"{key} has a correct value of {chess_board[key]}")
if board_check[key] != chess_board[key]:
# this print is just for visualization
print(f"{key} has broken value of {chess_board[key]}")
results_b.append(chess_board[key])
# print broken positions
for i in results_b:
print(f"Figure {i} is in a bad position.")
test_board = {
"1a": "wrook",
"7h": "wpawn",
"7g": "bpawn",
"1b": "bknight",
}
isValidChessBoard(test_board)
Results:
1a has a correct value of wrook
7h has broken value of bpawn
7g has a correct value of bpawn
1b has broken value of wknight
Figure bpawn is in a bad position.
Figure wknight is in a bad position.
Solution 6:[6]
Since the Chess Dictionary Validator question doesn't require to output the place of the error in the chessboard, so this is my answer:
def valid_chess_board(board):
bpieces, wpieces = 0, 0
pieces = ("king", "queen", "rook", "bishop", "knight", "pawn")
board_pieces = list(board.values())
# Checking the kings
if board_pieces.count("bking") != 1 or board_pieces.count("wking") != 1:
return False
# Checking the pawns
if board_pieces.count("bpawn") > 8 or board_pieces.count("wpawn") > 8:
return False
# Checking the colors
for p in board_pieces:
if p[0] == "b" and p[1:] in pieces:
bpieces += 1
elif p[0] == "w" and p[1:] in pieces:
wpieces += 1
else:
return False
# Checking the pieces
if bpieces > 16 or wpieces > 16:
return False
# Checking the spaces
for s in board:
if s[0] not in "12345678" or s[1] not in "abcdefgh":
return False
return True
chess_board = {
"1a": "wrook",
"2a": "wpawn",
"6a": "bpawn",
"8a": "brook",
"2b": "wpawn",
"5b": "bpawn",
"1c": "wbishop",
"2c": "wbishop",
"3c": "wpawn",
"6c": "bknight",
"7c": "bpawn",
"1d": "wqueen",
"2d": "wknight",
"5d": "bpawn",
"8d": "bqueen",
"6e": "bbishop",
"7e": "bbishop",
"1f": "wrook",
"2f": "wpawn",
"3f": "wknight",
"6f": "bknight",
"8f": "brook",
"1g": "wking",
"2g": "wpawn",
"7g": "bpawn",
"8g": "bking",
"2h": "wpawn",
"7h": "bpawn",
}
print(valid_chess_board(chess_board))
Solution 7:[7]
My solution - I used sets to check for valid spaces but this could be achieved with lists as well.
board = {'1a': 'wrook', '1b': 'wknight', '1c': 'wbishop', '1d': 'wqueen', '1e': 'wking', '1f': 'wbishop',
'1g': 'wknight', '1h': 'wrook','2a': 'wpawn', '2b': 'wpawn', '2c': 'wpawn', '2d': 'wpawn', '2e': 'wpawn',
'2f': 'wpawn', '2g': 'wpawn', '2h': 'wpawn', '3a': '', '3b': '', '3c': '', '3d': '', '3e': '', '3f': '',
'3g': '', '3h': '', '4a': '', '4b': '', '4c': '', '4d': '', '4e': '', '4f': '', '4g': '', '4h': '',
'5a': '', '5b': '', '5c': '', '5d': '', '5e': '', '5f': '', '5g': '', '5h': '',
'6a': '', '6b': '', '6c': '', '6d': '', '6e': '', '6f': '', '6g': '', '6h': '',
'7a': 'bpawn', '7b': 'bpawn', '7c': 'bpawn', '7d': 'bpawn', '7e': 'bpawn', '7f': 'bpawn', '7g': 'bpawn', '7h': 'bpawn',
'8a': 'brook', '8b': 'bknight', '8c': 'bbishop' , '8d': 'bqueen', '8e': 'bking', '8f': 'bbishop',
'8g': 'bknight','8h': 'brook'}
def isValidChessBoard(board_dict):
#check for 1 black king and 1 white king
bking=0
wking=0
for king in board_dict.values():
if king == 'bking':
bking += 1
if king == 'wking':
wking += 1
if bking != 1 or wking != 1:
return False
# check for 8 black pawns and 8 white pawns
bpawn = 0
wpawn = 0
for pawn in board_dict.values():
if pawn == 'bpawn':
bpawn += 1
if pawn == 'wpawn':
wpawn += 1
if wpawn != 8 or wpawn != 8:
return False
#check for valid spaces
valid_spaces = {'1a', '1b', '1c', '1d', '1e', '1f', '1g', '1h','2a', '2b', '2c', '2d', '2e', '2f', '2g', '2h',
'3a', '3b', '3c', '3d', '3e', '3f', '3g', '3h','4a', '4b', '4c', '4d', '4e', '4f', '4g', '4h',
'5a', '5b', '5c', '5d', '5e', '5f', '5g', '5h','6a', '6b', '6c', '6d', '6e', '6f', '6g', '6h',
'7a', '7b', '7c', '7d', '7e', '7f', '7g', '7h','8a', '8b', '8c', '8d', '8e', '8f', '8g', '8h'}
spaces = set()
for i in board_dict.keys():
spaces.add(i) # use set add method (like append for lists)
if spaces != valid_spaces:
return False
#check for 16 pieces per player
piece_count = 0
for piece in board_dict.values():
if piece != '': # don't count the empty spaces (no pieces)
piece_count += 1
if piece_count != 32: # 16 x 2 = 32 total pieces
return False
return 'This is a valid board'
print(isValidChessBoard(board))
Solution 8:[8]
Here is my attempt. I would love to get some feedback from more experienced people.
board_width = ['1', '2', '3', '4', '5', '6', '7', '8']
board_height = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
board = []
for x in board_width: #create a list of possible board positions
for y in board_height:
board.append(x + y)
pieces = ['king', 'queen', 'rook', 'rook',
'bishop', 'bishop', 'knight', 'knight',
'pawn', 'pawn', 'pawn', 'pawn', 'pawn',
'pawn', 'pawn', 'pawn'] #list of all pieces for each player
white_pieces = pieces.copy()
black_pieces = pieces.copy()
def is_valid_chess_board(chess_dict):
if 'wking' and 'bking' in chess_dict.values():
for key, value in chess_dict.items(): #iterate each dict elements
if value == '':
board.remove(key)
elif value.startswith('w') and key in board:
lis_val = list(value)
lis_val.remove('w')
val_str = "".join(lis_val)
if val_str in white_pieces:
white_pieces.remove(val_str)
board.remove(key)
print(f"The White {val_str} was placed at {key}")
else:
print(f"This {val_str} is not a proper Chess piece")
elif value.startswith('b') and key in board:
lis_val = list(value)
lis_val.remove('b')
val_str = "".join(lis_val)
if val_str in black_pieces:
black_pieces.remove(val_str)
board.remove(key)
print(f"The Black {val_str} was placed at {key}")
else:
print(f"This {val_str} is not a proper Chess piece")
else:
print("You have an incomplete Chess board")
break
else:
print("You have an incomplete Chess board!")
print(board)
Solution 9:[9]
def isValid(board):
# PUT TOGETHER A LIST OF ALL POSSIBLE PIECES
pieces = ['king', 'queen', 'rook', 'knight', 'bishop', 'pawn']
colors = ['b', 'w']
all_pieces = {}
possible_pieces = ['']
color_count = {'b': 0, 'w': 0}
for piece in pieces:
for color in colors:
possible_pieces.append('{}{}'.format(color, piece))
all_pieces.setdefault('{}{}'.format(color, piece), 0)
# CHECKS IF PIECES HAVE VALID NAMES
for v in board.values():
if v not in possible_pieces:
print('Error: Invalid chess piece type')
return False
# ITERATE THROUGH BOARD, AND COUNT PIECES AND COLORS
for k in board:
if board.get(k) == '':
continue
all_pieces[board.get(k)] += 1 # INCREASE PIECE TYPE
color_count[board.get(k)[0]] += 1 # INCREASE COLOR COUNT
# CHECK TOTAL WHITE/BLACK PIECES
if color_count['w'] > 16 or color_count['b'] > 16:
print('Error: Invalid number of white or black pieces')
return False
# CHECKS IF VALID NUMBER OF PIECES
for i in possible_pieces:
num = all_pieces.get(i)
if i == 'bking' or i == 'wking':
if num != 1:
print('Error: Invalid number of Kings')
return False
elif i == 'bqueen' or i == 'wqueen':
if num > 1:
print('Error: Invalid number of Queens')
return False
elif i == 'brook' or i == 'wrook':
if num > 2:
print('Error: Invalid number of Rooks')
return False
elif i == 'bknight' or i == 'wknight':
if num > 2:
print('Error: Invalid number of Knights')
return False
elif i == 'bbishop' or i == 'wbishop':
if num > 2:
print('Error: Invalid number of Bishops')
return False
elif i == 'bpawn' or i == 'wpawn':
if num > 8:
print('Error: Invalid number of Pawns')
return False
# CHECK ALL VALID SPACES
for s in board:
if s[0] not in '12345678' or s[1] not in 'abcdefgh':
print('Error: Space is not valid!')
return False
# IF PASS ALL CHECKS, THE BOARD IS VALID
return True
Solution 10:[10]
You guys are not following the book. You guys are writing codes that would confuse even the greatest expert or even the author himself. All the hints to write this code is in the book. This means you guys didn't read the book. If you read it, you wouldn't be making all these mistakes in your code. Please find the final answer below, it's simple and efficient and better than all the code you guys posted in this thread:
def isValidChessBoard(board):
board = {'1a': 'brook', '1b': 'bknight', '1c': 'bbishop', '1d': 'bking', '1e': 'bqueen', '1f': 'bbishop',
'1g': 'bknight', '1h': 'brook',
'2a': 'bpawn', '2b': 'bpawn', '2c': 'bpawn', '2d': 'bpawn', '2e': 'bpawn', '2f': 'bpawn',
'2g': 'bpawn', '2h': 'bpawn',
'3a': '', '3b': '', '3c': '', '3d': '', '3e': '', '3f': '',
'3g': '', '3h': '',
'4a': '', '4b': '', '4c': '', '4d': '', '4e': '', '4f': '',
'4g': '', '4h': '',
'5a': '', '5b': '', '5c': '', '5d': '', '5e': '', '5f': '',
'5g': '', '5h': '',
'6a': '', '6b': '', '6c': '', '6d': '', '6e': '', '6f': '',
'6g': '', '6h': '',
'7a': 'wpawn', '7b': 'wpawn', '7c': 'wpawn', '7d': 'wpawn', '7e': 'wpawn', '7f': 'wpawn',
'7g': 'wpawn', '7h': 'wpawn',
'8a': 'wrook', '8b': 'wknight', '8c': 'wbishop', '8d': 'wking', '8e': 'wqueen', '8f': 'wbishop',
'8g': 'wknight', '8h': 'wrook'
}
# Criteria 1 - 1 bbking and 1 wking
count = {}
for v in board.values():
count.setdefault(v, 0)
count[v] = count[v] + 1
# print(count)
# Criteria 2 - Each player can have at most 16 pieces, at most 8 pawns
del count['']
#print(count)
pieces = 0
for v in count.values():
pieces = pieces + v
#print(pieces)
# Criteria 3 - All pieces must be on a valid space '1a' to '8h', not '9z'
validSpace = {'1a': 'brook', '1b': 'bknight', '1c': 'bbishop', '1d': 'bking', '1e': 'bqueen', '1f': 'bbishop',
'1g': 'bknight', '1h': 'brook',
'2a': 'bpawn', '2b': 'bpawn', '2c': 'bpawn', '2d': 'bpawn', '2e': 'bpawn', '2f': 'bpawn',
'2g': 'bpawn', '2h': 'bpawn',
'3a': '', '3b': '', '3c': '', '3d': '', '3e': '', '3f': '',
'3g': '', '3h': '',
'4a': '', '4b': '', '4c': '', '4d': '', '4e': '', '4f': '',
'4g': '', '4h': '',
'5a': '', '5b': '', '5c': '', '5d': '', '5e': '', '5f': '',
'5g': '', '5h': '',
'6a': '', '6b': '', '6c': '', '6d': '', '6e': '', '6f': '',
'6g': '', '6h': '',
'7a': 'wpawn', '7b': 'wpawn', '7c': 'wpawn', '7d': 'wpawn', '7e': 'wpawn', '7f': 'wpawn',
'7g': 'wpawn', '7h': 'wpawn',
'8a': 'wrook', '8b': 'wknight', '8c': 'wbishop', '8d': 'wking', '8e': 'wqueen', '8f': 'wbishop',
'8g': 'wknight', '8h': 'wrook'
}
if count['bking'] == 1:
if count['wking'] == 1:
if pieces == 32:
if count['bpawn'] == 8:
if count['wpawn'] == 8:
if board == validSpace:
#return 'True: This is a Vaild Chessboard'
return True
chessBoardOne = {'1a': 'wrook', '1b': 'wknight', '1c': 'wbishop', '1d': 'wqueen', '1e': 'wking', '1f': 'wbishop',
'1g': 'wknight', '1h': 'wrook','2a': 'wpawn', '2b': 'wpawn', '2c': 'wpawn', '2d': 'wpawn', '2e': 'wpawn',
'2f': 'wpawn', '2g': 'wpawn', '2h': 'wpawn', '3a': '', '3b': '', '3c': '', '3d': '', '3e': '', '3f': '',
'3g': '', '3h': '', '4a': '', '4b': '', '4c': '', '4d': '', '4e': '', '4f': '', '4g': '', '4h': '',
'5a': '', '5b': '', '5c': '', '5d': '', '5e': '', '5f': '', '5g': '', '5h': '',
'6a': '', '6b': '', '6c': '', '6d': '', '6e': '', '6f': '', '6g': '', '6h': '',
'7a': 'bpawn', '7b': 'bpawn', '7c': 'bpawn', '7d': 'bpawn', '7e': 'bpawn', '7f': 'bpawn', '7g': 'bpawn', '7h': 'bpawn',
'8a': 'brook', '8b': 'bknight', '8c': 'bbishop' , '8d': 'bqueen', '8e': 'bking', '8f': 'bbishop',
'8g': 'bknight','8h': 'brook'}
print(isValidChessBoard(chessBoardOne))
#print(Answer)
Solution 11:[11]
def isValidChessBoard(board): board = {'1a': board['1a'], '1b': board['1b'] , '1c': board['1c'], '1d': board['1d'], '1e': board['1e'], '1f': board['1f'], '1g': board['1g'], '1h': board['1h'], '2a': board['2a'], '2b': board['2b'], '2c': board['2c'], '2d': board['2d'], '2e': board['2e'], '2f': board['2f'], '2g': board['2g'], '2h': board['2h'], '3a': board['3a'], '3b': board['3b'], '3c': board['3c'], '3d': board['3d'], '3e': board['3e'], '3f': board['3f'], '3g': board['3g'], '3h': board['3h'], '4a': board['4a'], '4b': board['4b'], '4c': board['4c'], '4d': board['4d'], '4e': board['4e'], '4f': board['4f'], '4g': board['4g'], '4h': board['4h'], '5a': board['5a'], '5b': board['5b'], '5c': board['5c'], '5d': board['5d'], '5e': board['5e'], '5f': board['5f'], '5g': board['5g'], '5h': board['5h'], '6a': board['6a'], '6b': board['6b'], '6c': board['6c'], '6d': board['6d'], '6e': board['6e'], '6f': board['6f'], '6g': board['6g'], '6h': board['6h'], '7a': board['7a'], '7b': board['7b'], '7c': board['7c'], '7d': board['7d'], '7e': board['7e'], '7f': board['7f'], '7g': board['7g'], '7h': board['7h'], '8a': board['8a'], '8b': board['8b'], '8c': board['8c'], '8d': board['8d'], '8e': board['8e'], '8f': board['8f'], '8g': board['8g'], '8h': board['8h']} # Criteria 1 - 1 bbking and 1 wking
count = {}
for v in board.values():
count.setdefault(v, 0)
count[v] = count[v] + 1
print(count)
# Criteria 2 - Each player can have at most 16 pieces, at most 8 pawns
del count['']
#print(count)
pieces = 0
for v in count.values():
pieces = pieces + v
#print(pieces)
# Criteria 3 and 4 - All pieces must be on a valid space '1a' to '8h', not '9z'. Names must start with w or b.
validSpace = {'1a': 'brook', '1b': 'bknight', '1c': 'bbishop', '1d': 'bking', '1e': 'bqueen', '1f': 'bbishop',
'1g': 'bknight', '1h': 'brook',
'2a': 'bpawn', '2b': 'bpawn', '2c': 'bpawn', '2d': 'bpawn', '2e': 'bpawn', '2f': 'bpawn',
'2g': 'bpawn', '2h': 'bpawn',
'3a': '', '3b': '', '3c': '', '3d': '', '3e': '', '3f': '',
'3g': '', '3h': '',
'4a': '', '4b': '', '4c': '', '4d': '', '4e': '', '4f': '',
'4g': '', '4h': '',
'5a': '', '5b': '', '5c': '', '5d': '', '5e': '', '5f': '',
'5g': '', '5h': '',
'6a': '', '6b': '', '6c': '', '6d': '', '6e': '', '6f': '',
'6g': '', '6h': '',
'7a': 'wpawn', '7b': 'wpawn', '7c': 'wpawn', '7d': 'wpawn', '7e': 'wpawn', '7f': 'wpawn',
'7g': 'wpawn', '7h': 'wpawn',
'8a': 'wrook', '8b': 'wknight', '8c': 'wbishop', '8d': 'wking', '8e': 'wqueen', '8f': 'wbishop',
'8g': 'wknight', '8h': 'wrook'
}
print(count['bking'])
print(count['bpawn'])
if count['bking'] == 1:
if count['wking'] == 1:
if pieces == 32:
if count['bpawn'] == 8:
if count['wpawn'] == 8:
if board == validSpace:
return True
chessBoardOne = {'1a': 'brook', '1b': 'bknight', '1c': 'bbishop', '1d': 'bking', '1e': 'bqueen', '1f': 'bbishop', '1g': 'bknight', '1h': 'brook', '2a': 'bpawn', '2b': 'bpawn', '2c': 'bpawn', '2d': 'bpawn', '2e': 'bpawn', '2f': 'bpawn', '2g': 'bpawn', '2h': 'bpawn', '3a': '', '3b': '', '3c': '', '3d': '', '3e': '', '3f': '', '3g': '', '3h': '', '4a': '', '4b': '', '4c': '', '4d': '', '4e': '', '4f': '', '4g': '', '4h': '', '5a': '', '5b': '', '5c': '', '5d': '', '5e': '', '5f': '', '5g': '', '5h': '', '6a': '', '6b': '', '6c': '', '6d': '', '6e': '', '6f': '', '6g': '', '6h': '', '7a': 'wpawn', '7b': 'wpawn', '7c': 'wpawn', '7d': 'wpawn', '7e': 'wpawn', '7f': 'wpawn', '7g': 'wpawn', '7h': 'wpawn', '8a': 'wrook', '8b': 'wknight', '8c': 'wbishop', '8d': 'wking', '8e': 'wqueen', '8f': 'wbishop', '8g': 'wknight', '8h': 'wrook' }
print(isValidChessBoard(chessBoardOne)) #print(Answer)
Solution 12:[12]
piece = {}
# enter chess piece and position
def pieceSet():
while True:
print("Enter chess piece: (start with 'b' or 'w' + piece) or enter 'q' to exit")
pc = str(input())
if pc == 'q':
break
print("Place the piece on the chess board: ")
position = str(input())
piece[str(position)] = str(pc)
def isValidChessBoard():
# board position and coordinates
board = []
for row in range(1, 9):
for col in ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'):
board.append(str(row)+str(col))
# check if both kings are still on the board
if 'wking' not in piece.values() or 'bking' not in piece.values():
print('---The Board is Invalid!---')
print("King is not on the board!")
return False
# check the position of every piece on the board
for key in piece.keys():
if key not in board:
print('---The Board is Invalid!---')
print("Chess Board only has 8 boxes per row ('a' to 'h') and 8 boxes percolumn ('1 to 8')")
return False
# check if the name starts with a "w" or "b"
for pieces in piece.values():
if pieces[0] != "b" and pieces[0] != "w":
print('---The Board is Invalid!---')
print("Chess pieces only have 2 colors: (b)lack and (w)hite")
return False
# check the quantity of every chess pieces and see if every piece is valid
bpawn = 0
wpawn = 0
bking = 0
wking = 0
bqueen = 0
wqueen = 0
bbishop = 0
wbishop = 0
bknight = 0
wknight = 0
brook = 0
wrook = 0
for value in piece.values():
if value == 'bpawn':
bpawn += 1
if bpawn > 8:
print('---The Board is Invalid!---')
print("Exceeded the limit of bpawn!")
return False
else:
continue
elif value == 'wpawn':
wpawn += 1
if wpawn > 8:
print('---The Board is Invalid!---')
print("Exceeded the limit of wpawn!")
return False
else:
continue
elif value == 'bking':
bking += 1
if bking > 1:
print('---The Board is Invalid!---')
print("Exceeded the limit of bking!")
return False
else:
continue
elif value == 'wking':
wking += 1
if wking > 1:
print('---The Board is Invalid!---')
print("Exceeded the limit of wking!")
return False
else:
continue
elif value == 'bqueen':
bqueen += 1
if bqueen > 1:
print('---The Board is Invalid!---')
print("Exceeded the limit of bqueen!")
return False
else:
continue
elif value == 'wqueen':
wqueen += 1
if wqueen > 1:
print('---The Board is Invalid!---')
print("Exceeded the limit of wqueen!")
return False
else:
continue
elif value == 'bbishop':
bbishop += 1
if bbishop > 2:
print('---The Board is Invalid!---')
print("Exceeded the limit of bbishop!")
return False
else:
continue
elif value == 'wbishop':
wbishop += 1
if wbishop > 2:
print('---The Board is Invalid!---')
print("Exceeded the limit of wbishop!")
return False
else:
continue
elif value == 'bknight':
bknight += 1
if bknight > 2:
print('---The Board is Invalid!---')
print("Exceeded the limit of bknight!")
return False
else:
continue
elif value == 'wknight':
wknight += 1
if wknight > 2:
print('---The Board is Invalid!---')
print("Exceeded the limit of wknight!")
return False
else:
continue
elif value == 'brook':
brook += 1
if brook > 2:
print('---The Board is Invalid!---')
print("Exceeded the limit of brook!")
return False
else:
continue
elif value == 'wrook':
wrook += 1
if wrook > 2:
print('---The Board is Invalid!---')
print("Exceeded the limit of wrook!")
return False
else:
continue
else:
print('---The Board is Invalid!---')
print(str(value) + " piece not included!")
return False
def result():
if isValidChessBoard() == False:
return False
else:
print('---The Board is Valid!---')
return True
pieceSet()
print('piece =', piece)
print(result())
Solution 13:[13]
#validate chess board
dict_chess ={'1a':'bking', '8f':'wking', '1b':'bqueen', '6d': 'wqueen', \
'5c': 'wrook'}
chessHeightLocation = ['a','b','c','d','e','f','g','h']
chessWidthLocation = [1, 2, 3, 4, 5, 6, 7, 8]
colors = ['w', 'b']
pieces = ['pawn', 'knight', 'bishop', 'rook', 'queen', 'king']
def isValidChessBoard(dictChess):
playerCount = {'bpawn': 0, 'wpawn': 0, 'wking': 0, 'bking': 0, 'wpieceCount': 0, 'bpieceCount': 0}
for keysInChessBoard in dictChess:
#check for Space
#print(int(keysInChessBoard[0]) not in chessWidthLocation)
if (int(keysInChessBoard[0]) not in chessWidthLocation) or (keysInChessBoard[1] not in chessHeightLocation):
print('Not valid space: ' + keysInChessBoard)
return False
#check for black and white
if dictChess[keysInChessBoard][0] not in colors:
print('Not valid color of piece should have b for black or w for white: ' + dictChess[keysInChessBoard])
return False
#check for piece
if dictChess[keysInChessBoard][1:] not in pieces:
print('Not valid piece: ' + dictChess[keysInChessBoard])
return False
#check for pawns
if dictChess[keysInChessBoard] == 'bpawn' or dictChess[keysInChessBoard] == 'wpawn':
playerCount[dictChess[keysInChessBoard]] += 1
if playerCount[dictChess[keysInChessBoard]] > 8:
print('More than 8 pawns in one player')
return False
#check for king
if dictChess[keysInChessBoard] == 'bking' or dictChess[keysInChessBoard] == 'wking':
playerCount[dictChess[keysInChessBoard]] += 1
if playerCount[dictChess[keysInChessBoard]] > 1:
print('More than 1 king')
return False
#pieceCount
if dictChess[keysInChessBoard][0] in colors:
if dictChess[keysInChessBoard][0] == 'w':
playerCount[dictChess[keysInChessBoard][0]+'pieceCount'] += 1
elif dictChess[keysInChessBoard][0] == 'b':
playerCount[dictChess[keysInChessBoard][0]+'pieceCount'] += 1
if playerCount[dictChess[keysInChessBoard][0]+'pieceCount'] > 16:
print('More than 16 piece')
return False
#print(playerCount)
return True
print(isValidChessBoard(dict_chess))
Solution 14:[14]
just another option
```
chessboard = {'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': '', }
def check_location(board):
for location in board.keys():
row = int(location[:1])
column = location[1:]
if not ((1 <= row <= 8) and ('a' <= column <= "h")):
print(f"Invalid to have {board[location]} at postion {location}")
return False
def check_piece_count(board):
pieces = ['wpawn', 'bpawn', 'wknight', 'bknight', 'bbishop',
'wbishop', 'wrook', 'brook', 'wqueen', 'bqueen', 'wking', 'bking']
max_pieces = [8, 8, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1]
for piece in zip(pieces, max_pieces, board.keys()):
if sum(value == piece[0] for value in board.values()) > piece[1]:
return False
return True
if check_location(chessboard) == None and check_piece_count(chessboard) == True:
print(True)
else:
print(False)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
