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 &gt; 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 &lt; 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 &lt; 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 &lt; boardSizeY &amp;&amp; column &lt; 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 &gt;= 0 &amp;&amp; column &gt;= 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 &gt;= 0 &amp;&amp; column &lt; 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 &lt; boardSizeY &amp;&amp; column &gt;= 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
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 &gt;= 0 &amp;&amp; row &lt; boardSizeY &amp;&amp; column &gt;= 0 &amp;&amp; column &lt; 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.