Jerome Palayoor

Contact
A completed Sudoku puzzle showing the Solved label and final time

Sudoku

A Sudoku game that generates a fresh, playable puzzle every time

Generating a solvable puzzle

Every puzzle starts from an empty board. The generator drops 15 random valid numbers onto it, then hands the rest to a backtracking solver to fill in a complete, valid solution.

def solve(bo):
    find = find_empty(bo)
    if not find:
        return True
    else:
        x, y = find

    for i in range(1,10):
        if valid(bo, i, (x, y)):
            bo[y][x] = i

            if solve(bo):
                return True

            bo[y][x] = 0

    return False

This is classic backtracking, try a number, if it leads somewhere impossible later, undo it and try the next one. Once a full solution exists, 60 of its 81 cells get cleared at random to become the actual puzzle.

A freshly generated Sudoku puzzle with the top-left cell selected

Checking a move

The same valid() function that builds the solution also checks your own entries live, no duplicate in the row, column, or 3x3 box.

def valid(bo, num, pos):
    for i in range(len(bo[0])):
        if bo[pos[1]][i] == num and pos[0] != i:
            return False

    for i in range(len(bo)):
        if bo[i][pos[0]] == num and pos[1] != i:
            return False

    box_x = pos[0] // 3
    box_y = pos[1] // 3

    for i in range(box_y*3, box_y*3 + 3):
        for j in range(box_x * 3, box_x*3 + 3):
            if bo[i][j] == num and pos != [j,i]:
                return False

    return True

Type a number and it turns green if it's a legal placement, red if it conflicts with something already on the board.

A Sudoku puzzle partway through, showing valid entries in green and invalid entries in red

Highlighting

Beyond just the selected cell, its whole row, column, and 3x3 box get a light grey highlight, and separately, every other cell sharing the same number gets a darker grey highlight of its own.

if (i == pos[0]) or (j == pos[1]) or ((i//3 == pos[0]//3) and (j//3 == pos[1]//3)):
    pygame.draw.rect(win,(222,222,222),(i*size,j*size,size,size))

if ((check[j][i] == check[pos[1]][pos[0]]) and check[j][i] != 0):
    pygame.draw.rect(win,(150,150,150),(i*size,j*size,size,size))
A Sudoku puzzle showing every cell containing the number 3 highlighted in grey

Solving and generating

Pressing S instantly reveals the full solution, pressing Space throws away the current puzzle and generates a brand new one, with the timer resetting to zero either way.

A completed Sudoku puzzle showing the Solved label and final time

Contact Me