# Calculating the squares dominated by a queen on a chessboard

I have a JavaScript function that increments a counter for each square on the chessboard as it becomes dominated by a queen and decrements it if one of the dominating queens are removed (only queens, this isn't actually a chess game with all of the pieces, it's essentially the 8 queens puzzle). If a square is dominated by at least one queen, (e.g. square.dominatedBy > 0), a CSS class is later applied to change the color of the square.

The function seems far longer than it needs to be though, and there has to be a better way to DRY it up.

(chessBoardSquares is an array of an array of Squares on the board, which are objects with properties such as row, column, and dominatedBy)

function setDominatedSquares(queenPosition, remove = false) {
// handle squares in the same row as the queen
for (var column = 0; column < boardSizeX; column++) {
if (remove) {
chessBoardSquares[queenPosition.row][column].dominatedBy--;
} else {
chessBoardSquares[queenPosition.row][column].dominatedBy++;
}
}
// handle squares in the same column as the queen
for (var row = 0; row < boardSizeY; row++) {
if (remove) {
chessBoardSquares[row][queenPosition.column].dominatedBy--;
} else {
chessBoardSquares[row][queenPosition.column].dominatedBy++;
}
}
// handle diagonals down and to right
var row = queenPosition.row;
var column = queenPosition.column;
while (row < boardSizeY && column < boardSizeX) {
if (remove) {
chessBoardSquares[row][column].dominatedBy--;
} else {
chessBoardSquares[row][column].dominatedBy++;
}
row++;
column++;
}
// handle diagonals up and to left
row = queenPosition.row;
column = queenPosition.column;
while (row >= 0 && column >= 0) {
if (remove) {
chessBoardSquares[row][column].dominatedBy--;
} else {
chessBoardSquares[row][column].dominatedBy++;
}
row--;
column--;
}

// handle diagonals down and to left
row = queenPosition.row;
column = queenPosition.column;
while (row >= 0 && column < boardSizeX) {
if (remove) {
chessBoardSquares[row][column].dominatedBy--;
} else {
chessBoardSquares[row][column].dominatedBy++;
}
row--;
column++;
}

// handle diagonals up and to right
row = queenPosition.row;
column = queenPosition.column;
while (row < boardSizeY && column >= 0) {
if (remove) {
chessBoardSquares[row][column].dominatedBy--;
} else {
chessBoardSquares[row][column].dominatedBy++;
}
row++;
column--;
}
// update the UI
updateDominatedSquares();
}


Update: For anyone interested, this code is now running live at queensoptimization.azurewebsites.net

• Shouldn't a queen's dominance be limited by obstacles? Mar 22 '17 at 13:00
• @200_success This is an interesting point that I hadn't thought about. However, in this case, the only potential obstacle would be another queen, which would end up not changing the squares that would be dominated at all from the case where there was no obstacle. Mar 22 '17 at 15:20

I would probably break this up into a function setDominatedForLine that would work for each direction. Instead of a true/false remove parameter I used a dominatedIncrement parameter with a value of +1 or -1.

function setDominatedSquares(queenPosition, dominatedIncrement = +1) {

function setDominatedForLine(rowInc, columnInc) {
let row    = queenPosition.row;
let column = queenPosition.column;
while (row >= 0 && row < boardSizeY && column >= 0 && column < boardSizeX) {
chessBoardSquares[row][column].dominatedBy += dominatedIncrement;
row    += rowInc;
column += columnInc;
}
}

// Column
setDominatedForLine( 0,  1);
setDominatedForLine( 0, -1);
// Row
setDominatedForLine( 1,  0);
setDominatedForLine(-1,  0);
// Diagonals
setDominatedForLine( 1,  1);
setDominatedForLine( 1, -1);
setDominatedForLine(-1,  1);
setDominatedForLine(-1, -1);

// update the UI
updateDominatedSquares();
}


You could also modify it slightly with something like:

let directions = [ {r:-1, c:-1}, {r:-1, c: 0}, {r:-1, c: 1},
{r: 0, c:-1},               {r: 0, c: 1},
{r: 1, c:-1}, {r: 1, c: 0}, {r: 1, c: 1} ]
for (let dir of directions)
setDominatedForLine( dir.r, dir.c );


But I'm not sure if that is an improvement.