0

I'm relatively new to coding, so any criticism is appreciated. I just finished chapter 5 of Automate the Boring Stuff and started the practice projects of the chapter. I've looked at other codes on the same project to see their takes on it, and to see how I can do it. But the code keeps returning False as the value, and I'm not sure where the issue is.

import string

chessboard = {'1h': 'bking', '6c': 'wqueen', '2g': 'bbishop', '5h': 'bqueen', '3e': 'wking'}

def isValidChessBoard(chessboard):

    # Define the components 
    bpieces, wpieces = 0, 0
    bking, wking, bpawn, wpawn = 0, 0, 0, 0
    valid = True
    coord = True
    
    # Check if board has exactly 1 black and white king.
    if bking and wking != 1:
        valid = False
    
    # Check if there are at most 16 pieces, at most 8 pawns, and must be within '1a' and '8h'. 
    if bpieces or wpieces > 16:
        valid = False
    if bpawn or wpawn > 8: 
        valid = False
    
    for x in range(1,9):
        for y in list(map(chr,range(ord('a'), ord('h')+1))):
            coord = True
    
    # Check if the pieces begins with 'b' or 'w'; followed by 'pawn', 'knight', 'bishop', 'rook', 'queen' or 'king'.
    for piece in chessboard.values():
    
        if piece != 'b' or 'w' + 'pawn' or 'knight' or 'bishop' or 'rook' or 'queen' or 'king':
            valid = False
    
    if valid and coord:
        return True
    else:
        return False
    
print(isValidChessBoard(chessboard))

I think the issue is around here:

if piece != 'b' or 'w' + 'pawn' or 'knight' or 'bishop' or 'rook' or 'queen' or 'king': 
    valid = False

But I'm not sure, with how little experience I have with codes.

Nipuna Upeksha
  • 348
  • 3
  • 15
  • Step through it or introduce breakpoints and then examine the variable values – Bradley Thomas Apr 03 '22 at 13:22
  • `if bking and wking != 1` means `if (bking and wking) != 1`, which is not what you intended. You need to do `if bking != -1 and wking != 1`. Similar for all other boolean operators you've used – Pranav Hosangadi Apr 03 '22 at 13:22
  • Try to do intermediate debugging prints, e.g. `print(bking and wking != 1)` – Alexey S. Larionov Apr 03 '22 at 13:22
  • 1
    Try searching with `python if multiple conditions site:stackoverflow.com` - I'm sure you will find Q&A's addressing at least part of your problem. If you find one that solves your problem let us know and we will mark this as a duplicate. – wwii Apr 03 '22 at 13:33
  • 1
    Does this answer your question? [How to test multiple variables for equality against a single value?](https://stackoverflow.com/questions/15112125/how-to-test-multiple-variables-for-equality-against-a-single-value) – Nick is tired Apr 03 '22 at 13:35
  • [Formatting help](https://stackoverflow.com/editing-help)... [Formatting sandbox](https://meta.stackexchange.com/questions/3122/formatting-sandbox) – wwii Apr 03 '22 at 13:35

1 Answers1

1

The value False comes because your chessboard is not getting checked for its pieces and your default values for bpieces and wpieces are 0 and the default values for bking, wking, bpawn and wpawn are 0. And some of your checks are getting overridden in later checks. This is a plausible code snippet I came up with. I hope you can improve it.

import string
from collections import Counter

chessboard = {'1h': 'bking', '6c': 'wqueen', '2g': 'bbishop', '5h': 'bqueen', '3e': 'wking'}

def isValidChessBoard(chessboard):

    # count the number of pieces in board
    res = dict(Counter(chessboard.values()))
    
    # Define the components 
    bpieces, wpieces = sum([v for k,v in res.items() if k[0]=='b']), sum([v for k,v in res.items() if k[0]=='w'])
    bking, wking, bpawn, wpawn = res['bking'] if 'bking' in res.keys() else 0, res['wking'] if 'wking' in res.keys() else 0, res['bpawn'] if 'bpawn' in res.keys() else 0, res['wpawn'] if 'wpawn' in res.keys() else 0
    
    # Check if board has exactly 1 black and white king.
    if bking !=1 or wking != 1:
        return False
    
    # Check if there are at most 16 pieces, at most 8 pawns, and must be within '1a' and '8h'. 
    if bpieces > 16 or wpieces > 16:
        return False
    if bpawn > 8 or wpawn > 8: 
        return False
    
    for pos in chessboard.keys():
        if pos[0] not in range(0,9) and pos[1] not in ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']:
            return False
    
    # Check if the pieces begins with 'b' or 'w'; followed by 'pawn', 'knight', 'bishop', 'rook', 'queen' or 'king'.
    pieces_list = ['king', 'queen', 'pawn', 'knight', 'bishop', 'rook']
    for piece in chessboard.values():
        if (piece[0] != 'b' or piece[0]!='w') and piece[1:] not in pieces_list:
            return False
    
    return True
    
print(isValidChessBoard(chessboard))
Nipuna Upeksha
  • 348
  • 3
  • 15
  • Can you explain what the Counter module does? I haven't gotten to know a lot of modules yet. – Hakunok Apr 03 '22 at 16:06
  • Basically it is for counting as the name implies. Here, it is used to count the certain values present in the `dictionary`. Say we have `{‘h2’:’wpawn’, ‘g2’:’wpawn’}` then it counts the number of `wpawns` present in the dictionary, in this case its 2. – Nipuna Upeksha Apr 03 '22 at 16:12
  • Thank you for the explanation. Might I ask if there's a way to access the number of pieces without using the Counter module as a beginner? – Hakunok Apr 03 '22 at 16:25
  • You can use loops and store them inside another dictionary. Something like this, `{‘wpawn’:2, ‘bking’:1}` – Nipuna Upeksha Apr 03 '22 at 16:26
  • Correct me if I'm wrong, but shouldn't the first k[0] == 'b' instead? because we're setting values of the bpieces first. – Hakunok Apr 04 '22 at 03:13
  • Yes. My mistake. Fixed it. Thanks for noting it. – Nipuna Upeksha Apr 04 '22 at 03:26