Number path game

What is it?

A web version of the Numbrix logic game where the numbers 1 to 81 need to be placed in a grid so they form a 'path' through it (no diagonals allowed).

This is a web version of the logic game Numbrix from Parade magazines. The puzzle is a 9 by 9 cell grid that you need to fill with each number from 1 to 81 to form a path through the grid (without using diagonals). Some numbers pre-populated on the edge of the grid of each puzzle to get started.

How does it work?

It generates several puzzles at a time, assigns a difficulty level to each, and lets you browse through them to find a puzzle you would like to try.

This web version first generates several new puzzles at once, gives each of them a rough difficulty rating, then allows the player to scroll through them to see which puzzle they want to try. If you get stuck while trying to solve it, you can toggle the display of the puzzle's solution path on and off.

How is it built?

It attempts 5,000 puzzle generations when the page is loaded, and shows the ones where complete puzzles were found. You can toggle whether the answer (the path through the grid) is displayed or not.

The main components of this app generate the puzzles and then display the currently selected puzzle on the screen.

The completed puzzle configurations for each website load (5,000 attempted puzzle generations) are stored in an array, with the rows and columns for each puzzle represented as an array of arrays, enabling easy browsing of the different puzzles found.

There is a toggle to switch between showing each puzzle ready for solving or showing the answer as a solved path that connects the numbers. This is fully rendered in HTML through <td> elements for the number cells, and <div> elements in different directions to denote the path.

To try and give puzzle solvers more detail about each of the puzzles generated, I built a method to assign expected difficulty levels (easy, medium, or hard) to each of the puzzles based on the length of the typical number 'loops' in each puzzle that take place in between the initial numbers given around the outside edge. Longer 'loops' mean there are larger differences in the initially filled-in number values. This also means there are more possible ways to configure the numbers connecting two of them inside the grid, and therefore the puzzle is typically more difficult.

Why did I build it?

I wanted a way to make more Numbrix-like puzzles for myself and family members to be able to solve.

A family member introduced me to Numbrix puzzles but we only got one new puzzle per week when it was published in Parade magazine and I wanted build more puzzles for them to be able to solve. I knew it could be tricky to build an automated puzzle generator for this because random shuffling would perform extremely poorly in generating these puzzles. Because of that, I also knew I would need some optimizations based on the puzzle rules, and that challenge was appealing to me.

Project design

I started by getting the basic mechanics for the game building working before adding features like assigning a difficulty level to puzzles and a toggle to display the solved version of each puzzle.

The design started quite basic, with focusing on getting code that could randomly generate these numberPath puzzles reliably. When that was working, I worked to include additional features to make it more fun for the player: including the ability to browse through all puzzles generated to pick one that looks fun to solve, ranking the puzzles so the player can see how easy or difficult a puzzle may be, and being able to display the solution for the chosen puzzle.

What I am most proud of

Heuristics I identified to improve the success rate for generating the puzzles.

I am most proud of the heuristics that allow the app to identify many more puzzles per run (more detail about this is in the next section) and assigning a general difficulty level for each puzzle based on the size of number 'loops' that are not anchored by the initially given numbers.

Challenges I ran into and how I resolved them

Generating complete (81 cell) puzzles was computationally costly to do randomly and had a very low success rate, so I identified two heuristic rules and built them into the puzzle generation to improve the success rate.

Initially I built this to randomly fill the grid with numbers until there were no more possible moves, and then to start over and try again. This allowed me to get the basic code working to check for open squares the four possible directions, and to fill them.

However, not surprisingly, the percentage of full puzzles that included all 81 numbers that this produced was exceedingly small. To help fix this, I identified 2 conditions that seemed to prevent many of the puzzles from being able to be completed:

  1. Packing numbers into single cell gaps, if found
  2. Avoiding having numbers cross 2-cell gaps and therefore cut them off.

I made heuristic weights for both conditions to favor puzzles that used both of these rules and tuned these weights by trial and error to increase the number of puzzles successfully found.

What I learned for future projects

This project reinforced how to traverse two-dimensional grids of values, pathfinding through those grids, and looking for heuristic rules that can improve that pathfinding.

Working with two-dimensional grids of values and pathfinding through those grids while following different rule sets were both helpful when building my wordPath project. I also learned to closely examine app output given a set of input rules, and to determine heuristic changes that could be made to those rules so that the app could run more efficiently.