I’m currently practicing JavaScript by developing a Rock Paper Scissors game with a graphical interface, but I’m encountering some issues that I can’t resolve. Whenever I select an option in the interface, the application freezes completely. I had some difficulty with the event handling logic but I’m uncertain if that’s the source of the problem or if it’s something else. Below is my HTML and JavaScript code for your review.
HTML Code:
<!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">
<link rel="stylesheet" type="text/css" href="css/styles.css">
<script src="https://kit.fontawesome.com/77133b1b16.js" crossorigin="anonymous"></script>
<title>Rock, Paper, Scissors, Lizard, Spock</title>
</head>
<body>
<div class="container">
<div class="header">
<h1>SELECT YOUR MOVE</h1>
</div>
<div class="options">
<div class="option" id="rock">
<div><img src="rock.png" alt="rock"></div>
<p>Rock</p>
</div>
<div class="option" id="paper">
<div><img src="paper.png" alt="paper"></div>
<p>Paper</p>
</div>
<div class="option" id="scissors">
<div><img src="scissors.png" alt="scissors"></div>
<p>Scissors</p>
</div>
<div class="option" id="lizard">
<div><img src="lizard.png" alt="lizard"></div>
<p>Lizard</p>
</div>
<div class="option" id="spock">
<div><img src="spock.png" alt="spock"></div>
<p>Spock</p>
</div>
</div>
<h1 class="score-header">Scores</h1>
<div class="scoreboard">
<div class="user-score">
<h2>You</h2>
<span id="userScore"></span>
</div>
<div class="ai-score">
<h2>Computer</h2>
<span id="aiScore"></span>
</div>
</div>
<span id="resultMessage"></span>
<div class="game-rules">
<h3>Gameplay Rules:</h3>
<p>“Scissors cut Paper, Paper covers Rock, Rock crushes Lizard, Lizard poisons Spock, Spock smashes Scissors, Scissors decapitates Lizard, Lizard consumes Paper, Paper disproves Spock, Spock vaporizes Rock, and as traditionally, Rock crushes Scissors.”</p>
</div>
</div>
<footer class="footer">
<p>© CamiCoding 2022</p>
</footer>
<script src="script.js"></script>
</body>
</html>
JavaScript Code:
let choices = ["rock", "paper", "scissors", "lizard", "spock"];
let scorePlayer = 0;
let scoreComputer = 0;
let totalRounds = 0;
let roundWinner;
const scorePlayerElement = document.getElementById('userScore');
const scoreComputerElement = document.getElementById('aiScore');
const resultMessageElement = document.getElementById('resultMessage');
const optionButtons = document.querySelectorAll('.option');
optionButtons.forEach(option => {
option.addEventListener('click', handleRound);
});
function handleRound(e) {
let playerChoice = e.target.id;
let computerChoice = getComputerChoice();
if (playerChoice === computerChoice) {
roundWinner = 'draw';
} else if (
(playerChoice === "paper" && computerChoice === "scissors") ||
(playerChoice === "rock" && computerChoice === "paper") ||
(playerChoice === "spock" && computerChoice === "lizard") ||
(playerChoice === "lizard" && computerChoice === "rock") ||
(playerChoice === "scissors" && computerChoice === "rock") ||
(playerChoice === "lizard" && computerChoice === "scissors") ||
(playerChoice === "paper" && computerChoice === "lizard") ||
(playerChoice === "spock" && computerChoice === "paper") ||
(playerChoice === "rock" && computerChoice === "spock") ||
(playerChoice === "scissors" && computerChoice === "spock")
) {
roundWinner = 'computer';
scoreComputer++;
} else {
roundWinner = 'player';
scorePlayer++;
}
updateScore();
}
function getComputerChoice() {
const randomIndex = Math.floor(Math.random() * choices.length);
return choices[randomIndex];
}
function updateScore() {
if (roundWinner === 'draw') {
resultMessageElement.textContent = "It's a draw!";
} else if (roundWinner === 'computer') {
resultMessageElement.textContent = "You lost this round!";
} else {
resultMessageElement.textContent = "You won this round!";
}
scorePlayerElement.textContent = scorePlayer;
scoreComputerElement.textContent = scoreComputer;
}
Thank you for any assistance you can provide!
Hey there!
It looks like a small issue with event handling might be causing the freezing of your app when you select an option. Let’s go through a quick solution to optimize it effectively.
Key Observations:
- Event Target: When accessing the player’s choice, it’s possible that you might be selecting the wrong element. The event
e.target.id
should point to your option div
directly.
Solution:
- Ensure the event listener captures the click on the
div
element correctly. A simple change would be checking the right property that holds the identifier. Instead of using e.target.id
, ensure you are indeed capturing the right div
id.
Updated JavaScript Code:
optionButtons.forEach(option => {
option.addEventListener('click', (e) => handleRound(e.currentTarget.id));
});
function handleRound(playerChoice) {
let computerChoice = getComputerChoice();
if (playerChoice === computerChoice) {
roundWinner = 'draw';
} else if (
(playerChoice === "paper" && computerChoice === "scissors") ||
(playerChoice === "rock" && computerChoice === "paper") ||
(playerChoice === "spock" && computerChoice === "lizard") ||
(playerChoice === "lizard" && computerChoice === "rock") ||
(playerChoice === "scissors" && computerChoice === "rock") ||
(playerChoice === "lizard" && computerChoice === "scissors") ||
(playerChoice === "paper" && computerChoice === "lizard") ||
(playerChoice === "spock" && computerChoice === "paper") ||
(playerChoice === "rock" && computerChoice === "spock") ||
(playerChoice === "scissors" && computerChoice === "spock")
) {
roundWinner = 'computer';
scoreComputer++;
} else {
roundWinner = 'player';
scorePlayer++;
}
updateScore();
}
Explanation:
- By using
e.currentTarget.id
, we ensure that the correct div
element’s id is utilized for the player’s choice.
Try this out, and your app should run smoothly again! 
Feel free to ask if you have more questions!
Cheers,
David Grant
Try updating your event handling logic. It seems like the event target is not correctly capturing the ID of the selected option. Adjust it like so:
optionButtons.forEach(option => {
option.addEventListener('click', (e) => handleRound(e.currentTarget.id));
});
function handleRound(playerChoice) {
let computerChoice = getComputerChoice();
if (playerChoice === computerChoice) {
roundWinner = 'draw';
} else if (
// List your conditions here
) {
roundWinner = 'computer';
scoreComputer++;
} else {
roundWinner = 'player';
scorePlayer++;
}
updateScore();
}
This change ensures e.currentTarget.id
is used, grabbing the correct element ID while avoiding incorrect targets that might lead to freezing issues. Give it a shot!
paper: [‘scissors’, ‘lizard’],
scissors: [‘rock’, ‘spock’],
lizard: [‘rock’, ‘scissors’],
spock: [‘lizard’, ‘paper’]
};
optionButtons.forEach(option => {
option.addEventListener(‘click’, (e) => handleRound(e.currentTarget.id));
});
function handleRound(playerChoice) {
const computerChoice = getComputerChoice();
if (playerChoice === computerChoice) {
roundWinner = 'draw';
} else if (losingConditions[playerChoice].includes(computerChoice)) {
roundWinner = 'computer';
scoreComputer++;
} else {
roundWinner = 'player';
scorePlayer++;
}
updateScore();
}
Explanation:
- I've introduced a mapping of each choice to its losing conditions, streamlining the decision-making process to improve both readability and performance.
- This approach minimizes direct condition checks, leveraging JavaScript arrays and object properties to determine round outcomes more efficiently.
Implementing these recommendations should help improve the responsiveness of your app. If further complications persist, the issue might be with other aspects, such as resource loading times or external library dependencies.
Hey ExcitedGamer85,
The issue you are facing is likely due to incorrect event handling. Let’s make the necessary adjustments to ensure your application runs smoothly.
Problem:
Your current event handler might not effectively capture the player’s choice due to targeting issues.
Solution:
Use e.currentTarget.id
to correctly capture the ID of the selected option. This ensures that the appropriate div
ID is used when registering the player’s choice.
Updated JavaScript Code:
optionButtons.forEach(option => {
option.addEventListener('click', (e) => handleRound(e.currentTarget.id));
});
function handleRound(playerChoice) {
let computerChoice = getComputerChoice();
if (playerChoice === computerChoice) {
roundWinner = 'draw';
} else if (
(playerChoice === "paper" && computerChoice === "scissors") ||
(playerChoice === "rock" && computerChoice === "paper") ||
(playerChoice === "spock" && computerChoice === "lizard") ||
(playerChoice === "lizard" && computerChoice === "rock") ||
(playerChoice === "scissors" && computerChoice === "rock") ||
(playerChoice === "lizard" && computerChoice === "scissors") ||
(playerChoice === "paper" && computerChoice === "lizard") ||
(playerChoice === "spock" && computerChoice === "paper") ||
(playerChoice === "rock" && computerChoice === "spock") ||
(playerChoice === "scissors" && computerChoice === "spock")
) {
roundWinner = 'computer';
scoreComputer++;
} else {
roundWinner = 'player';
scorePlayer++;
}
updateScore();
}
Explanation:
By utilizing e.currentTarget.id
, you ensure that you are referencing the correct div
element, reducing the chance of selecting incorrect targets that might be causing the application to freeze.
Give this a try, and your issue should be resolved! If there are any other problems, feel free to reach out.
Best,
David Grant
The freezing issue in your Rock Paper Scissors game seems to arise from the way you handle events. The potential root cause is in the event handling logic, as multiple users have pointed out. Let's explore a different way to optimize your event handling to ensure smooth operation.
Potential Cause:
Your current event listener might be capturing clicks on unintended elements such as the images inside the selectable div
elements. This may prevent the correct IDs from being accessed, thus halting the game logic.
Solution:
Instead of relying on e.target.id
, which could refer to the inner img
element, consider using e.currentTarget.id
. This method ensures you are targeting the correct div
that the event listener is attached to.
optionButtons.forEach(option => {
option.addEventListener('click', (e) => handleRound(e.currentTarget.id));
});
function handleRound(playerChoice) {
const computerChoice = getComputerChoice();
if (playerChoice === computerChoice) {
roundWinner = 'draw';
} else if (
(playerChoice === "paper" && computerChoice === "scissors") ||
(playerChoice === "rock" && computerChoice === "paper") ||
(playerChoice === "spock" && computerChoice === "lizard") ||
(playerChoice === "lizard" && computerChoice === "rock") ||
(playerChoice === "scissors" && computerChoice === "rock") ||
(playerChoice === "lizard" && computerChoice === "scissors") ||
(playerChoice === "paper" && computerChoice === "lizard") ||
(playerChoice === "spock" && computerChoice === "paper") ||
(playerChoice === "rock" && computerChoice === "spock") ||
(playerChoice === "scissors" && computerChoice === "spock")
) {
roundWinner = 'computer';
scoreComputer++;
} else {
roundWinner = 'player';
scorePlayer++;
}
updateScore();
}
Benefits:
- Correct Targeting: By ensuring you reference the correct
div
element, you eliminate incorrect targeting, which can potentially cause freezing.
- Enhanced Readability: The game logic becomes clearer when you separate event handling from inner elements like images.
Implement these changes, and it should resolve the application freeze you are experiencing. If further issues arise, consider checking for any resource loading delays or other potential JavaScript errors that aren't linked to event handling directly.