我已经为无与伦比的tic toc toe游戏实现了minimax算法。 minimax算法是递归的,执行大的迭代,这对于计算机来说并不大,对人类来说只是很大的。 第一步在codepen上执行大约需要3秒钟,但在本地计算机上立即执行。 怎么了?我的代码效率不高?或者它在codepen上有问题吗? 它如何使它在codepen上高效? 这是我的JS代码:
var player;
var opponent;
var myMove = false;
var board = [
[null, null, null],
[null, null, null],
[null, null, null]
];
//displays modal
$('.play').click(function() {
$('.modal').css("display", "block");
});
$('.O').click(function() {
$('.modal').css("display", "none");
player = 'O';
opponent = 'X';
resetGame();
updateSymbol();
main();
});
$('.X').click(function() {
$('.modal').css("display", "none");
player = 'X';
opponent = 'O';
resetGame();
updateSymbol();
main();
});
function main() {
$(".col-xs-4").click(function() {
if ($(this).is(':empty')) {
var cell = $(this).attr("id");
var row = parseInt(cell[1]);
var col = parseInt(cell[2]);
if (!myMove) {
board[row][col] = false;
myMove = true;
updateMove();
makeMove();
}
}
});
}
function checkWin(board) {
vals = [true, false];
var allNotNull = true;
for (var k = 0; k < vals.length; k++) {
var value = vals[k];
// Check rows, columns, and diagonals for win
var diagonalComplete1 = true;
var diagonalComplete2 = true;
for (var i = 0; i < 3; i++) {
if (board[i][i] != value) {
diagonalComplete1 = false;
}
if (board[2 - i][i] != value) {
diagonalComplete2 = false;
}
var rowComplete = true;
var colComplete = true;
for (var j = 0; j < 3; j++) {
if (board[i][j] != value) {
rowComplete = false;
}
if (board[j][i] != value) {
colComplete = false;
}
if (board[i][j] === null) {
allNotNull = false;
}
}
if (rowComplete || colComplete) {
return value ? 1 : 0;
}
}
if (diagonalComplete1 || diagonalComplete2) {
return value ? 1 : 0;
}
}
if (allNotNull) {
return -1;
}
return null;
}
function resetGame() {
board = [
[null, null, null],
[null, null, null],
[null, null, null]
];
myMove = false;
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
$("#" + "b" + i + "" + j).text("").css("background", "#222");
}
}
$('h3').css("display", "none").text("");
}
function updateMove() {
updateSymbol();
var winner = checkWin(board);
if (winner === 1) {
$('h3').css("display", "block").append(opponent + " won!!").addClass("animated infinite pulse");
markWin();
setTimeout(resetGame, 2000);
} else if (winner === 0) {
$('h3').css("display", "block").append(player + ' won!!').addClass("animated infinite pulse");
markWin();
setTimeout(resetGame, 2000);
} else if (winner === -1) {
$('h3').css("display", "block").append("It's a Draw!!").addClass("animated infinite pulse");
markWin();
setTimeout(resetGame, 2000);
}
}
function updateSymbol() {
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (board[i][j] === false && $("#" + "b" + i + "" + j).is(':empty')) {
$("#" + "b" + i + "" + j).text(player);
} else if (board[i][j] === true && $("#" + "b" + i + "" + j).is(':empty')) {
$("#" + "b" + i + "" + j).text(opponent);
}
}
}
}
function markWin() {
var arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[1, 4, 7],
[2, 5, 8],
[3, 6, 9],
[1, 5, 9],
[3, 5, 7]
];
for (var i = 0; i < arr.length; i++) {
if ($('.' + 'b' + arr[i][0] + ':contains("O")').length > 0 && $('.' + 'b' + arr[i][1] + ':contains("O")').length > 0 && $('.' + 'b' + arr[i][2] + ':contains("O")').length > 0) {
$('.' + 'b' + arr[i][0]).css("background", "green");
$('.' + 'b' + arr[i][1]).css("background", "green");
$('.' + 'b' + arr[i][2]).css("background", "green");
i = arr.length;
}
} //checks O win
for (var j = 0; j < arr.length; j++) {
if ($('.' + 'b' + arr[j][0] + ':contains("X")').length > 0 && $('.' + 'b' + arr[j][1] + ':contains("X")').length > 0 && $('.' + 'b' + arr[j][2] + ':contains("X")').length > 0) {
$('.' + 'b' + arr[j][0]).css("background", "green");
$('.' + 'b' + arr[j][1]).css("background", "green");
$('.' + 'b' + arr[j][2]).css("background", "green");
j = arr.length;
}
} //checks X win
return false;
}
//[0,0] [0,1] [0,2]
//[1,0] [1,1] [1,2]
//[2,0] [2,1] [2,2]
function minimax(board, player) {
nodes++;
var winner = checkWin(board);
if (winner !== null) {
switch (winner) {
case 1:
// AI wins
return [1, board];
case 0:
// opponent wins
return [-1, board];
case -1:
// Tie
return [0, board];
}
} else {
// Next states
var nextVal = null;
var nextBoard = null;
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (board[i][j] === null) {
board[i][j] = player;
var value = minimax(board, !player)[0];
if ((player && (nextVal === null || value > nextVal)) || (!player && (nextVal === null || value < nextVal))) {
nextBoard = board.map(function(arr) {
return arr.slice();
});
nextVal = value;
}
board[i][j] = null;
}
}
}
return [nextVal, nextBoard];
}
}
function minimaxMove(board) {
nodes = 0;
return minimax(board, true)[1];
}
function makeMove() {
board = minimaxMove(board);
console.log(nodes);
myMove = false;
if (nodes !== 1) {
updateMove();
}
}
这是我的代码的codepen链接: http://codepen.io/makkBit/pen/JXgdEo/