pythonnested-lists

Any way to check if a number is already within a 3x3 grid in a 9x9 grid of nested lists?


Programming a sudoku game and I've got a nested list acting as my board and the logic written out however I am stumped on how to check if a number is specifically within a 3x3 grid within the 9x9 nested list board I've got


#board initilization
board = [
 [0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 2, 0, 0, 0, 0, 0, 0, 2],
 [0, 0, 0, 3, 0, 3, 0, 0, 0],
 [0, 0, 5, 0, 0, 0, 0, 0, 0],
 [0, 8, 0, 0, 0, 6, 0, 5, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 2, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 9, 0],
 [0, 0, 0, 1, 0, 0, 0, 0, 0]
]

#main game logic
    #list printing logic and collecting user inputs
while True:
    print("Welcome to the Python Sudoku")
    print("Here's your board")
    for row in board:
        print(row)
    print("You will have a choice to which row you choose and which column you choose")
    print("You will also have a choice of number you wish to input")
    rowchoice = int(input("Please pick the row you wish to add the number to 0-8 where 0 is the first row"))
        #error handling to handle invalid inputs nested in to check after each input
    if rowchoice > 8:
        print("Invalid number, try again")
        continue
    if rowchoice < 0:
        print("Invalid number, try that again")
        continue
    columnchoice = int(input("Please pick the column of choice 0-8 where 0 is the first column"))
    if columnchoice > 8:
        print("Invalid number try again")
        continue
    if columnchoice < 0:
        print("Invalid number try again")
        continue
    guess = int(input("Please pick the sudoku guess number 1-9"))
    if guess > 9:
        print("Invalid number, try again.")
        continue
    if guess < 0:
        print("Invalid number, try again")
        continue
    #adding user guess to user choice
    board[rowchoice][columnchoice] = guess
    #printing new updated board
    for row in board:
        print(board)

    






Thought of trying a check if its in one of the lists but I don't think that will work as each list is not a 3x3 grid

Also would be greatly appreciated if functions are not used as I am required not to use them for this sudoku game, thanks!


Solution

  • First you just need a given cell (row,col) which is the top left corner (the start) of the 3x3 subgrid you are trying to check:

    start_row = (row // 3) * 3
    start_col = (col // 3) * 3
    

    Then simply iterate through the 3x3 subgrid.

    Function implementation:

    def is_valid_move(board, row, col, num):
        # Check row and column
        if num in board[row] or any(board[i][col] == num for i in range(9)):
            return False
        
        # Determine the top-left corner of the 3x3 subgrid
        start_row, start_col = 3 * (row // 3), 3 * (col // 3)
        
        # Check the 3x3 subgrid
        for r in range(start_row, start_row + 3):
            if num in board[r][start_col:start_col + 3]:
                return False
        return True
    

    Add this:

    # Main Game Loop
    while True:
    
    ...
            if is_valid_move(board, row, col, num):
                board[row][col] = num
                print(f"Placed {num} at ({row}, {col}).")
            else:
                print("Invalid move. Number conflicts with existing ones.")
            
    ...
    

    Non Function implementation (requested in comment as additional requirement)

    Instead of adding a function you can just add the same logic into the main loop itself.

            # Subgrid Check
            start_row = (rowchoice // 3) * 3
            start_col = (columnchoice // 3) * 3
            subgrid_valid = True
            for r in range(start_row, start_row + 3):
                for c in range(start_col, start_col + 3):
                    if board[r][c] == guess:
                        subgrid_valid = False
                        break
                if not subgrid_valid:
                    break
            if not subgrid_valid:
                print("Number  already exists in the 3x3 subgrid.")
                continue