Visualizing N-Queens

Andrei Taylor
Jul 10, 2017 · 7 min read

Here for the visualizer? You can find it here andreitaylor.com/nqueens

I’m studying for programming interviews right now and I came across the N-Queens problem. I thought it would be interesting to break down this problem in excruciating detail so that we can all understand the solution. This blog post does just that.

The Question

The N-Queens puzzle is the problem of placing N Queens on an N×N chessboard such that no two queens attack each other.

What is a Queen and how does it move?

A Queen is a chess piece, it moves on a chess board. It is able to move up, down, left, right or on a diagonal. This means that any queen that is on the same row, column or diagonal is able to be attacked.

like this…

What is a solution?

A board is solved when there are N Queens placed on the board in such a way that none of the Queens can attack each-other.

A solution for N=4 (there are only 2 solutions for N = 4)

Since none of the queens are on the same row or on the same column or on the same diagonal this permutation is a solution for N=4.

For your reference, I have included an image of every solution to the N=5 puzzle below.

There are 10 solutions to N=5

But, how do we generate these solutions? I think it’s easiest to start with a brute force solution.

Brute Force

If we don’t care about how long it takes, what is the simplest way to generate solutions?

The first thing that comes to my mind is to generate every possible permutation of Queens on the board, then have a function that tells you if the current state of the board is a solution.

For our brute force lets limit ourselves to the permutations with 1 queen per column. This is because every solution to the N-Queens problem will have at most 1 queen in each column, can you see why?

I made a video to visualize this below.

And here is the handwaivey javascript code.

This code would produce solutions if set_queen , remove_queen and is_solution worked as described above (I didn’t implement them here).

Take a moment to understand the recursive nature of the above code before you continue. Basically, we are recursing on each column and placing a queen at each possible row in that column. If this doesn’t make sense, try watching the video above and reading the code at the same time.

Backtracking Baby

It’s kinda dumb that we are looking at so many obviously invalid board placements. I mean take a look at the 5th through 12th moves of the brute force algorithm. None of these are even close to being valid, what a waste of time.

These moves are obviously not solutions

How about we change the algorithm a bit so that we don’t have to place any of the Queens in stupid places.

Instead of checking for solutions after each move, how about how about we check to see if the current move is valid before placing the piece and recursing.

This is known as backtracking, and its the way we are going to solve this problem. Backtracking is a general algorithm that says if the current partial solution is invalid you shouldn’t continue computing.

In our problem it looks like this.

As you can see, backtracking greatly reduces the number of boards we have to look at in-order to get to a solution. Check out this comparison!

Comparison of Brute Force and Backtracking

Note that there is a row that records the number of executions of the backtracking loop and that row is not the same as the number of Queens placed. This is because the loop still has to check if the move is valid even though its not necessarily going to put a queen in that position.

For example when when N = 4, even though only 16 Queens are actually placed on the board (see above video) , you are actually running the check operation 60 times. To contrast, in our brute force solution, all of the Queens placed are actually executions of the loop.

Now lets see some code

Again take some time to read this and understand it before you move on, I believe in you. You can get it.

Enough is Enough Lets See the Damn Code

The way to implement is_valid_move is to check if the input cell has any other Queens along the same row, column, up diagonal or down diagonal.

Testing for rows and columns is easy, just make an array ROWS[N] and when you place something in row x set the value of ROWS[x] to true. The same goes for columns with an array called COLS[N]. But what about those pesky diagonals?

Before we get to the actual code, lets visualize a very interesting property of indexes in a 2 dimensional array.

Lets say you are trying to place a queen at row=0, col=0 what is the best way to check if there is anything on the downwards diagonal in green?

How can we know if there is anything in the spaces in green?

The naieve way is to iterate over all of the entries in that diagonal and test if there is anything there. But that seems wasteful, especially since as the board size increases we are going to have to do more operations. We can do a lot better.

Diagonal Tracking With Arrays

How about we keep an additional array for the upward diagonal and the downward diagonal. For the upwards diagonal make UP_DIAG[2*N-1] in this array you store row+col. The same idea goes for the downward diagonal make an array DOWN_DIAG[2*N-1] but in this array you index by row — col .

row = 0, col = 0

Do you see how it works? At index 0,0 row + col and row — col are 0 so we set those indexes in the UP_DIAG and DOWN_DIAG arrays respectively. Now lets look at the next valid move.

row = 2, col = 1

Lets go through the moves that we tried to get to this valid placement.

  1. We try row = 0 and col = 1 which is invalid because we already have something in ROW[0].
  2. Then we try row = 1 and col = 1 which is invalid because we have something in DOWN_DIAG[0] (row — col = 1–1 = 0).
  3. Then we get to row = 2 and col = 1 and find no problems, so we can place the piece. When we place this piece we mark off UP_DIAG[3] = true (row + col = 1 + 2 = 3) and DOWN_DIAG[1]=true (row — col = 2–1=1) and the row and column arrays as seen in the diagram.

If you still don’t understand this you can take the tool you see above for a test drive at andreitaylor.com/nqueens. Hover over the UP_DIAG entries to see the corresponding upwards diagonal line. Hover over the DOWN_DIAG entries to see the corresponding downward diagonal line. Or just hover over the board to see which diagonal each cell corresponds to.

I think this diagonal tracking system is the coolest part of the N-Queens problem because it is applicable for any 2D array based game where you need to track entries on a diagonal. Thinking off the top of my head, you could use this to to make a tick tack toe, or Connect 4 Implementation or to solve the no three in line problem.

I think I have explained this enough that we can see the code and understand it. Note that I added in an offset for the DOWN_DIAG indexing in my code, this makes it so that the index is stored going from 0 to N-1 instead of -(N/2–1) to (N/2 -1).

You can literally copy and paste this into your browser console to run it. It will print out the number of solutions and the number of tries. Note that even though it would work, I wouldn’t choose a N greater than 12 or 13 as this is a very big computation.

Its Over

That’s it! Please leave! Well actually, I’ll leave you with a few notes about this blog.

  • There are better ways to do this problem, specifically I know you don’t need the full NxN array and you you can just have a N size array that represents the columns and each entry is the row of the queen in that column pascal solution is here, look at the array x. Also there are bit-wise implementations that run orders of magnitude faster.
  • is_solution() is a cool function to write, try writing it yourself. hint: you can use the diagonal arrays but they should be integers instead of booleans. Also the set_queen and remove_queen would need to be edited to take this into account.
  • The blog post was my focus, the visualizer started out as a way to save me time when making visuals. The source code for it is … sloppy… but it is open source (HTML, js) feel free to look through if you wish. It’s admittedly not my finest work.
  • The visualizer is very slow because it uses a bunch of generators to save the state. The visualizer is meant to visualize not to solve.
Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade