Description: I have created a Rock-Paper-Scissors game using HTML, CSS, and JavaScript. The game functions properly initially, allowing users to select their choice and play against the computer. However, after completing a game and clicking the "Play Again" button, the event listeners on the game choices (rock, paper, scissor) do not reattach correctly. This results in users being unable to play another round after clicking "Play Again."
function getComputerChoice(){
const choice = ['rock','paper','scissor']
const length = choice.length
return choice[Math.floor(Math.random() * length)]
}
const choicesImage = document.querySelectorAll('.choice img')
const choices = document.querySelectorAll('.choice')
const container = document.querySelector('.container')
const playerResult = document.querySelector('.playerChoice')
const computerResult = document.querySelector('.computerChoice')
const innerContent = container.innerHTML
const status = document.querySelector('.status')
let playerCurrentScore = 0 , computerCurrentScore = 0
function declareResult(){
if(playerCurrentScore === 5 || computerCurrentScore === 5 ){
container.classList.add('new')
const newContent = document.querySelector('.new')
newContent.textContent = playerCurrentScore === 5 ? 'Player Wins!':'Computer Wins!'
newContent.style.fontSize = "35px"
newContent.style.textAlign = "center"
const btn = document.createElement('button')
btn.textContent = "Play Again"
newContent.append(btn)
btn.addEventListener('click',changeContent)
}
}
function changeContent(){
container.classList.remove('new')
container.innerHTML = innerContent
attachEvents();
}
function attachEvents(){
choicesImage.forEach((choice) => {
choice.addEventListener('click',game,true);
});
}
attachEvents();
function game(e){
let index = -Infinity
if(e.target.alt === 'rock') index = 0
else if(e.target.alt === 'paper') index = 1
else if(e.target.alt === 'scissor') index = 2
choices[index].classList.add('active')
choicesImage.forEach((others,indices) => {
if(index !== indices) choices[indices].classList.remove('active')
});
playerResult.src = 'images/rock.svg'
computerResult.src = 'images/rock.svg'
container.classList.add('start')
status.textContent = "Loading.."
setTimeout(() => {
container.classList.remove('start')
let user = e.target.alt
let computer= getComputerChoice()
if(user === 'scissor'){
playerResult.src = `images/${user}.png`
}else{
playerResult.src = `images/${user}.svg`
}
if(computer === 'scissor'){
computerResult.src = `images/${computer}.png`
}else{
computerResult.src = `images/${computer}.svg`
}
let playerScore = document.querySelector('.playerScore')
let computerScore = document.querySelector('.computerScore')
if(user === 'rock' && computer === 'scissor' || user === 'paper' && computer === 'rock' ||
user === 'scissor' && computer === 'paper'){
status.textContent = `You win! ${user} beats ${computer}`
playerCurrentScore++
playerScore.textContent = playerCurrentScore
computerScore.textContent = computerCurrentScore
}else if(user === computer){
status.textContent = `Draw Match...`
playerScore.textContent = playerCurrentScore
computerScore.textContent = computerCurrentScore
}else{
status.textContent = `You Lose! ${computer} beats ${user}`
computerCurrentScore++
playerScore.textContent = playerCurrentScore
computerScore.textContent = computerCurrentScore
}
declareResult()
},500)
}
@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
:root{
--gradient: linear-gradient(
to right,
#8B008Ba1,
#800080b2,
slateblue,
darkslateblue
);
--bodyFont:'Poppins', sans-serif;
}
*{
box-sizing: border-box;
margin: 0;
padding: 0;
}
body{
background-image: var(--gradient);
background-repeat: no-repeat;
background-attachment: fixed;
animation: bg-animation 20s ease infinite 2s alternate;
background-size: 300%;
font-size: 62.5%;
font-family: var(--bodyFont);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 100vh;
overflow-y: hidden;
}
@keyframes bg-animation{
0%{
background-position: left;
}
50%{
background-position: right;
}
100%{
background-position: left;
}
}
.container{
background-color: white;
padding: 2.5rem;
width: 90%;
max-width: 500px;
border-radius: 1.5rem;
box-shadow: 2px 2px 30px 4px rgba(60, 103, 108, 0.593);
}
.container.start .choice{
pointer-events: none;
}
.game-container{
display: flex;
justify-content: space-around;
}
.playerChoice,.computerChoice{
width: 6rem;
height: 6rem;
transform: rotate(90deg);
}
.container.start .playerChoice{
animation: userShake .5s ease infinite;
}
@keyframes userShake{
0%{
transform: rotate(85deg);
}
50%{
transform: rotate(99deg);
}
}
.container.start .computerChoice{
animation: computerShake .5s ease infinite;
}
@keyframes computerShake{
0%{
transform: rotate(265deg) rotateY(175deg);
}
50%{
transform: rotate(279deg) rotateY(190deg);
}
}
.computerChoice{
transform: rotate(270deg) rotateY(180deg);
}
.status{
text-align: center;
margin: 2.5rem auto;
font-size: 1.5rem;
}
.choice-container{
display: flex;
justify-content: space-around;
align-items: center;
}
.choice{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
opacity: 0.5;
transition: opacity 0.1s;
}
.choice:hover{
cursor:pointer;
opacity: 1;
}
.active{
opacity: 1;
}
.choice img{
width: 4rem;
height: 4rem;
}
.desc{
font-size: 1.2rem;
font-weight: bold;
}
.score{
display:flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.player,.computer{
font-size: 1.2rem;
margin-top: 2.0rem;
}
.playerScore,.computerScore{
font-size: 1.5rem;
vertical-align: middle;
font-weight: bold;
margin-left: 1.0rem;
}
.container.new p{
font-size: 35px;
text-align: center;
}
.container.new button{
display: block;
width: 250px;
height: 50px;
border-radius: 10px;
font-size: 15px;
margin: auto;
}
<div class="container">
<div class="game-container">
<img src="images/rock.svg" alt="player" class="playerChoice">
<img src="images/rock.svg" alt="computer" class="computerChoice">
</div>
<p class="status"></p>
<div class="choice-container">
<span class="choice">
<img src="images/rock.svg" alt="rock">
<p class="desc">Rock</p>
</span>
<span class="choice">
<img src="images/paper.svg" alt="paper">
<p class="desc">Paper</p>
</span>
<span class="choice">
<img src="images/scissor.png" alt="scissor">
<p class="desc">Scissor</p>
</span>
</div>
<div class="results">
<div class="score">
<p class="player">Player Score: <span class="playerScore">0</span></p>
<p class="computer">Computer Score: <span class="computerScore">0</span></p>
</div>
<p class="announce"></p>
</div>
</div>
Link:
- I have attempted to remove and reattach event listeners, but it does not work as expected.
- The game UI elements reset correctly, but the click events on the choices are not properly reattached.
- I have checked the browser console for errors, but no errors are shown.
- I have verified the HTML structure, CSS classes, and ensured that the event listener code is executed.
Why might the event listeners fail to reattach properly after pressing "Play Again"? Are there any potential issues or common mistakes I might be missing? Any suggestions or advice on how to debug and resolve this problem would be greatly appreciated.