用于tic tac toe游戏javascript的minimax功能

时间:2017-10-12 14:10:33

标签: javascript jquery algorithm minimax

我正在尝试使用javascript构建tic tac toe游戏,所以基本上我的tic tac toe版本没有AI所以计算机在第一个空位(在bestSpot()函数中可以看到)然后我用一个替换它minimax函数使计算机无与伦比(来自此repo:sourcecode)当我尝试将其与我的代码组合时,我收到错误[请参阅附图] [] 2。我无法确定引发错误的minimax函数是什么问题。任何帮助都会非常明显。 (禁用minimax取消注释bestSpot()函数中的第一行) 注意:请扩展全视图剪辑以跳过页面响应错误。



var currentPlayer = '';
var computerPlayer = '';
var playerSelection = [];
var computerSelection = [];
var boardInputs = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const winCombos = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9],
  [1, 4, 7],
  [2, 5, 8],
  [3, 6, 9],
  [1, 5, 9],
  [7, 5, 3]
]


$(document).ready(function() {

  $('.board').hide();
  $('.restart').hide();
  // $('.mine').hide();
  choseSign();

});

function choseSign() {
  $('.choseSq').on('click', function() {
    var element = $(this).attr('value');
    console.log('element player', element);
    if (element == 'o' || element == 'x') {
      currentPlayer += element;
      $('.mine').fadeOut(500);
      $('.board').fadeIn(3000);
      if (currentPlayer === 'x') {
        computerPlayer = 'o';
      } else {
        computerPlayer = 'x';
      }
      startGame();
    }
  });
}

function startGame() {
  document.getElementById('tictactoe').style.pointerEvents = 'auto';
  $('.square').on('click', function() {
    var element2 = $(this).attr('value');
    var myIndex = playerSelection.indexOf(parseInt(element2));
    var comIndex = computerSelection.indexOf(parseInt(element2));

    if (myIndex === -1 && comIndex === -1) {
      if (currentPlayer == 'o') {
        $(this).append("<img src='http://www.dreamincode.net/forums/uploads/monthly_10_2010/post-0-12884151170642.png'/>");
        boardInputs[parseInt(element2) - 1] = currentPlayer;
        console.log('board: ', boardInputs);
      } else {
        $(this).append("<img src='http://www.dreamincode.net/forums/uploads/post-97990-1260678617.png'/>");
        boardInputs[parseInt(element2) - 1] = currentPlayer;
        console.log('board: ', boardInputs);
      }

      playerSelection.push(parseInt(element2));
      console.log('current player: ', playerSelection);
      let gameWon = checkWin(boardInputs, currentPlayer);
      if (gameWon) {
        gameOver(gameWon, 'you won');
      } else if (playerSelection.length < 6) {
        document.getElementById('tictactoe').style.pointerEvents = 'none';
        console.log('##CUR PLY: ', currentPlayer, '$$%AI PLY: ', computerPlayer)
        setTimeout(() => {
          computerTurn(bestSpot(), computerPlayer);
        }, 1000);
      }
    } else {
      console.log('Position Taken !');
    }
  });

}


function computerTurn(squareId, player) {
  document.getElementById('tictactoe').style.pointerEvents = 'auto';
  //var random_number = Math.floor(Math.random() * (9 - 1 + 1)) + 1;
  console.log("SQR_ID: ", squareId);
  //boardInputs[squareId] = computerPlayer;
  var playerIndex = playerSelection.indexOf(squareId);
  var computerIndex = computerSelection.indexOf(squareId);
  var generatePosition = '.sq';

  if (playerIndex === -1 && computerIndex === -1) {
    computerSelection.push(squareId);
    generatePosition += squareId
    console.log("genPos: ", generatePosition);

    if (currentPlayer === 'x') {
      $(generatePosition).append("<img src='http://www.dreamincode.net/forums/uploads/monthly_10_2010/post-0-12884151170642.png'/>");
      boardInputs[squareId - 1] = computerPlayer;
    } else {
      $(generatePosition).append("<img src='http://www.dreamincode.net/forums/uploads/post-97990-1260678617.png'/>");
      boardInputs[squareId - 1] = computerPlayer;
    }
    console.log('board: ', boardInputs);
    let gameWon = checkWin(boardInputs, computerPlayer);
    if (gameWon) {
      gameOver(gameWon, 'Computer won');
    }

  } else {
    if (computerSelection.length < 4) {
      computerTurn(bestSpot(), computerPlayer);
    } else {
      console.log('it\'s a -- DRAW -- Game Finished');
      console.log('board result', boardInputs);


      $('.status').text('its a draw');
      $('.restart').show();
      $('.RestartBtn').on('click', function() {
        clearGame();
        $('.restart').hide();
      });
    }
  }
  console.log("computer board: ", computerSelection);

}

function clearGame() {
  for (i = 1; i < 10; i++) {
    var sq = '.sq' + i;
    $(sq).text('');
    $(sq).css("background-color", "rgb(248, 248, 248)");
  }

  $('.board').hide();
  $('.mine').fadeIn(1500);
  currentPlayer = '';
  computerPlayer = '';
  playerSelection = [];
  computerSelection = [];
  boardInputs = [];
  boardInputs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
}

function checkWin(board, player) {
  let plays = board.reduce((a, e, i) =>
    (e === player) ? a.concat(i + 1) : a, []);
  let gameWon = null;
  for (let [index, win] of winCombos.entries()) {
    if (win.every(elem => plays.indexOf(elem) > -1)) {
      gameWon = {
        index: index,
        player: player
      };
      break;
    }
  }
  return gameWon;
}

function gameOver(gameWon, status) {
  document.getElementById('tictactoe').style.pointerEvents = 'none';
  for (let index of winCombos[gameWon.index]) {
    var square = '.sq' + index;
    $(square).css("background-color", "rgb(41, 168, 62)");
  }

  setTimeout(() => {
    $('.status').text(status);
    $('.restart').show();
    // $('.board').hide();

  }, 1000);

  $('.RestartBtn').on('click', function() {
    clearGame();
    $('.restart').hide();
  });

}

function emptySquares() {
  // console.log('emt func')    
  return boardInputs.filter(s => typeof s === 'number');
  // return boardInputs.filter((elm, i) => i === elm);
}

function bestSpot() {
  // return emptySquares()[0];  // uncomment to disable minimax algorithem
  return minimax(boardInputs, computerPlayer).index; // comment to disable minimax 
}

function minimax(newBoard, player) {
  var availSpots = emptySquares(newBoard);
  console.log('aviSpt: ', availSpots);


  if (checkWin(newBoard, currentPlayer)) {
    return {
      score: -10
    };
  } else if (checkWin(newBoard, computerPlayer)) {
    return {
      score: 10
    };
  } else if (availSpots.length === 0) {
    return {
      score: 0
    };
  }
  var moves = [];
  for (var i = 0; i < availSpots.length; i++) {
    var move = {};
    move.index = newBoard[availSpots[i]];
    newBoard[availSpots[i]] = player;

    if (player == computerPlayer) {
      var result = minimax(newBoard, currentPlayer);
      move.score = result.score;
    } else {
      var result = minimax(newBoard, computerPlayer);
      move.score = result.score;
    }

    newBoard[availSpots[i]] = move.index;

    moves.push(move);
  }

  var bestMove;
  if (player === computerPlayer) {
    var bestScore = -10000;
    for (var i = 0; i < moves.length; i++) {
      if (moves[i].score > bestScore) {
        bestScore = moves[i].score;
        bestMove = i;
      }
    }
  } else {
    var bestScore = 10000;
    for (var i = 0; i < moves.length; i++) {
      if (moves[i].score < bestScore) {
        bestScore = moves[i].score;
        bestMove = i;
      }
    }
  }

  return moves[bestMove];
}
&#13;
body {
  background: rgb(248, 248, 248);
  text-transform: capitalize;
  font-family: 'Architects Daughter', cursive;
}

.game {
  width: 433px;
  height: 433px;
}

.board {
  align-items: center;
  align-content: center;
  height: 399px;
  width: 399px;
  margin: auto;
  margin-top: 20px;
}


/* .restart{
    border: 2px solid rgb(201, 23, 23);
    display: inline-flex;
    height: 149px;
    width: 299px;
    left: 38%;
    background-color: rgb(255, 255, 255);
    margin-bottom:-82px; 
    
} */


/* .extraline{
    border: 2px solid rgb(23, 201, 47);
    position: absolute;
    align-items: center;
    align-content: center;
    height: 149px;
    width: 299px;
    background-color: rgb(255, 255, 255);
    
} */

.chose {
  /* text-transform: capitalize;
    color: rgb(201, 23, 23);
    border: 8px solid rgb(41, 168, 62);
    position: absolute;
    align-items: center;
    align-content: center;
    height: 349px;
    width: 299px;
    margin: auto;
    background-color: rgb(255, 255, 255);
    text-align: center;   
    margin-left: 53px;  */
}

img {
  height: 60px;
  width: 60px;
  margin: 29px 0 0 29px;
}

.center {
  margin: auto;
  width: 40%;
  margin-top: 93px;
}

.square {
  border: 5px solid rgb(201, 23, 23);
  float: left;
  width: 120px;
  height: 120px;
  overflow: hidden;
}

.squarex {
  border: 6px solid red;
  float: left;
  position: relative;
  width: 400px;
  height: 1px;
  padding-bottom: 30%;
  /* = width for a 1:1 aspect ratio */
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  /* you change this to "contain" if you don't want the images to be cropped */
  margin-top: -4px;
}

.x2 {
  border: 6px solid green;
  height: 150px;
  width: 400px;
  display: inline-block;
  margin-right: -4px;
}

#rec1 {
  border: 5px solid rgb(41, 168, 62);
  border-top-color: rgb(248, 248, 248);
  border-left-color: rgb(248, 248, 248);
  border-bottom-color: rgb(218, 172, 25);
}

#rec2 {
  border: 5px solid rgb(218, 172, 25);
  border-top-color: rgb(248, 248, 248);
  border-right-color: rgb(137, 60, 153);
  border-bottom-color: rgb(113, 216, 54);
}

#rec3 {
  border-top-color: rgb(248, 248, 248);
  border-right-color: rgb(248, 248, 248);
  border-bottom-color: rgb(153, 60, 77);
}

#rec4 {
  border-left-color: rgb(248, 248, 248);
  border-bottom-color: rgb(248, 248, 248);
  border-right-color: rgb(153, 60, 77);
  border-top-color: rgb(0, 162, 211);
}

#rec5 {
  border-bottom-color: rgb(248, 248, 248);
  border-right-color: rgb(39, 131, 173);
  border-top-color: rgb(176, 0, 211);
  border-left-color: rgb(68, 187, 161);
  text-align: center;
  color: rgb(209, 16, 16);
  font-size: 25px;
  font-weight: bold;
}

#rec6 {
  border-right-color: rgb(248, 248, 248);
  border-bottom-color: rgb(248, 248, 248);
  border-left-color: rgb(236, 202, 48);
  border-top-color: rgb(36, 128, 233);
}

.restart {
  position: absolute;
  text-align: center;
}

.choseSq {
  border-radius: 22px;
  margin: auto;
  width: 100px;
  padding-bottom: 25px;
  padding-right: 27px;
  display: inline;
}

.choseSq:hover {
  background-color: rgb(255, 223, 223);
}

.sq1 {
  border: 5px solid rgb(25, 116, 103);
  border-top-color: rgb(248, 248, 248);
  border-left-color: rgb(248, 248, 248);
}

.sq2 {
  border: 5px solid rgb(39, 131, 173);
  border-top-color: rgb(248, 248, 248);
}

.sq3 {
  border: 5px solid rgb(236, 202, 48);
  border-top-color: rgb(248, 248, 248);
  border-right-color: rgb(248, 248, 248);
}

.sq4 {
  border: 5px solid rgb(151, 153, 60);
  border-left-color: rgb(248, 248, 248);
}

.sq5 {
  border: 5px solid rgb(153, 60, 77);
}

.sq6 {
  border: 5px solid rgb(60, 69, 153);
  border-right-color: rgb(248, 248, 248);
}

.sq7 {
  border: 5px solid rgb(137, 60, 153);
  border-left-color: rgb(248, 248, 248);
  border-bottom-color: rgb(248, 248, 248);
}

.sq8 {
  border: 5px solid rgb(218, 172, 25);
  border-bottom-color: rgb(248, 248, 248);
}

.sq9 {
  border: 5px solid rgb(41, 168, 62);
  border-right-color: rgb(248, 248, 248);
  border-bottom-color: rgb(248, 248, 248);
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title></title>
  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="style.css">
  <link href="https://fonts.googleapis.com/css?family=Architects+Daughter" rel="stylesheet">
</head>

<body>
  <!--[if lt IE 7]>
            <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
  <div class="restart">
    <h1 class="status"></h1>
    <h2>Restart the game?</h2>
    <button class='RestartBtn'>Restart</button>
  </div>
  <div class="mine">
    <div id="rec1" class="x2">
    </div>
    <div id="rec2" class="x2">

    </div>
    <div id="rec3" class="x2">
    </div>

    <div id="rec4" class="squarex">
    </div>

    <div id="rec5" class="squarex ">
      <h2>Please Chose a sign to start a game</h2>
      <div class=" choseSq" value="x">
        <img src="http://www.dreamincode.net/forums/uploads/post-97990-1260678617.png" />
      </div>
      <div class=" choseSq" value="o">
        <img src="http://www.dreamincode.net/forums/uploads/monthly_10_2010/post-0-12884151170642.png" />
      </div>
    </div>

    <div id="rec6" class="squarex">
    </div>
  </div>

  <div class="game center">
    <div class="board" id='tictactoe'>
      <div class="square sq1" value="1">
      </div>
      <div class="square sq2" value="2">
      </div>
      <div class="square sq3" value="3">
      </div>
      <div class="square sq4" value="4">
      </div>
      <div class="square sq5" value="5">
      </div>
      <div class="square sq6" value="6">
      </div>
      <div class="square sq7" value="7">
      </div>
      <div class="square sq8" value="8">
      </div>
      <div class="square sq9" value="9">
      </div>
    </div>

  </div>

  <script src="script.js" type="text/javascript"></script>
</body>

</html>
&#13;
&#13;
&#13;

0 个答案:

没有答案