How Do I Optimize My Javascript Code That I Currently Have?
Solution 1:
Concur with @pelmetennui in that it is best to segregate the internal representation of the game board from the presentation tier. Towards that end, have framed out a representation of the board, which can act as a springboard for generating the HTML DOM representation...
Note that in this particular representation, the board is a single dimensional array and includes a twice thick border. This is a standard board representation technique for some enthusiast chess engines, as it provides an easy method for generating moves, including Knights which can make an initial jump of 2 files and/or 2 ranks, and hence the twice thick border. (See the pieces
object which lists the possible moves as relative changes to the current index in the single dimensional array.) This border then obviates the need to check array boundaries when generating candidate move lists...
let pieces = {
'k': { name: 'King', color: 'Black', moves: [ +1, -11, -12, -13, -1, +11, +12, +13 ], moveMax: 1, img: 'black_king.png' },
'q': { name: 'Queen', color: 'Black', moves: [ +1, -11, -12, -13, -1, +11, +12, +13 ], moveMax: 7, img: 'black_queen.png' },
'r': { name: 'Rook', color: 'Black', moves: [ +1, -12, -1, +12 ], moveMax: 7, img: 'black_rook.png' },
'b': { name: 'Bishop', color: 'Black', moves: [ -11, -13, +11, +13 ], moveMax: 7, img: 'black_bishop.png' },
'n': { name: 'Knight', color: 'Black', moves: [ -10, -23, -25, -14, +10, +23, +25, +14 ], moveMax: 1, img: 'black_knight.png' },
'p': { name: 'Pawn', color: 'Black', moves: [ +12 ], moveMax: 1, specialRank: 7, img: 'black_pawn.png'},
'K': { name: 'King', color: 'White', moves: [ +1, -11, -12, -13, -1, +11, +12, +13 ], moveMax: 1, img: 'white_king.png' },
'Q': { name: 'Queen', color: 'White', moves: [ +1, -11, -12, -13, -1, +11, +12, +13 ], moveMax: 7, img: 'white_queen.png' },
'R': { name: 'Rook', color: 'White', moves: [ +1, -12, -1, +12 ], moveMax: 7, img: 'white_rook.png' },
'B': { name: 'Bishop', color: 'White', moves: [ -11, -13, +11, +13 ], moveMax: 7, img: 'white_bishop.png' },
'N': { name: 'Knight', color: 'White', moves: [ -10, -23, -25, -14, +10, +23, +25, +14 ], moveMax: 1, img: 'white_knight.png' },
'P': { name: 'Pawn', color: 'White', moves: [ -12 ], moveMax: 1, specialRank: 2, img: 'white_pawn.png'}
}
classChessBoard {
constructor( FEN ) {
this.board = [
'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X',
'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X',
'X', 'X', '.', '.', '.', '.', '.', '.', '.', '.', 'X', 'X',
'X', 'X', '.', '.', '.', '.', '.', '.', '.', '.', 'X', 'X',
'X', 'X', '.', '.', '.', '.', '.', '.', '.', '.', 'X', 'X',
'X', 'X', '.', '.', '.', '.', '.', '.', '.', '.', 'X', 'X',
'X', 'X', '.', '.', '.', '.', '.', '.', '.', '.', 'X', 'X',
'X', 'X', '.', '.', '.', '.', '.', '.', '.', '.', 'X', 'X',
'X', 'X', '.', '.', '.', '.', '.', '.', '.', '.', 'X', 'X',
'X', 'X', '.', '.', '.', '.', '.', '.', '.', '.', 'X', 'X',
'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X',
'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'
];
if ( FEN ) {
this.setToFen( FEN );
}
}
print() {
let charBoard = '';
for ( let rank = 8; 1 <= rank; rank-- ) {
charBoard += ' ';
for ( let file = 1; file <= 8; file++ ) {
charBoard += this.board[ this.fileRankToIndex( file, rank ) ] + ' ';
}
charBoard += '\n';
}
return charBoard;
}
setToFen( FEN ) {
// See https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notationlet file = 1;
let rank = 8;
for ( let i = 0; i < FEN.length; i++ ) {
let fenChar = FEN[ i ];
if ( fenChar === ' ') {
break;
} elseif ( fenChar === '/' ) {
rank--;
file = 1;
} elseif ( '0' <= fenChar && fenChar <= '8' ) {
file = file + parseInt( fenChar );
} elseif ( pieces[ fenChar ] ) {
this.board[ this.fileRankToIndex( file, rank ) ] = fenChar;
file++;
}
}
}
indexToFileRank( i ) {
return { file: i % 12 - 1, rank: 10 - ( i / 12 |0 ) };
}
fileRankToIndex( file, rank ) {
return ( 24 + ( 8 - rank ) * 12 + file + 1 );
}
}
// Let's test our ChessBoard class!let cb = newChessBoard( 'rnbqkbnr/pppppppp/8/8/8/2N5/PPPPPPPP/R1BQKBNR w KQkq - 0 1' );
console.log( cb.print() + '\n' );
console.log( `Piece at d1 (file 4, rank 1) is: ${cb.board[ cb.fileRankToIndex( 4, 1 ) ]}\n` );
console.log( `Where can N at c3 move to?` );
let c3 = cb.fileRankToIndex( 3, 3 );
let result = '';
debugger;
for ( let move of pieces[ 'N' ].moves ) {
let possibleMove = c3 + move;
if ( cb.board[ possibleMove ] === '.' ) {
let square = cb.indexToFileRank( possibleMove );
result += ' abcdefgh'[ square.file ] + square.rank + ' ';
}
}
console.log( `N at c3 can move to: ${result}` );
Hopefully this gives you a head start reducing redundancy of code, and in writing a method to generate the HTML DOM, a method which should be similar to the print()
method, except of course, generating <div>
and <img...>
nodes. Note that the pieces
object contains attribute img
referencing the PNG image name for the piece in question, which can be used to populate the <img src=...
node when looping over the file
and rank
of this.board
...
Solution 2:
You should separate your presentation and your model for the game. Your model for the game should encode the state of the board as some convenient data structure. There are multiple potential data structures that would make sense:
Using an object as a map:
const chessboard = {"A4": "BLACK_ROOK", "C6": "WHITE_KNIGHT"};
Using a multidimensional array:
const chessboard = [
[null, null, null, "BLACK_KNIGHT", "BLACK_KING", null, null, null],
[null, null, null, null, "BLACK_PAWN", null, null, null],
[null, null, null, null, null, null, null, null],
[null, null, null, null, null, null, null, null],
[null, null, null, null, null, null, null, null],
[null, null, null, null, null, null, null, null],
[null, null, null, null, null, null, null, null],
[null, null, null, "WHITE_KNIGHT", "WHITE_KING", null, null, null],
];
Then you would define some function that converts the internal model of the game into a presentation, by e.g. iterating over these data structures and mapping them to divs.
This would let you parameterize calls from your various onmouseover/onclick functions, so that instead of calling separate functions, they'd call e.g. onmouseover = "hideDot('A4')"
or onclick = "hideDot(3, 4)"
. You could then have a single function that implements whatever logic you need.
Post a Comment for "How Do I Optimize My Javascript Code That I Currently Have?"