gpt4 book ai didi

javascript - 调用函数时创建 Web Worker | JavaScript

转载 作者:行者123 更新时间:2023-11-28 03:48:59 25 4
gpt4 key购买 nike

我有一个 Tic Tac Toe 3D 游戏,我想对其进行优化,因为此时它使我的网络浏览器崩溃。它使用 MiniMax alpha-beta-pruning 算法,我将代码分成 3 个不同的文件:

TTT3D
|-js
|---init.js # 我在其中定义所有变量(如winingCombos、人类、计算机等)
|---worker.js # miniMax 算法,最后,我将 choice 变量作为消息发送
|---ticAlpha.js # 工作线程已构建并尝试获取响应
|-index.html

这是代码:

index.html

<!DOCTYPE html>
<html>
<head>
<title>Tic Tac Toe 3D</title>
<link rel="stylesheet" type="text/css" href="css/main.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<meta charset="utf-8">
</head>
<body>
<section id="intro">
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2" style="text-align: center;">
<h1>Hi there! Let's play <b>Tic Tac Toe</b>! Choose your player!</h1>
<button value="X" id="X" onclick="startGame('X')">X</button>
<button value="O" id="O" onclick="startGame('O')">O</button>
</div>
</div>
</div>
</section>

<section id="board" class="hidden">
<div class="container">
<div class="row bottom">
<div class="col-md-3"></div>
<div class="col-md-2 boxContent">
<ul>
<li>
<h2>X</h2>
</li>
<li style="float: right !important;">
<input type="text" name="xPlayerScore" id="xPlayerScore" value="-" readonly>
</li>
</ul>
</div>

<div class="col-md-2 boxContent">
<ul>
<li>
<h2>O</h2>
</li>
<li style="float: right !important;">
<input type="text" name="oPlayerScore" id="oPlayerScore" value="-" readonly>
</li>
</ul>
</div>
<button class="col-md-2" onclick="playAgain()" style="margin-left: 7px;">
<img src="images/again.png" width="16">
Play Again
</button>


<div class="col-md-3"></div>
</div>
</div>

<div class="canvas1">
<div class="row">
<div class="tile" boardcol="0" boardrow="0" boardlevel="0" onclick="makeMove(0)" id="0"></div>
<div class="tile" boardcol="1" boardrow="0" boardlevel="0" onclick="makeMove(1)" id="1"></div>
<div class="tile" boardcol="2" boardrow="0" boardlevel="0"onclick="makeMove(2)" id="2"></div>
</div>
<div class="row">
<div class="tile" boardcol="0" boardrow="1" boardlevel="0"onclick="makeMove(3)" id="3"></div>
<div class="tile" boardcol="1" boardrow="1" boardlevel="0"onclick="makeMove(4)" id="4"></div>
<div class="tile" boardcol="2" boardrow="1" boardlevel="0"onclick="makeMove(5)" id="5"></div>
</div>
<div class="row">
<div class="tile" boardcol="0" boardrow="2" boardlevel="0"onclick="makeMove(6)" id="6"></div>
<div class="tile" boardcol="1" boardrow="2" boardlevel="0"onclick="makeMove(7)" id="7"></div>
<div class="tile" boardcol="2" boardrow="2" boardlevel="0"onclick="makeMove(8)" id="8"></div>
</div>
</div>

<div class="canvas2">
<div class="row">
<div class="tile" boardcol="0" boardrow="0" boardlevel="1"onclick="makeMove(9)" id="9"></div>
<div class="tile" boardcol="1" boardrow="0" boardlevel="1"onclick="makeMove(10)" id="10"></div>
<div class="tile" boardcol="2" boardrow="0" boardlevel="1"onclick="makeMove(11)" id="11"></div>
</div>
<div class="row">
<div class="tile" boardcol="0" boardrow="1" boardlevel="1"onclick="makeMove(12)" id="12"></div>
<div class="tile" boardcol="1" boardrow="1" boardlevel="1"onclick="makeMove(13)" id="13"></div>
<div class="tile" boardcol="2" boardrow="1" boardlevel="1"onclick="makeMove(14)" id="14"></div>
</div>
<div class="row">
<div class="tile" boardcol="0" boardrow="2" boardlevel="1"onclick="makeMove(15)" id="15"></div>
<div class="tile" boardcol="1" boardrow="2" boardlevel="1"onclick="makeMove(16)" id="16"></div>
<div class="tile" boardcol="2" boardrow="2" boardlevel="1"onclick="makeMove(17)" id="17"></div>
</div>
</div>

<div class="canvas3">
<div class="row">
<div class="tile" boardcol="0" boardrow="0" boardlevel="2"onclick="makeMove(18)" id="18"></div>
<div class="tile" boardcol="1" boardrow="0" boardlevel="2"onclick="makeMove(19)" id="19"></div>
<div class="tile" boardcol="2" boardrow="0" boardlevel="2"onclick="makeMove(20)" id="20"></div>
</div>
<div class="row">
<div class="tile" boardcol="0" boardrow="1" boardlevel="2"onclick="makeMove(21)" id="21"></div>
<div class="tile" boardcol="1" boardrow="1" boardlevel="2"onclick="makeMove(22)" id="22"></div>
<div class="tile" boardcol="2" boardrow="1" boardlevel="2"onclick="makeMove(23)" id="23"></div>
</div>
<div class="row">
<div class="tile" boardcol="0" boardrow="2" boardlevel="2"onclick="makeMove(24)" id="24"></div>
<div class="tile" boardcol="1" boardrow="2" boardlevel="2"onclick="makeMove(25)" id="25"></div>
<div class="tile" boardcol="2" boardrow="2" boardlevel="2"onclick="makeMove(26)" id="26"></div>
</div>
</div>
</section>



<script src="https://code.jquery.com/jquery-3.1.1.js"
integrity="sha256-16cdPddA6VdVInumRGo6IbivbERE8p7CQR3HzTBuELA="
crossorigin="anonymous"></script>
<script src="js/init.js"></script>
<script src="js/ticAlpha.js"></script>
</body>
</html>

init.js

var winningCombos   = new Array();

winningCombos[0] = [0, 1, 2];
winningCombos[1] = [3, 4, 5];
winningCombos[2] = [6, 7, 8];

// Per columns

winningCombos[3] = [0, 3, 6];
winningCombos[4] = [1, 4, 7];
winningCombos[5] = [2, 5, 8];

// Diagonals

winningCombos[6] = [0, 4, 8];
winningCombos[7] = [2, 4, 6];


// Second board

//Per lines

winningCombos[8] = [9, 10, 11];
winningCombos[9] = [12, 13, 14];
winningCombos[10] = [15, 16, 17];

// Per columns

winningCombos[11] = [9, 12, 15];
winningCombos[12] = [10, 13, 16];
winningCombos[13] = [11, 14, 17];

// Diagonals

winningCombos[14] = [9, 13, 17];
winningCombos[15] = [11, 13, 15];


// Third board

// Per lines

winningCombos[16] = [18, 19, 20];
winningCombos[17] = [21, 22, 23];
winningCombos[18] = [24, 25, 26];

// Per columns

winningCombos[19] = [18, 21, 24];
winningCombos[20] = [19, 22, 25];
winningCombos[21] = [20, 23, 26];

// Diagonals

winningCombos[22] = [18, 22, 26];
winningCombos[23] = [20, 22, 24];


// 3D Winning

winningCombos[24] = [0, 13, 26];
winningCombos[25] = [20, 13, 6];

// Per lines

winningCombos[26] = [0, 10, 20];
winningCombos[27] = [3, 13, 23];
winningCombos[28] = [6, 16, 26];

var free = ' ';
var boardSize = 27;
var board = new Array();
var activePlayer = 'Human';
var i;
var choice;
var human;
var humanTurn;
var computer;
var computerTurn;
var humanWin = 0;
var computerWin = 0;

$(document).ready(function() {
$("button").click(function(){
$("#intro").addClass("hidden");
$("#board").removeClass("hidden");
});
});

function startGame(player) {
for (i = 0; i < boardSize; i += 1) {
board[i] = free;
}

activePlayer = 'Human';

if (player == "X") {
human = "X";
humanTurn = "<p>X</p>";
computer = "O";
computerTurn = "<p>O</p>";
} else {
human = "O";
humanTurn = "<p>O</p>";
computer = "X";
computerTurn = "<p>X</p>";
}
}

ticAlpha.js

function makeMove(pos) {
if (board[pos] === free && !gameOver(board)) {
board[pos] = human;
document.getElementById(pos).innerHTML = humanTurn;

if (!gameOver(board)) {
activePlayer = 'Computer';
makeComputerMove();
}
}
}

function makeComputerMove() {
// miniMax(board, 0, -Infinity, +Infinity);

var worker = new Worker('worker.js');
worker.postMessage('its time');

worker.onmessage = function(event) {
var move = event.data;
};

board[move] = computer;
document.getElementById(move).innerHTML = computerTurn;
choice = [];
activePlayer = 'Human';
}

function score(possibleGame) {
var score = getWinner(possibleGame);

if (score === 3) {
return 0;
} else if (score === 1) {
return -1;
} else if (score === 2) {
return 1;
}
}

function miniMax(node, depth, alpha, beta) {
if (getWinner(node) !== 0) {
return score(node);
}

depth += 1;
// var scores = new Array();
// var moves = new Array();
var availableMoves = getAvailableMoves(node);
var move, result, possibleGame;
if (activePlayer === 'Computer'){
for (var i = 0; i < availableMoves.length; i += 1) {
move = availableMoves[i];
possibleGame = generateNewGame(move, node);
result = miniMax(possibleGame, depth, alpha, beta);
node = undoMove(node, move);

if (result > alpha) {
alpha = result;
if (depth === 1) {
choice = move;
} else if (alpha >= beta) {
return alpha;
}
}
}
return alpha;
} else if (activePlayer === 'Human') {
for (var i = 0; i < availableMoves.length; i += 1) {
move = availableMoves[i];
possibleGame = generateNewGame(move, node);
result = miniMax(possibleGame, depth, alpha, beta);
node = undoMove(node, move);

if (result < beta) {
beta = result;
if (depth === 1) {
choice = move;
} else if (alpha >= beta) {
return beta;
}
}
}

return beta;
}
}

function undoMove(possibleGame, move) {
possibleGame[move] = free;
changePlayerTurn();
return possibleGame;
}

function getAvailableMoves(tempBoard) {
var availableMoves = new Array();
for (var i = 0; i < boardSize; i += 1) {
if (board[i] === free) {
availableMoves.push(i);
}
}
return availableMoves;
}

function generateNewGame(move, possibleGame) {
var piece = changePlayerTurn();
possibleGame[move] = piece;
return possibleGame;
}

function changePlayerTurn() {
var turn;
if (activePlayer === 'Computer') {
turn = computer;
activePlayer = 'Human';
} else {
turn = human;
activePlayer = 'Computer';
}

return turn;
}

function gameOver(tempBoard) {
if (getWinner(tempBoard) === 0) {
return 0;
} else if (getWinner(tempBoard) === 1) {
alert("You won!");
humanWin += 1;
if (human === "X") {
document.getElementById("xPlayerScore").value = humanWin;
} else {
document.getElementById("oPlayerScore").value = humanWin;
}
} else if (getWinner(tempBoard) === 2) {
alert("Computer won!");
computerWin += 1;
if (computer === "X") {
document.getElementById("xPlayerScore").value = computerWin;
} else {
document.getElementById("oPlayerScore").value = computerWin;
}
} else if (getWinner(tempBoard) === 3) {
alert("The game was a draw!");
}
return 1;
}

function getWinner(tempBoard) {
for (i = 0; i < winningCombos.length; i += 1) {
if (tempBoard[winningCombos[i][0]] === human &&
tempBoard[winningCombos[i][1]] === human &&
tempBoard[winningCombos[i][2]] === human) {
return 1; // human won
} else if (tempBoard[winningCombos[i][0]] === computer &&
tempBoard[winningCombos[i][1]] === computer &&
tempBoard[winningCombos[i][2]] === computer) {
return 2; // computer won
}
}

if (tempBoard.indexOf(free) >= 0) {
return 0; // not finished yet
}

return 3; // the game was a draw
}

function gameOver(tempBoard) {
if (getWinner(tempBoard) === 0) {
return 0;
} else if (getWinner(tempBoard) === 1) {
alert("You won!");
humanWin += 1;
if (human === "X") {
document.getElementById("xPlayerScore").value = humanWin;
} else {
document.getElementById("oPlayerScore").value = humanWin;
}
} else if (getWinner(tempBoard) === 2) {
alert("Computer won!");
computerWin += 1;
if (computer === "X") {
document.getElementById("xPlayerScore").value = computerWin;
} else {
document.getElementById("oPlayerScore").value = computerWin;
}
} else if (getWinner(tempBoard) === 3) {
alert("The game was a draw!");
}
return 1;
}

function getWinner(tempBoard) {
for (i = 0; i < winningCombos.length; i += 1) {
if (tempBoard[winningCombos[i][0]] === human &&
tempBoard[winningCombos[i][1]] === human &&
tempBoard[winningCombos[i][2]] === human) {
return 1; // human won
} else if (tempBoard[winningCombos[i][0]] === computer &&
tempBoard[winningCombos[i][1]] === computer &&
tempBoard[winningCombos[i][2]] === computer) {
return 2; // computer won
}
}

if (tempBoard.indexOf(free) >= 0) {
return 0; // not finished yet
}

return 3; // the game was a draw
}

function playAgain() {
if (getWinner(board) != 0) {
for (var j = 0; j < boardSize; j += 1) {
document.getElementById(j).innerHTML = "";
}
resetBoard();
}
}

function resetBoard() {
for (i = 0; i < boardSize; i += 1) {
board[i] = free;
}
}

worker.js

function miniMax(node, depth, alpha, beta) {
if (getWinner(node) !== 0) {
return score(node);
}

depth += 1;
// var scores = new Array();
// var moves = new Array();
var availableMoves = getAvailableMoves(node);
var move, result, possibleGame;
if (activePlayer === 'Computer'){
for (var i = 0; i < availableMoves.length; i += 1) {
move = availableMoves[i];
possibleGame = generateNewGame(move, node);
result = miniMax(possibleGame, depth, alpha, beta);
node = undoMove(node, move);

if (result > alpha) {
alpha = result;
if (depth === 1) {
choice = move;
} else if (alpha >= beta) {
return alpha;
}
}
}
return alpha;
} else if (activePlayer === 'Human') {
for (var i = 0; i < availableMoves.length; i += 1) {
move = availableMoves[i];
possibleGame = generateNewGame(move, node);
result = miniMax(possibleGame, depth, alpha, beta);
node = undoMove(node, move);

if (result < beta) {
beta = result;
if (depth === 1) {
choice = move;
} else if (alpha >= beta) {
return beta;
}
}
}

return beta;
}
}

function undoMove(possibleGame, move) {
possibleGame[move] = free;
changePlayerTurn();
return possibleGame;
}

function getAvailableMoves(tempBoard) {
var availableMoves = new Array();
for (var i = 0; i < boardSize; i += 1) {
if (board[i] === free) {
availableMoves.push(i);
}
}
return availableMoves;
}

function generateNewGame(move, possibleGame) {
var piece = changePlayerTurn();
possibleGame[move] = piece;
return possibleGame;
}

function changePlayerTurn() {
var turn;
if (activePlayer === 'Computer') {
turn = computer;
activePlayer = 'Human';
} else {
turn = human;
activePlayer = 'Computer';
}

return turn;
}

function gameOver(tempBoard) {
if (getWinner(tempBoard) === 0) {
return 0;
} else if (getWinner(tempBoard) === 1) {
alert("You won!");
humanWin += 1;
if (human === "X") {
document.getElementById("xPlayerScore").value = humanWin;
} else {
document.getElementById("oPlayerScore").value = humanWin;
}
} else if (getWinner(tempBoard) === 2) {
alert("Computer won!");
computerWin += 1;
if (computer === "X") {
document.getElementById("xPlayerScore").value = computerWin;
} else {
document.getElementById("oPlayerScore").value = computerWin;
}
} else if (getWinner(tempBoard) === 3) {
alert("The game was a draw!");
}
return 1;
}

function getWinner(tempBoard) {
for (i = 0; i < winningCombos.length; i += 1) {
if (tempBoard[winningCombos[i][0]] === human &&
tempBoard[winningCombos[i][1]] === human &&
tempBoard[winningCombos[i][2]] === human) {
return 1; // human won
} else if (tempBoard[winningCombos[i][0]] === computer &&
tempBoard[winningCombos[i][1]] === computer &&
tempBoard[winningCombos[i][2]] === computer) {
return 2; // computer won
}
}

if (tempBoard.indexOf(free) >= 0) {
return 0; // not finished yet
}

return 3; // the game was a draw
}

onmessage = function(e) {
miniMax(board, 0, -Infinity, Infinity);
postMessage(choice);
};

问题是变量 move 始终未定义,即使我在 worker.onmessage 内执行 console.log()函数,它不显示任何内容。

这更有可能误解了网络 worker 是什么以及应该使用的概念,但我尝试了超过 24 小时来解决它,但感觉像是 0 进度。如果可能的话,将不胜感激您的帮助。非常感谢!

最佳答案

嗯,一个问题是,您似乎希望工作线程能够访问主线程上可用的所有变量,但事实并非如此。您必须在主线程和工作线程中维护棋盘状态,并通过消息同步它们。这是让工作人员提前并在应用程序的整个生命周期中保持相同的另一个原因。

考虑在 worker.js 中调用 miniMax(board, 0, -Infinity, Infinity);。此调用可能会在线程中引发错误,因为 board 未定义,因此 miniMax 尝试在函数体中访问它并引发错误。

此外,您还可以在工作线程中调用 postMessage(choice),但 choice 并未在任何地方定义。

关于javascript - 调用函数时创建 Web Worker | JavaScript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48195664/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com