井字游戏中计算机的随机位置选择无法正常工作
Posted
技术标签:
【中文标题】井字游戏中计算机的随机位置选择无法正常工作【英文标题】:Random Position Choosing for Computer in Tic-Tac-Toe not Working How It's Supposed to 【发布时间】:2020-04-15 05:47:10 【问题描述】:好的,我曾一度用 Python 制作了一个非常简单的井字游戏,而且非常有趣,所以我想我会为它加点趣味并用 html/JS/CSS 来制作它漂亮一点。进展非常顺利,但是在为游戏制作简单的“AI”时遇到了一点小问题。游戏的简单 AI 应该是完全随机的,确实如此,但有时它会占据一个已经被占用的方格,有时它根本不动,所以我知道这可能很简单,我只是不知道是什么。我认为它可能在这段代码中的某个地方,但我不知道:
function computerEasyModeMove()
if(player == 'x')
computer = 'o';
if(player == 'o')
computer = 'x';
var computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 1 && (topLeftBox.innerHTML == 'o' || topLeftBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 2 && (topMiddleBox.innerHTML == 'o' || topMiddleBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 3 && (topRightBox.innerHTML == 'o' || topRightBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 4 && (middleLeftBox.innerHTML == 'o' || middleLeftBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 5 && (middleMiddleBox.innerHTML == 'o' || middleMiddleBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 6 && (middleRightBox.innerHTML == 'o' || middleRightBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 7 && (bottomLeftBox.innerHTML == 'o' || bottomLeftBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 8 && (bottomMiddleBox.innerHTML == 'o' || bottomMiddleBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 9 && (bottomRightBox.innerHTML == 'o' || bottomRightBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
if(computerMove == 1)
topLeftBox.innerHTML = computer;
topLeftBox.style.pointerEvents = 'none';
if(computerMove == 2)
topMiddleBox.innerHTML = computer;
topMiddleBox.style.pointerEvents = 'none';
if(computerMove == 3)
topRightBox.innerHTML = computer;
topRightBox.style.pointerEvents = 'none';
if(computerMove == 4)
middleLeftBox.innerHTML = computer;
middleLeftBox.style.pointerEvents = 'none';
if(computerMove == 5)
middleMiddleBox.innerHTML = computer;
middleMiddleBox.style.pointerEvents = 'none';
if(computerMove == 6)
middleRightBox.innerHTML = computer;
middleRightBox.style.pointerEvents = 'none';
if(computerMove == 7)
bottomLeftBox.innerHTML = computer;
bottomLeftBox.style.pointerEvents = 'none';
if(computerMove == 8)
bottomMiddleBox.innerHTML = computer;
bottomMiddleBox.style.pointerEvents = 'none';
if(computerMove == 9)
bottomRightBox.innerHTML = computer;
bottomRightBox.style.pointerEvents = 'none';
这基本上是我用于简易 AI 的代码,完整代码如下。我觉得我的比赛看起来不错。如果你想尝试一下,我一直在 repl.it 上制作它,(https://repl.it/@AnthonyRobinso2/Tic-Tac-Toe-HTMLJS) 如果这样更容易帮助我。我还在开发这款游戏,以及更难的 AI 模式,所以我仍然需要完成这些,但我想要一个可玩的游戏,即使它真的很容易。再次感谢!
HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<center>
<div id='setup'>
Hey! Welcome to my Tic-Tac-Toe game! Please choose some settings below!
<br>
<div class='xOrO'>
<h3>Player:</h3>
Do you want to be X's?<input type='checkbox' id='Xs' value='X' onchange='player = "x"'>
Or do you want to be O's?<input type='checkbox' id='Os' value='O' onchange='player = "o"'>
<h3>Opponent AI Level:</h3>
Easy<input type='checkbox' id='easy' value='easyMode'>
Medium (Coming Soon)<input type='checkbox' id='medium' value='mediumMode'>
Hard (Coming Soon)<input type='checkbox' id='hard' value='hardMode'>
<br>
<h4>Do you want to go first, or have the computer go first?</h4>
First<input type='checkbox' id='goFirst' value='first' onchange='playerFirst = true'>
  Second<input type='checkbox' id='goSecond' value='second' onchange='playerFirst = false'>
<br>
<br>
<br>
<button id='confirm' onclick='getGameUp()'>Confirm</button>
</div>
<div id='ticTacBoard'>
<div id='topLeft' onclick='move("topLeft")'> </div>
<div id='topMiddle' onclick='move("topMiddle")'> </div>
<div id='topRight' onclick='move("topRight")'> </div>
<br>
<div id='middleLeft' onclick='move("middleLeft")'> </div>
<div id='middleMiddle' onclick='move("middleMiddle")'> </div>
<div id='middleRight' onclick='move("middleRight")'> </div>
<br>
<div id='bottomLeft' onclick='move("bottomLeft")'> </div>
<div id='bottomMiddle' onclick='move("bottomMiddle")'> </div>
<div id='bottomRight' onclick='move("bottomRight")'> </div>
</div>
<br>
<br>
<br>
<br>
<br>
<div id='winDiv'>
<h1 id='winHeader'>
YOU WON!!!
</h1>
</div>
<div id='lossDiv'>
<h1 id='lossHeader'>
You lost...
</h1>
</div>
<div id='tieDiv'>
<h1 id='tieHeader'>
It's a tie!
</h1>
</div>
</center>
<script src="script.js"></script>
</body>
</html>
var player;
var computer;
var playerFirst;
var topLeftBox = document.getElementById('topLeft');
var topMiddleBox = document.getElementById('topMiddle');
var topRightBox = document.getElementById('topRight');
var middleLeftBox = document.getElementById('middleLeft');
var middleMiddleBox = document.getElementById('middleMiddle');
var middleRightBox = document.getElementById('middleRight');
var bottomLeftBox = document.getElementById('bottomLeft');
var bottomMiddleBox = document.getElementById('bottomMiddle');
var bottomRightBox = document.getElementById('bottomRight');
var winDiv = document.getElementById('winDiv');
var lossDiv = document.getElementById('lossDiv');
var ticTacBoard = document.getElementById('ticTacBoard');
var setup = document.getElementById('setup');
function getGameUp()
setup.style.visibility = "hidden";
ticTacBoard.style.visibility = "visible";
if(playerFirst == false)
computerEasyModeMove();
function move(x)
if(x=='topLeft')
if(topLeftBox.innerHTML != 'o' && topLeftBox.innerHTML != 'x')
topLeftBox.innerHTML = player;
topLeftBox.style.pointerEvents = 'none';
if(x=='topMiddle')
if(topMiddleBox.innerHTML != 'o' && topMiddleBox.innerHTML != 'x')
topMiddleBox.innerHTML = player;
topMiddleBox.style.pointerEvents = 'none';
if(x=='topRight')
if(topRightBox.innerHTML != 'o' && topRightBox.innerHTML != 'x')
topRightBox.innerHTML = player;
topRightBox.style.pointerEvents = 'none';
if(x=='middleLeft')
if(middleLeftBox.innerHTML != 'o' && middleLeftBox.innerHTML != 'x')
middleLeftBox.innerHTML = player;
middleLeftBox.style.pointerEvents = 'none';
if(x=='middleMiddle')
if(middleMiddleBox.innerHTML != 'o' && middleMiddleBox.innerHTML != 'x' )
middleMiddleBox.innerHTML = player;
middleMiddleBox.style.pointerEvents = 'none';
if(x=='middleRight')
if(middleRightBox.innerHTML != 'o' && middleRightBox.innerHTML != 'x')
middleRightBox.innerHTML = player;
middleRightBox.style.pointerEvents = 'none';
if(x=='bottomLeft')
if(bottomLeftBox.innerHTML != 'o' && bottomLeftBox.innerHTML != 'x')
bottomLeftBox.innerHTML = player;
bottomLeftBox.style.pointerEvents = 'none';
if(x=='bottomMiddle')
if(bottomMiddleBox.innerHTML != 'o' && bottomMiddleBox.innerHTML != 'x')
bottomMiddleBox.innerHTML = player;
bottomMiddleBox.style.pointerEvents = 'none';
if(x=='bottomRight')
if(bottomRightBox.innerHTML != 'o' && bottomRightBox.innerHTML != 'x')
bottomRightBox.innerHTML = player;
bottomRightBox.style.pointerEvents = 'none';
checkWinCondition();
if(winDiv.style.visibility != 'visible')
computerEasyModeMove();
checkWinCondition();
function computerEasyModeMove()
if(player == 'x')
computer = 'o';
if(player == 'o')
computer = 'x';
var computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 1 && (topLeftBox.innerHTML == 'o' || topLeftBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 2 && (topMiddleBox.innerHTML == 'o' || topMiddleBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 3 && (topRightBox.innerHTML == 'o' || topRightBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 4 && (middleLeftBox.innerHTML == 'o' || middleLeftBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 5 && (middleMiddleBox.innerHTML == 'o' || middleMiddleBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 6 && (middleRightBox.innerHTML == 'o' || middleRightBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 7 && (bottomLeftBox.innerHTML == 'o' || bottomLeftBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 8 && (bottomMiddleBox.innerHTML == 'o' || bottomMiddleBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 9 && (bottomRightBox.innerHTML == 'o' || bottomRightBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
if(computerMove == 1)
topLeftBox.innerHTML = computer;
topLeftBox.style.pointerEvents = 'none';
if(computerMove == 2)
topMiddleBox.innerHTML = computer;
topMiddleBox.style.pointerEvents = 'none';
if(computerMove == 3)
topRightBox.innerHTML = computer;
topRightBox.style.pointerEvents = 'none';
if(computerMove == 4)
middleLeftBox.innerHTML = computer;
middleLeftBox.style.pointerEvents = 'none';
if(computerMove == 5)
middleMiddleBox.innerHTML = computer;
middleMiddleBox.style.pointerEvents = 'none';
if(computerMove == 6)
middleRightBox.innerHTML = computer;
middleRightBox.style.pointerEvents = 'none';
if(computerMove == 7)
bottomLeftBox.innerHTML = computer;
bottomLeftBox.style.pointerEvents = 'none';
if(computerMove == 8)
bottomMiddleBox.innerHTML = computer;
bottomMiddleBox.style.pointerEvents = 'none';
if(computerMove == 9)
bottomRightBox.innerHTML = computer;
bottomRightBox.style.pointerEvents = 'none';
function computerMediumModeMove()
function computerHardModeMove()
function checkWinCondition()
//Top 3 Player
if(topLeftBox.innerHTML == player && topMiddleBox.innerHTML == player && topRightBox.innerHTML == player)
ticTacBoard.style.pointerEvents = 'none';
winDiv.style.visibility = 'visible';
//Top 3 Computer
if(topLeftBox.innerHTML == computer && topMiddleBox.innerHTML == computer && topRightBox.innerHTML == computer)
ticTacBoard.style.pointerEvents = 'none';
lossDiv.style.visibility = 'visible';
//Middle 3 Player
if(middleLeftBox.innerHTML == player && middleMiddleBox.innerHTML == player && middleRightBox.innerHTML == player)
ticTacBoard.style.pointerEvents = 'none';
winDiv.style.visibility = 'visible';
//Middle 3 Computer
if(middleLeftBox.innerHTML == computer && middleMiddleBox.innerHTML == computer && middleRightBox.innerHTML == computer)
ticTacBoard.style.pointerEvents = 'none';
lossDiv.style.visibility = 'visible';
//Bottom 3 Player
if(bottomLeftBox.innerHTML == player && bottomMiddleBox.innerHTML == player && bottomRightBox.innerHTML == player)
ticTacBoard.style.pointerEvents = 'none';
winDiv.style.visibility = 'visible';
//Bottom 3 Computer
if(bottomLeftBox.innerHTML == computer && bottomMiddleBox.innerHTML == computer && bottomRightBox.innerHTML == computer)
ticTacBoard.style.pointerEvents = 'none';
lossDiv.style.visibility = 'visible';
//Left 3 Player (Up and Down)
if(bottomLeftBox.innerHTML == player && topLeftBox.innerHTML == player && middleLeftBox.innerHTML == player)
ticTacBoard.style.pointerEvents = 'none';
winDiv.style.visibility = 'visible';
//Left 3 Computer (Up and Down)
if(bottomLeftBox.innerHTML == computer && topLeftBox.innerHTML == computer && middleLeftBox.innerHTML == computer)
ticTacBoard.style.pointerEvents = 'none';
lossDiv.style.visibility = 'visible';
//Middle 3 Player (Up and Down)
if(bottomMiddleBox.innerHTML == player && topMiddleBox.innerHTML == player && middleMiddleBox.innerHTML == player)
ticTacBoard.style.pointerEvents = 'none';
winDiv.style.visibility = 'visible';
//Middle 3 Computer (Up and Down)
if(bottomMiddleBox.innerHTML == computer && topMiddleBox.innerHTML == computer && middleMiddleBox.innerHTML == computer)
ticTacBoard.style.pointerEvents = 'none';
lossDiv.style.visibility = 'visible';
//Right 3 Player (Up and Down)
if(bottomRightBox.innerHTML == player && topRightBox.innerHTML == player && middleRightBox.innerHTML == player)
ticTacBoard.style.pointerEvents = 'none';
winDiv.style.visibility = 'visible';
//Right 3 Computer (Up and Down)
if(bottomRightBox.innerHTML == computer && topRightBox.innerHTML == computer && middleRightBox.innerHTML == computer )
ticTacBoard.style.pointerEvents = 'none';
lossDiv.style.visibility = 'visible';
//Diagonal Left to Right Player (Down Slope)
if(bottomRightBox.innerHTML == player && topLeftBox.innerHTML == player && middleMiddleBox.innerHTML == player)
ticTacBoard.style.pointerEvents = 'none';
winDiv.style.visibility = 'visible';
//Diagonal Left to Right Computer (Down Slope)
if(bottomRightBox.innerHTML == computer && topLeftBox.innerHTML == computer && middleMiddleBox.innerHTML == computer)
ticTacBoard.style.pointerEvents = 'none';
lossDiv.style.visibility = 'visible';
//Diagonal Right to Left Player (Up Slope)
if(bottomLeftBox.innerHTML == player && topRightBox.innerHTML == player && middleMiddleBox.innerHTML == player)
ticTacBoard.style.pointerEvents = 'none';
winDiv.style.visibility = 'visible';
//Diagonal Right to Left Computer(Up Slope)
if(bottomLeftBox.innerHTML == computer && topRightBox.innerHTML == computer && middleMiddleBox.innerHTML == computer)
ticTacBoard.style.pointerEvents = 'none';
lossDiv.style.visibility = 'visible';
CSS:
#setup
background-color:white;
height:75vh;
width:75vw;
#ticTacBoard
text-transform:capitalize;
font-size:0vw;
background-color:white;
visibility:hidden;
position:absolute;
top:2vh;
#winDiv
visibility:hidden;
background-color:white;
position:relative;
border:2px solid black;
#lossDiv
visibility:hidden;
background-color:white;
position:relative;
border:2px solid black;
#tieDiv
visibility:hidden;
background-color:white;
position:relative;
border:2px solid black;
#topLeft
display:inline-block;
padding:30px;
border-right:2px solid black;
border-bottom:2px solid black;
width:15vw;
height:15vh;
font-size:9vw;
cursor:pointer;
#topLeft:hover
background-color:lightgrey;
#topMiddle
display:inline-block;
padding:30px;
border-bottom:2px solid black;
width:15vw;
height:15vh;
font-size:9vw;
cursor:pointer;
#topMiddle:hover
background-color:lightgrey;
#topRight
display:inline-block;
padding:30px;
border-left:2px solid black;
border-bottom:2px solid black;
width:15vw;
height:15vh;
font-size:9vw;
cursor:pointer;
#topRight:hover
background-color:lightgrey;
#middleLeft
display:inline-block;
padding:30px;
border-right:2px solid black;
border-bottom:2px solid black;
width:15vw;
height:15vh;
font-size:9vw;
cursor:pointer;
#middleMiddle:hover
background-color:lightgrey;
#middleMiddle
display:inline-block;
padding:30px;
border-bottom:2px solid black;
width:15vw;
height:15vh;
font-size:9vw;
cursor:pointer;
#middleLeft:hover
background-color:lightgrey;
#middleRight
display:inline-block;
padding:30px;
border-left:2px solid black;
border-bottom:2px solid black;
width:15vw;
height:15vh;
font-size:9vw;
cursor:pointer;
#middleRight:hover
background-color:lightgrey;
#bottomLeft
display:inline-block;
padding:30px;
border-right:2px solid black;
width:15vw;
height:15vh;
font-size:9vw;
cursor:pointer;
#bottomLeft:hover
background-color:lightgrey;
#bottomMiddle
display:inline-block;
padding:30px;
width:15vw;
height:15vh;
font-size:9vw;
cursor:pointer;
#bottomMiddle:hover
background-color:lightgrey;
#bottomRight
display:inline-block;
padding:30px;
border-left:2px solid black;
width:15vw;
height:15vh;
font-size:9vw;
cursor:pointer;
#bottomRight:hover
background-color:lightgrey;
body
background-color:grey;
【问题讨论】:
【参考方案1】:发生这种情况是因为您的逻辑存在缺陷。我将使用您的一小部分代码(如下所示):
var computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 1 && (topLeftBox.innerHTML == 'o' || topLeftBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
while(computerMove == 2 && (topMiddleBox.innerHTML == 'o' || topMiddleBox.innerHTML == 'x'))
computerMove = Math.floor(Math.random() * 9) + 1;
考虑这种情况:代码的第一行生成computerMove = 1
并且 topLeftBox
已经填充了“x”或“o”(没关系)。然后,我们转到第二行(第一个while
循环)。因为它检测到topLeftBox
已经被填满,它会随机化一个数字。假设随机化给出computerMove = 2
。然后,由于computerMove
不再是1
,第一个while
循环退出,进入第二个while
循环。为了这个例子,我们假设topMiddleBox
也已经填充了“x”或“o”。它满足循环条件,因此,它随机化一个数字。假设它随机化computerMove = 1
。第二个循环的条件,要求computerMove
的值是2
,没有满足,因此退出循环。问题:它产生了computerMove
的1
和topLeftBox
已经被填充。那是你的代码失败的时候。
我还注意到您提供了所有 div
s 的唯一 ID。但是,在这种特殊情况下,您可以通过为所有 div
s 提供一个可以迭代的类来简化代码。请参阅以下代码,该代码可解决您的问题,并且在您的特定情况下无需为每个 div
提供特定 ID:
JS
let actionBox = document.querySelectorAll('div.action-box')
function computerEasyModeMove()
let randomizeMove = () => Math.floor(Math.random() * 9)
let computerMove = randomizeMove()
computer = player == 'x' ? 'o' : 'x'
while (actionBox[computerMove].innerHTML.trim() != ' ')
computerMove = randomizeMove()
actionBox[computerMove].innerHTML = computer
actionBox[computerMove].style.pointerEvents = 'none'
HTML(在div#ticTacBoard
内)
<div id='topLeft' class='action-box' onclick='move("topLeft")'> </div>
<div id='topMiddle' class='action-box' onclick='move("topMiddle")'> </div>
<div id='topRight' class='action-box' onclick='move("topRight")'> </div>
<br>
<div id='middleLeft' class='action-box' onclick='move("middleLeft")'> </div>
<div id='middleMiddle' class='action-box' onclick='move("middleMiddle")'> </div>
<div id='middleRight' class='action-box' onclick='move("middleRight")'> </div>
<br>
<div id='bottomLeft' class='action-box' onclick='move("bottomLeft")'> </div>
<div id='bottomMiddle' class='action-box' onclick='move("bottomMiddle")'> </div>
<div id='bottomRight' class='action-box' onclick='move("bottomRight")'> </div>
分叉代码:here
【讨论】:
哇!感谢所有的帮助!关于为什么它没有做我认为它正在做的事情的解释真的帮助了我!我还有很多东西要学,但是像你这样的人让我继续我会放弃的项目,我感谢你!【参考方案2】:我还没有测试过,但我认为如果你将其更改为遵循它应该可以工作(将 9 个 while 循环替换为 1 个 while 循环)。想法是确保在已被占用的情况下获取下一个随机单元格。
var computerMove = Math.floor(Math.random() * 9) + 1;
while (computerMove == 1 && (topLeftBox.innerHTML == 'o' || topLeftBox.innerHTML == 'x')
|| (computerMove == 2 && (topMiddleBox.innerHTML == 'o' || topMiddleBox.innerHTML == 'x'))
|| (computerMove == 3 && (topRightBox.innerHTML == 'o' || topRightBox.innerHTML == 'x'))
|| (computerMove == 4 && (middleLeftBox.innerHTML == 'o' || middleLeftBox.innerHTML == 'x'))
|| (computerMove == 5 && (middleMiddleBox.innerHTML == 'o' || middleMiddleBox.innerHTML == 'x'))
|| (computerMove == 6 && (middleRightBox.innerHTML == 'o' || middleRightBox.innerHTML == 'x'))
|| (computerMove == 7 && (bottomLeftBox.innerHTML == 'o' || bottomLeftBox.innerHTML == 'x'))
|| (computerMove == 8 && (bottomMiddleBox.innerHTML == 'o' || bottomMiddleBox.innerHTML == 'x'))
|| (computerMove == 9 && (bottomRightBox.innerHTML == 'o' || bottomRightBox.innerHTML == 'x')))
computerMove = Math.floor(Math.random() * 9) + 1;
【讨论】:
哟!这行得通!谢啦!我喜欢不同的方法有多种答案,而且它们都有效,所以我们都是赢家!我将使用这个,因为它使我的代码与我一直在编写的风格基本相同,而另一个答案现在对我来说更先进。下次我会尝试像其他人说的那样做,因为这似乎是更有效的方式,但这正是我想要的!再次感谢。以上是关于井字游戏中计算机的随机位置选择无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章