我正在尝试使用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;