Building a Sudoku Checker in JavaScript

Sudoku is a fascinating puzzle that challenges our logic and problem-solving skills. Building a Sudoku checker can be an exciting project for developers looking to sharpen their JavaScript abilities and enhance their understanding of algorithms. In this tutorial, we’ll walk through the process of creating a simple yet effective Sudoku checker using JavaScript.

Understanding the Sudoku Puzzle

Before diving into coding, it’s essential to understand the structure of a Sudoku puzzle. A standard Sudoku grid consists of a 9×9 board, divided into nine 3×3 subgrids, known as boxes. The objective of the game is to fill in the grid with numbers from 1 to 9, ensuring that each number appears exactly once in each row, column, and box. This makes it a great candidate for using arrays and nested loops in JavaScript.

To create our Sudoku checker, we need a way to represent the board in our code. We can use a two-dimensional array (an array of arrays) for this purpose. Each inner array will represent a row on the Sudoku board, and the values will be the numbers filled in by the player or zero for empty cells. With this in mind, let’s outline the logic we’ll implement in our checker.

Our Sudoku checker will perform the following tasks:

  • Validate numbers in each row
  • Validate numbers in each column
  • Validate numbers in each 3×3 box

By ensuring each of these conditions is met, we can ascertain whether the Sudoku board is valid or not.

Setting Up the Project

For this project, we’ll create a simple HTML file with a JavaScript section. You can use any code editor, such as VS Code or WebStorm, and follow along. Here’s a basic outline for our HTML setup:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Sudoku Checker</title>
</head>
<body>
    <h1>Sudoku Checker</h1>
    <script>
        // JavaScript code will go here
    </script>
</body>
</html>

This HTML structure sets up a foundation for our Sudoku checker. Next, we will implement the JavaScript logic to validate the Sudoku board.

Implementing the Sudoku Checker Logic

We’ll create a function called `isValidSudoku(board)` that takes a 9×9 array as an input and returns true or false based on whether the board is valid. Here’s how we can structure our code:

function isValidSudoku(board) {
    // Check rows, columns, and boxes
}

Now, we need to loop through each row, column, and box to verify that each number from 1 to 9 appears only once. Here’s how we can achieve that:

We’ll start with validating the rows. We’ll create a helper function, `isUnique`, that checks if numbers in a given array are unique and not equal to zero:

function isUnique(array) {
    const seen = new Set();
    for (let number of array) {
        if (number !== 0) { // Ignore empty cells
            if (seen.has(number)) {
                return false;
            }
            seen.add(number);
        }
    }
    return true;
}

With the `isUnique` function, we can check each row by iterating through the board:

for (let row of board) {
    if (!isUnique(row)) {
        return false;
    }
}

After ensuring rows are valid, we’ll validate the columns similarly. We can extract each column by iterating over the index values of rows:

for (let col = 0; col < 9; col++) {
    const column = board.map(row => row[col]);
    if (!isUnique(column)) {
        return false;
    }
}

Lastly, we will check the 3×3 boxes. The 3×3 boxes can be iterated through nested loops. Here’s how it looks:

for (let boxRow = 0; boxRow < 3; boxRow++) {
    for (let boxCol = 0; boxCol < 3; boxCol++) {
        const box = [];
        for (let row = 0; row < 3; row++) {
            for (let col = 0; col < 3; col++) {
                box.push(board[boxRow * 3 + row][boxCol * 3 + col]);
            }
        }
        if (!isUnique(box)) {
            return false;
        }
    }
}

With this complete, our `isValidSudoku` function should look like this:

function isValidSudoku(board) {
    for (let row of board) {
        if (!isUnique(row)) {
            return false;
        }
    }

    for (let col = 0; col < 9; col++) {
        const column = board.map(row => row[col]);
        if (!isUnique(column)) {
            return false;
        }
    }

    for (let boxRow = 0; boxRow < 3; boxRow++) {
        for (let boxCol = 0; boxCol < 3; boxCol++) {
            const box = [];
            for (let row = 0; row < 3; row++) {
                for (let col = 0; col < 3; col++) {
                    box.push(board[boxRow * 3 + row][boxCol * 3 + col]);
                }
            }
            if (!isUnique(box)) {
                return false;
            }
        }
    }

    return true;
}

This function will now check the board and return whether it’s a valid Sudoku configuration. Let’s now see how to use this function in practice.

Testing the Sudoku Checker

Now that we have our Sudoku checking logic implemented, we need to test it with different board configurations. Let’s set up a few test cases:

const validBoard = [
    [5, 3, 0, 0, 7, 0, 0, 0, 0],
    [6, 0, 0, 1, 9, 5, 0, 0, 0],
    [0, 9, 8, 0, 0, 0, 0, 6, 0],
    [8, 0, 0, 0, 6, 0, 0, 0, 3],
    [4, 0, 0, 8, 0, 3, 0, 0, 1],
    [7, 0, 0, 0, 2, 0, 0, 0, 6],
    [0, 6, 0, 0, 0, 0, 2, 8, 0],
    [0, 0, 0, 4, 1, 9, 0, 0, 5],
    [0, 0, 0, 0, 8, 0, 0, 7, 9]
];

console.log(isValidSudoku(validBoard)); // Output: true

const invalidBoard = [
    [5, 3, 0, 0, 7, 0, 0, 0, 0],
    [6, 5, 0, 1, 9, 5, 0, 0, 0],
    [0, 9, 8, 0, 0, 0, 0, 6, 0],
    [8, 0, 0, 0, 6, 0, 0, 0, 3],
    [4, 0, 0, 8, 0, 3, 0, 0, 1],
    [7, 0, 0, 0, 2, 0, 0, 0, 6],
    [0, 6, 0, 0, 0, 0, 2, 8, 0],
    [0, 0, 0, 4, 1, 9, 0, 0, 5],
    [0, 0, 0, 0, 8, 0, 0, 7, 9]
];

console.log(isValidSudoku(invalidBoard)); // Output: false

Here we have defined a valid Sudoku board and an invalid one. When running this code, you should see the correct validation results in your console, confirming that our checker works as intended.

Improving the User Experience

Now that we have a functional Sudoku checker, we can enhance the user experience by creating a simple user interface (UI) that allows users to submit their Sudoku boards and receive feedback on their validity. This can be done using HTML forms and JavaScript event listeners.

Below is a basic example of how we can structure the UI:

<form id="sudoku-form">
    <table>
        <tbody>
            <tr>
                <td><input type="number" min="0" max="9"></td>
                <td><input type="number" min="0" max="9"></td>
                ...
                <td><input type="number" min="0" max="9"></td>
            </tr>
            
        </tbody>
    </table>
    <button type="submit">Check Sudoku

In the accompanying JavaScript, we’ll listen for the form submission, extract the values from the input fields into a 2D array, and then call the `isValidSudoku` function:

document.getElementById('sudoku-form').addEventListener('submit', function(event) {
    event.preventDefault();
    const board = Array.from({ length: 9 }, (_, row) => Array.from({ length: 9 }, (_, col) => {
        return +document.querySelector(
            `input[data-row="${row}"][data-col="${col}"]`
        ).value;
    }));

    const resultDiv = document.getElementById('result');
    resultDiv.textContent = isValidSudoku(board) ? 'Valid Sudoku!' : 'Invalid Sudoku!';
});

Replace the ellipsis in the HTML with appropriate input fields for each cell of the Sudoku board. Each input can have data attributes for its row and column to easily query them later.

Conclusion and Next Steps

In this tutorial, we built a Sudoku checker using JavaScript, utilizing arrays and basic logic to validate the board’s configuration. This project not only helps reinforce fundamental programming concepts but also offers a challenging way to engage with algorithms.

The next steps can include enhancing the user interface, adding features such as a Sudoku generator, or styling it with CSS to improve aesthetics. You can also look into employing advanced techniques like using Web Workers for offloading calculations if you expand to validating larger grids.

We hope this project inspires you to continue exploring JavaScript and its potential. With your new Sudoku checker in hand, dive into developing more engaging applications that challenge both you and your users!

Scroll to Top