patternjavascriptMinor
Tic Tac Toe with Minimax (memory management optimization)
Viewed 0 times
minimaxwithtoetictacoptimizationmemorymanagement
Problem
I've made a Tic Tac Toe game with minimax in Javascript. It works but I have to use
The relevant code:
Board class
```
//Game's constants
var DRAW = 0, PLAYERX = 1, PLAYERO = 2,
SCORES = {
1: 1,
0: 0,
2: -1
};
var dims = 3; //dimensions for the game's board
//Class representing the game's board
function Board(dims, board) {
this.dims = dims;
this.grid = [];
for (var square = 0; square < dims * dims; square++) {
if (board) {
this.grid.push(board[square]);
} else {
this.grid[square] = 0;
}
}
}
//Show visual representation of the grid for debugging purposes
Board.prototype.showGrid = function () {
var grid = [];
for (var i = 0; i < dims * dims; i++) {
grid.push(this.grid[i]);
}
return grid;
};
/*Returns one of the three constants for EMPTY, PLAYERX, or PLAYERO
that correspond to the contents of the board at position (square).*/
Board.prototype.square = function (sqr) {
return this.grid[sqr];
};
//Return an array of all empty squares in form [squares]
Board.prototype.getEmptySquares = function () {
var empty = [];
for (var i = 0; i < this.dims * this.dims; i++) {
if (this.square(i) === 0) empty.push(i);
}
return empty;
};
/*Place player on the board at position (square).
player should be either the constant PLAYERX or PLAYERO.
Does nothing if board square is not empty.*/
Board.prototype.move = function (square
location.reload(true); to automatically reload the page every time user starts a new game (by pressing 'Play again!' in the modal), otherwise the game becomes slower with every round until it stops responding. I guess the problem is in the way I've written runGame() function which does not free the memory and keeps all the context through closure throughout all the rounds. My question is therefore how can I rewrite it so I don't have to reload page on each new round and don't have those memory leaks. The relevant code:
Board class
```
//Game's constants
var DRAW = 0, PLAYERX = 1, PLAYERO = 2,
SCORES = {
1: 1,
0: 0,
2: -1
};
var dims = 3; //dimensions for the game's board
//Class representing the game's board
function Board(dims, board) {
this.dims = dims;
this.grid = [];
for (var square = 0; square < dims * dims; square++) {
if (board) {
this.grid.push(board[square]);
} else {
this.grid[square] = 0;
}
}
}
//Show visual representation of the grid for debugging purposes
Board.prototype.showGrid = function () {
var grid = [];
for (var i = 0; i < dims * dims; i++) {
grid.push(this.grid[i]);
}
return grid;
};
/*Returns one of the three constants for EMPTY, PLAYERX, or PLAYERO
that correspond to the contents of the board at position (square).*/
Board.prototype.square = function (sqr) {
return this.grid[sqr];
};
//Return an array of all empty squares in form [squares]
Board.prototype.getEmptySquares = function () {
var empty = [];
for (var i = 0; i < this.dims * this.dims; i++) {
if (this.square(i) === 0) empty.push(i);
}
return empty;
};
/*Place player on the board at position (square).
player should be either the constant PLAYERX or PLAYERO.
Does nothing if board square is not empty.*/
Board.prototype.move = function (square
Solution
Your code is leaking indeed. jQuery
Fixed App.js
(ps: shouldn't this be moved to stackoverflow)
.on is always adding events to the element. Not replacing them. Since you call this each time it's the player's turn. After 5 games, the event is already called 25 times for each click at the same time.Fixed App.js
$(document).ready(function () {
var board;
//helper function
function switchPlayer(player) {
return player === PLAYERX ? PLAYERO : PLAYERX;
}
function minimax(board, player) {
var mult = SCORES[String(player)], thisScore,
empty = board.getEmptySquares(), l = empty.length,
maxScore = -1, bestMove = null;
if (board.checkWin() != 'None') {
return [SCORES[board.checkWin()], 0];
} else {
for (var i = 0; i = maxScore) {
maxScore = thisScore;
bestMove = empty[i];
}
}
return [mult * maxScore, bestMove];
}
}
//Function that runs the game
function runGame() {
//Create a new board for the game
board = new Board(dims);
//clear previous board
for (var i = 0; i ' + text + '');
$('.winner').modal('show');
}
runGame();
$('#replay').on('click', function () {
$('.winner').modal('hide');
//location.reload(true);
runGame();
});
});(ps: shouldn't this be moved to stackoverflow)
Code Snippets
$(document).ready(function () {
var board;
//helper function
function switchPlayer(player) {
return player === PLAYERX ? PLAYERO : PLAYERX;
}
function minimax(board, player) {
var mult = SCORES[String(player)], thisScore,
empty = board.getEmptySquares(), l = empty.length,
maxScore = -1, bestMove = null;
if (board.checkWin() != 'None') {
return [SCORES[board.checkWin()], 0];
} else {
for (var i = 0; i < l; i++) {
var copy = board.clone();
copy.move(empty[i], player);
thisScore = mult * minimax(copy, switchPlayer(player))[0];
if (thisScore >= maxScore) {
maxScore = thisScore;
bestMove = empty[i];
}
}
return [mult * maxScore, bestMove];
}
}
//Function that runs the game
function runGame() {
//Create a new board for the game
board = new Board(dims);
//clear previous board
for (var i = 0; i < dims * dims; i++) {
$('#' + i).text('');
}
}
$('.square').on('click', function () {
var id = $(this).attr('id');
if (board.square(id) === 0) {
$(this).text('X');
board.move(id, PLAYERX);
if (board.checkWin() === 'None') {
AImove(board);
} else {
declareWinner(board.checkWin());
}
}else{
// still player's move
}
});
function AImove() {
var move = minimax(board, PLAYERO)[1];
board.move(move, PLAYERO);
$('#' + move).text('O');
if (board.checkWin() === 'None') {
// player move
} else {
declareWinner(board.checkWin());
}
}
function declareWinner(winner) {
winner = winner === 1 ? 'Player X' : winner === 2 ? 'Player O' : 'Draw';
var text = winner == 'Draw' ? "It's a draw!" : winner + ' wins!';
$('.modal-body').html('<h3>' + text + '</h3>');
$('.winner').modal('show');
}
runGame();
$('#replay').on('click', function () {
$('.winner').modal('hide');
//location.reload(true);
runGame();
});
});Context
StackExchange Code Review Q#112246, answer score: 2
Revisions (0)
No revisions yet.