JS代码在codepen上运行缓慢,尽管它在本地运行良好

时间:2016-05-24 20:01:11

标签: javascript jquery

我已经为无与伦比的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/

1 个答案:

答案 0 :(得分:4)

使用分析器确定代码缓慢的位置。

以下是使用谷歌浏览器的分析器结果。

问题似乎从函数minimaxMove开始。

enter image description here