Displaying a Sudoku Board For my programming class, we have been tasked with creating a Sudoku solver; the first step of the project was to create a program which would display the game board based on input provided by the user. 

import math #To be used later


def board_filler():
    """Creates the sudoku board from user input"""
    board = [[], [], [], [], [], [], [], [], [], [], []]
    for x in enumerate(board):
        #If it is one of the rows that have lines, add them
        if ((x[0] + 1) % 4) == 0:
           for y in range(11):
               board[x[0]].append("-")
        else:
            for y in range(11):
                #If it is a column that has lines in it, add them
                if ((y + 1) % 4) == 0:
                    board[x[0]].append("|")
                else:
                    #Repeat until an inout has been entered
                    z = True
                    while z:
                        z = False
                        if x[0] &gt; 7:
                            xRead = x[0] - 1
                        elif x[0] &gt; 3:
                            xRead = x[0]
                        else:
                            xRead = x[0] + 1
                        if y &gt; 7:
                            yRead = y - 1
                        elif y &gt; 3:
                            yRead = y
                        else:
                            yRead = y + 1
                        number = input("Please enter a number for the square in column %s and in row %s, if there is no number, just hit enter:" %(xRead, yRead))
                        #Trys to make it a number, then checks to see if it is a number 1 to 9
                        try:
                            number = int(number)
                            if number &gt; 9 or number &lt; 1:
                                z = True
                                print("Please enter a number between 1 and 9")
                            else:
                                board[x[0]].append(number)
                        #If it is not a number, check if its empty
                        except (TypeError, ValueError):
                            #If its empty, add a space
                            if len(number) == 0:
                                board[x[0]].append(" ")
                            #If not ask for a number
                            else:
                                z = True
                                print("Please enter a number")
    return board

def board_printer(board):
    """Prints the sudoku board"""
    #Turns board into str to make the .join work
    for x in enumerate(board):
        for y in enumerate(board):
            board[x[0]][y[0]] = str(board[x[0]][y[0]])
    #Prints the board
    for x in enumerate(board):
        print(" ".join(board[x[0]]))


board_printer(board_filler())


A few notes for review:


The board_filler function feels quite bloated.
I don't like the way I implemented xRead and yRead.


How can I improve my code?
First of all, let the code speak! Don't unnecessarily add comments unless they are explaining a really complicated piece of code.

Basic definitions:

A magic number is defined to be:


  Unique values with unexplained meaning or multiple occurrences which could (preferably) be replaced with named constants


Can you find the magic numbers in your code?
Yes that's right, the culprits are 11 and 4.

Let's just define variables for those!

ROWS = 11
COLS = 11
GRID_ROWS = 4
GRID_COLS = 4


Next, let's replace every magic number with the appropriate variable!

Making the code shorter!

Function board_printer

Why use enumerate? Why make everything a str?

Your whole function can just be rewritten as the following:

def board_printer(board):
    """Prints the sudoku board"""

    for row in board:
        print(*row)


Function board_filler

You don't need to use for x in enumerate(board) at all!
Just use for x in range(ROWS) and change every instance of x[0] to x accordingly



Instead of 

if ((x[0] + 1) % GRID_ROWS) == 0:
    for y in range(11):
        board[x].append("-")


Use

if ((x[0] + 1) % GRID_ROWS) == 0:
    board[x] = ["-"] * COLS




Use formatting!  

for taking input of number, use number = input("Please enter a number for the square in row {xRead} and in column {yRead} (hit enter for no number): ") instead of using %s



Why use a dummy variable z?

Just do:

while True:
    number = input("Please enter a number for the square in column {x[0] + 1} and in row {y + 1} (hit enter for no number): ")

    try:
        number = int(number)

        if number &gt; 9 or number &lt; 1:
            raise ValueError
        else:
            board[x].append(number)

        break

    except (TypeError, ValueError):
        if not number:
            board[x].append(" ")
        else:
            print("Please enter an integer between 1 and 9")


Essentially, it tries to take an input, check if the value is an integer between 1 and 9, else raises an exception. If the number was indeed valid, it makes it to the end of the try statement, which causes the loop to break

Misc


Run board_printer(board_filler()) inside if __name__ == __main__:. This causes board_printer(board_filler()) not to run if it was imported from another module.
Try using list(map(int, input(f'Enter {COLS - (COLS // GRID_COLS)} space separated integers: ').split())) for each row. It is tiring to fill every single cell by hand! So ask input for a whole row. It's your personal preference though!


Hope this helps!

EDIT:

This part is to solely dedicated to removing xRead and yRead and is not related to the above improvements

First we have to change
ROWS = COLS = 11 to ROWS = COLS = 9 and
GRID_ROWS = GRID_COLS = 4 to GRID_ROWS = GRID_COLS = 3

Do not append - or | to board at all!

Just remove all statements that append - or | and also remove xRead and yRead. Now, the board would look like a sudoku board without - or |



In the board_filler use

def board_printer(board):
    """Prints the sudoku board"""

    for row in range(ROWS):
        s = ''

        for col in range(COLS):
            s += str(board[row][col]) + ' '

            if not (col + 1) % GRID_COLS:
                s += '| '

        print(s)

        if not (row + 1) % GRID_ROWS:
            print('-' * len(s))


This will print - or | according to the row or column!



Final code including all above mentioned improvements


ROWS = COLS = 9
GRID_ROWS = GRID_COLS = 3

def board_filler():
    """Creates the sudoku board from user input"""

    board = [[] for _ in range(ROWS)]

    for x in range(ROWS):
        for y in range(COLS):
            while True:
                number = input(f"Please enter an integer for the square in column {x + 1} and in row {y + 1} (hit enter for no number): ")

                try:
                    number = int(number)

                    if number &gt; 9 or number &lt; 1:
                        raise ValueError
                    else:
                        board[x].append(number)

                    break

                except (TypeError, ValueError):
                    if not number:
                        board[x].append(" ")
                    else:
                        print("Please enter an integer between 1 and 9")

    return board

def board_printer(board):
    """Prints the sudoku board"""

    print()

    for row in range(ROWS):
        s = ''

        for col in range(COLS):
            s += str(board[row][col]) + ' '

            if not (col + 1) % GRID_COLS:
                s += '| '

        s = s[:-1] # Removes trailing space

        print(s)

        if not (row + 1) % GRID_ROWS:
            print('-' * len(s))

if __name__ == '__main__':
    board_printer(board_filler())


NOTE: board_filler doesn't look as bloated either! The code kills 2 birds with one stone!