HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Calculating the squares dominated by a queen on a chessboard

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
dominatedchessboardthequeensquarescalculating

Problem

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 = 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 = 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

Solution

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 = 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.

Code Snippets

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();
}
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 );

Context

StackExchange Code Review Q#158448, answer score: 4

Revisions (0)

No revisions yet.