Issue
I'm working on a task to build a Stone,Paper,Scissors Game. The game is supposed to run in 3 possible modes. best of 3 / best of 5 and endless games.
My code works fine until the point where I reset the game to begin a new game. For a reason which I can not figure out, it plays multiple instances of my game, each time I call the game() function. (after the game is over - a reset game button appears and the game mode needs to be reseleted)
I've added the entire project to this https://jsfiddle.net/vydkg3bz/, since I don't manage to pinpoint where the issue is.
I believe, due to all the extra logging I added, that the problem is somewhere in the game() function, as I tried to replace most of the code around it, with the same result.
Maybe someone has a moment to review my code and give me a hint where I should look?
// global variables
var choicesObj = {
Rock: "url('./img/stone.png')",
Paper: "url('./img/paper.png')",
Scissors: "url('./img/scissors.png')",
}
var choices = Object.keys(choicesObj);
var moveAI;
var movePlayer;
var winnerRound;
var winnerGame;
var roundCount = 0;
// actual game
function game(requiredWins) {
console.log("game");
enabler()
var inputs = document.querySelectorAll(".inputButton");
console.log(inputs);
for (var i = 0; i < inputs.length; i++) {
inputs[i].addEventListener("click", function() {
movePlayer = this.id
handleClick(movePlayer)
});
}
// checking choice, display choice IMG, call compareChoices function
function handleClick(buttonID) {
console.log("handleClick");
moveAIfunc()
movePlayer = buttonID;
console.log('movePlayer: ' + movePlayer);
console.log('moveAI: ' + moveAI);
document.getElementById("mainImgPlayer").style.backgroundImage = choicesObj[movePlayer];
document.getElementById("mainImgAI").style.backgroundImage = choicesObj[moveAI];
compareChoices(moveAI,movePlayer);
console.log("requiredWins", requiredWins);
gameEnd();
displays();
}
// AI control
function moveAIfunc() {
moveAI = choices[Math.floor(Math.random() * choices.length)]
}
// compare choices
function compareChoices(a, b) {
console.log("compareChoices");
a = choices.indexOf(a);
b = choices.indexOf(b);
console.log("requiredWins", requiredWins);
roundCount++;
if (a == b) {
winnerNone()
return;
}
if (a == choices.length - 1 && b == 0) {
winnerPlayer()
return;
}
if (b == choices.length - 1 && a == 0) {
winnerAI()
return;
}
if (a > b) {
winnerAI()
return;
}
else {
winnerPlayer()
return;
}
}
// game end
function gameEnd() {
console.log("gameEnd");
console.log(requiredWins,winsPlayer,winsAI);
if (winsPlayer == requiredWins) {
console.log(requiredWins,winsPlayer,winsAI);
winnerGame = "Player";
disabler()
createEndButton()
return;
}
if (winsAI == requiredWins) {
console.log(requiredWins,winsPlayer,winsAI);
winnerGame = "AI";
disabler()
createEndButton()
return;
}
}
}```
Solution
Your code seems to be pretty complicated. The state of the wins/required wins etc. is not saved adequately in it. For playing you add event listeners per game (click), which is pretty inefficient imho.
I have created a mockup (a minimal reproducable example) for the handling of games, using data attributes to remember the state of a game and event delegation for the handling. Maybe it's useful for you.
Not related, but here's my take on RPS.
document.addEventListener(`click`, handle);
function handle(evt) {
if (evt.target.id === `play`) {
return play(evt.target);
}
if (evt.target.name === `nWins`) {
return reset(evt.target);
}
}
function reset(radio) {
const value = radio === `none`
? Number.MAX_SAFE_INTEGER : +radio.value;
const bttn = document.querySelector(`#play`);
const result = document.querySelector(`#result`);
result.textContent = `(Re)start initiated, click [Play]`;
result.dataset.wins = bttn.dataset.wins = 0;
bttn.dataset.plays = 0;
return bttn.dataset.winsrequired = value;
}
function play(bttn) {
if (+bttn.dataset.winsrequired < 1) {
return document.querySelector(`#result`)
.textContent = `Select best of to start playing ...`;
}
const result = document.querySelector(`#result`);
bttn.dataset.plays = +bttn.dataset.plays + 1;
const won = Math.floor(Math.random() * 2);
const wins = +result.dataset.wins + won;
result.textContent = `${won ? `You win` : `You loose`} (plays: ${
bttn.dataset.plays}, wins ${wins})`;
result.dataset.wins = wins;
if (+bttn.dataset.plays === +bttn.dataset.winsrequired) {
result.textContent = `You won ${wins} of ${
bttn.dataset.winsrequired} games. Choose 'Best of'
to start another game`;
bttn.dataset.plays = bttn.dataset.winsrequired = 0;
result.dataset.wins = 0;
document.querySelectorAll(`[name="nWins"]`)
.forEach(r => r.checked = false);
}
}
Best of
<input type="radio" name="nWins" value="3"> 3
<input type="radio" name="nWins" value="5"> 5
<input type="radio" name="nWins" value="none"> indefinite
<button id="play" data-winsrequired="0" data-plays="0" >Play</button>
<p id="result" data-wins="0"></p>
Answered By - KooiInc
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.