为什么我不能根据单选按钮选择执行功能?嵌套函数不起作用:未定义或未使用



我正在自学JavaScript。目标:我希望单选按钮确定要运行哪些函数。我想对函数进行分组,以便某些特定的函数运行,而另一些函数则为其他单选按钮运行。

我意识到我的代码很乱,但我正在学习,我不知道问题是什么。


步骤:

  1. 用户通过单选按钮选择游戏类型-玩家vs玩家或玩家vs电脑
  2. 用户点击提交按钮
  3. 一个值被分配给游戏对象取决于单选按钮的选择
  4. 如果游戏= pvp,那么运行pvp()
  5. 如果游戏= pvc,然后运行pvc()(我还没有写这个,因为步骤4甚至不工作)

在第4步,我得到一个错误,我的一个函数在pvp()中没有定义


如果我删除外部函数pvp(),所有的函数工作完美。

我试图理解为什么当用户选择一个单选按钮时,我的函数没有运行。我不明白为什么我的嵌套函数出现未定义或未使用。

我已经移动了变量,看看是否有一个范围/提升问题。我试过用控制台调试,但什么也没得到。我设置game = "abc"我想在game = "abc"时运行函数。我想在game = "def"时运行其他函数。

我已经查看了window.onload(),它不适用于我的项目。我想。

我确保脚本标签放在我的html的末尾。

代码:

'use-strict';
//declare variables here
let boxs = document.querySelectorAll('.box');
let statusTxt = document.querySelector('#status');
let btnRestart = document.querySelector('#restart');
let btnStart = document.querySelector('#start');
let btnNewGame = document.querySelector('#newGame');
//a timer for seconds when the game starts
//example in the text for the window.onload but I don't want to use that
//I need to start this timer when the first token is placed.....
//set up x and o stamps
//fix the height here because stamps are huge in the game
//I need to figure out how to get the players to be randomly started
/////////////////////////////////////////////////////////////
//which type of game is being played? test radio buttons...
//run functions based on what the value ofgame is...
btnStart.addEventListener("click", e => {
console.log(e);
});
btnNewGame.addEventListener("click", e => {
console.log(e);
});
var game;
//i have a hoisted variable problem
game = "no game radio button";
console.log("test game type at page load = " + game);
function checkGameType() {
btnPVP = document.getElementById("pvp");
btnPVC = document.getElementById("pvc");
btnPVPchecked = document.getElementById("pvp").checked;
btnPVCchecked = document.getElementById("pvc").checked;
if (document.getElementById("pvp").checked) {
document.getElementById("messageGame").innerHTML = "Player V Player Game!";
console.log("player v player");
clearCount();
count = 0;
game = "pvp";
console.log("test game type at page load = " + game);
} else if (document.getElementById("pvc").checked) {
document.getElementById("messageGame").innerHTML = "Player V Computer Game!";
console.log("player v computer");
game = "pvc";
console.log("test game type at page load = " + game);
} else if (!btnPVPchecked && !btnPVCchecked) {
document.getElementById("messageGame").innerHTML = "No Game Selected!";
console.log("no game type selcted");
game = "none";
console.log("test game type at page load = " + game);
}
} //end checkGameType
function clearGameType() {
btnPVPunchecked = (document.getElementById("pvp").checked = false);
btnPVCunchecked = !(document.getElementById("pvc").checked = false);
console.log("game selection has been cleared");
document.getElementById("messageGame").innerHTML = "Pick a game!";
restartGame();
game = "none";
console.log(game + " ---- New Game var test");
} //end clearGameType
function restartGame() {
options = ["", "", "", "", "", "", "", "", ""];
setRandomPlayer();
running = true;
statusTxt.textContent = 'New Game! ' + player + ' turn!';
boxs.forEach(box => {
box.innerHTML = "";
box.classList.remove('win');
});
counter = 0;
stopCount();
} //end of restartgame
///////////////////////////////
//set up timer here so it can be accessed in funcs
//function for game type player v player
//game timer that looks ugly but works
//i tried making this a nested function and it was a disaster
var counter = 0;
var timeout;
var timer_on = 0;
function timedCount() {
document.getElementById("timeClock").innerHTML = counter + " seconds";
counter++;
timeout = setTimeout(timedCount, 1000);
//testing the timer in console
//console.log(counter);
}
function startCount() {
if (!timer_on) {
timer_on = 1;
timedCount();
}
//console.log(counter);
}
function stopCount() {
clearTimeout(timeout);
timer_on = 0;
//counter = 0;
document.getElementById("timeClock").innerHTML = counter + " seconds";
}
function clearCount() {
clearTimeout(timeout);
counter = 0;
}
//let currentPlayer=x; -- this is for if I wanted to start as x stamp every time
//initialize empty box options for the game board here
//when the game first loads in the browser
function init() {
//the game waits for user interaction - a click in the box
boxs.forEach(box => box.addEventListener('click', boxClick));
btnRestart.addEventListener('click', restartGame);
setRandomPlayer();
statusTxt.textContent = 'Current Game - player ' + player + ' ----- turn!';
running = true;
console.log(game + " test in init");
//here i see that game is undefined so this is why my pvp func is not working below....
} //end of init
init();
function setRandomPlayer() {
//wow it actually works, sometimes o starts, sometimes x starts
currentPlayer = Math.random() > 0.5 ? x : o; //images are being used not x and o
//this needs to be fixed because it doesn't match the random player order
//ok fixed the status message matches the current player
player = currentPlayer;
} //end of random player func
function pvp() {
var x = "x";
var o = "o";
var options = ["", "", "", "", "", "", "", "", ""];
var running = false;
//combo of wins possible that game checks for after each turn
var win = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
console.log('before game play func ---- ' + game);
///////////////////////////////
//start game play here
function boxClick() {
const index = this.dataset.index;
//if
if (options[index] !== "" || !running) {
return;
}
console.log("a click is recorded here");
updateBox(this, index);
isWinner();
}
//use a button to start the game play and attach timer to that     
//not needed ^; timer works fine onclick, finally
function updateBox(box, index) {
options[index] = player;
//dynamic html in the doc
box.innerHTML = currentPlayer;
console.log(currentPlayer + " plays their turn");
}
function nextPlayer() {
player = (player === "x") ? "o" : "x";
currentPlayer = (currentPlayer === x) ? o : x;
statusTxt.textContent = player + ' turn';
console.log("next player's turn " + currentPlayer);
}
//did anyone win
function isWinner() {
let isWon = false;
for (let i = 0; i < win.length; i++) {
const condition = win[i]; //[0,1,2]
const box1 = options[condition[0]];
const box2 = options[condition[1]];
const box3 = options[condition[2]];
if (box1 === "" || box2 === "" || box3 === "") {
continue;
}
if (box1 === box2 && box2 === box3) {
isWon = true;
boxs[condition[0]].classList.add('win');
boxs[condition[1]].classList.add('win');
boxs[condition[2]].classList.add('win');
}
}
if (isWon) {
statusTxt.textContent = 'player ' + player + ' wins!!';
running = false;
//stop the timer here too
stopCount();
} else if (!options.includes("")) {
statusTxt.textContent = 'The Game is Tied';
running = false;
} else {
nextPlayer();
}
} //end of check winner
//
} //end of pvp game

//functionality for game type player v computer
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Title</title>
<link rel="stylesheet" href="style.css">
<link rel="shortcut icon" href="#">
</head>
<body>

<br>
<h3>What kind of game do you want to play ?</h3><br>
<input type="radio" id="pvp" name="gameType" value="Player v Player">Player v Player
<input type="radio" id="pvc" name="gameType" value="Player v Computer" />Player v Computer<br><br>
<button id="start" onclick="checkGameType()">START!</button>
<button id="newGame" onclick="clearGameType()">New Game</button>
<div id="messageGame"></div><br>
<div>----[[Game Clock]]----</div>
<p id="timeClock"> </p>
<div id="status">Place your stamp to start playing!</div>
<div class="container" id="board">
<div data-index="0" class="box" onclick="startCount()"></div>
<div data-index="1" class="box" onclick="startCount()"></div>
<div data-index="2" class="box" onclick="startCount()"></div>
<div data-index="3" class="box" onclick="startCount()"></div>
<div data-index="4" class="box" onclick="startCount()"></div>
<div data-index="5" class="box" onclick="startCount()"></div>
<div data-index="6" class="box" onclick="startCount()"></div>
<div data-index="7" class="box" onclick="startCount()"></div>
<div data-index="8" class="box" onclick="startCount()"></div>
</div>
<br>
<button id="restart" onclick="restartGame()">Restart</button>
<script src="pvpgame.js"></script>
</body>
</html>

您可以使用eventListener和事件的回调函数。目标获取被按下的单选按钮的值。举个例子,如果你想知道当用户点击询问player的单选按钮时该把谁作为对手计算机或作为对手,查询元素,然后遍历它们,并通过eventListener运行nodeList中的节点。一旦用户输入,检查,然后在回调函数中使用逻辑来处理您希望从那里做的事情。

编辑:我意识到一个更尖锐的答案对你的情况会更好…请看我的编辑。编辑我包括开始按钮的例子中,首先看看他们准备开始游戏,一旦start按我们检查单选按钮被选中,如果没有选中我们运行err()功能,让用户知道选择一个对手'input[name="opponent"]:checked',一旦他们选择一个对手,的确是一个单选按钮按下,然后您可以使用更多的逻辑看哪个球员被选中,然后运行逻辑,具体选择。

下面是一个非常简单的例子,但希望你能明白要点。

const startGameBtn = document.querySelector('#start-game');
const board = document.querySelector('#board');
const playGame = (str) => {
let challenge;
if(str === 'computer'){
// run code here for when you play against the computer...
challenger = `the whiley ${str}`;
}
if(str === 'player'){
// run code here for when you play against another player...
challenger = `another ${str}`;
}
board.innerHTML = `<span class="${str}">You have decided to play against ${challenger}...</span>`;
}
const err = (el) => {
el.innerHTML = `<span class="err">Please choose an opponent above before starting the game!</span>`;
}
const startGame = (e) => {
const opponent = document.querySelector('input[name="opponent"]:checked');
if(opponent) {
playGame(opponent.value);
// further conditional or method to handle which player is chosen.
} else {
err(board);
}    
}
startGameBtn.addEventListener('click', startGame);
#board {
font-weight: bold;
display: flex;
justify-content: center;
}
.err {
color: darkred;
background-color: pink;
border-radius: 0.4rem;
padding: 0.5rem;
}
.player {
color: skyblue;
background-color: darkblue;
border-radius: 0.4rem;
padding: 0.5rem;
}
.computer {
color: darkorange;
background-color: yellow;
border-radius: 0.4rem;
padding: 0.5rem;
text-shadow: 1px 1px 1px black;
}
<div id="game-board">
<div>Would you like to play against a player? <input type="radio" name="opponent" value="player" class="opponent"></div>
<div>Would you like to play against the computer? <input type="radio" name="opponent" value="computer" class="opponent"></div>
<button id="start-game">Start</button>
<div id="board"></div>
</div>

最新更新