简体   繁体   中英

JS code runs slow on codepen, though it runs good locally

I have implemented minimax algorithm for an unbeatable tic toc toe game. The minimax algorithm is recursive, performing big iterations, which are not big for the computer, only big for humans. The very first step takes about 3 seconds to perform on codepen, but performs instantly on my computer locally. what's wrong? is my code not efficient? or it's a problem on codepen? How do it make it efficient on codepen? Here's my JS code:

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

Here's the codepen link of my code: http://codepen.io/makkBit/pen/JXgdEo/

Use a profiler to pinpoint where the code is slow.

Here's the profiler result using Google Chrome.

The problem seems to start from the function minimaxMove .

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM