Trying to Set a Span Element Equal to a Variable Value in a Js Rock, Paper, Scissors Game

Trying to set a span element equal to a variable value in a JS Rock, Paper, Scissors Game

Beside your typo idea= / id= ...

you could drastically minify your game logic and code by using indexes integers.

Game of integers

  • Use data-* attribute for user buttons. The attributes should hold numerical values 0, 1, 2. On click, the value will represents the player choice.
  • The AI should play numbers too: const AI = ~~(Math.random() * 3) // 0, 1, 2

Now that you know AI and Player both use integers (instead of strange letters combinations), you can store the Move names into an array const moves = ["Rock", "Paper", "Scissors"]; (where 0 is Rock... etc)

Rock Paper Scissors Logic

The game has three possible round resolutions, PL wins, AI wins, Draw.
Let's convert those "human" values to integers, in the same order:

  • 0 = PL win
  • 1 = AI win
  • 2 = Draw

Here's how to calculate those:

Draw

To calculate a Draw is the simplest. It's when both AI and PL integers are equal. Let's return 2

result = PL === AI ? 2

Player wins

To calculate Player win, simply increment AI choice by 1 and do a modulo 3. If the result of this operation is equal to player's choice, than Player must have won! Let's return 0

AI wins

Else, since our game has only 3 possible states, it's not a draw, and it's not a player win, than must be AI win! And let's return 1

const result = PL===AI ? 2 : (AI+1)%3 === PL? 0 : 1; // Possible results: 0, 1, 2

The cool thing in having a game result index based too is that now you can use also an array of messages like messages = ["You won!", "AI won", "it's a draw!", ] and get the desired message by the result index!. And bonus! You can also increment the score array values, 0 being the player's index and 1 being AIs!

const moves = ["Rock", "Paper", "Scissors"],  messages  = ["You won!", "AI won", "It's a draw!"], // [PL, AI, draw]  score     = [0, 0, 0],                              // [PL, AI, draw]  EL = sel => document.querySelector(sel),  EL_result  = EL("#result"),  EL_PLScore = EL("#PLScore"),  EL_AIScore = EL("#AIScore");
function game() { const PL = +this.dataset.playermove; // Get dataset value as integer const AI = ~~(Math.random() * 3); // All you need: 0, 1, 2 const result = PL === AI ? 2 : (AI + 1) % 3 === PL ? 0 : 1; // 0=PLwins 1=AIwins 2=draw
score[result]++; // Increment PL or AI's score (Increments number of draws too ;) ) EL_result.innerHTML = `You: ${moves[PL]}<br>AI: ${moves[AI]}<br>${messages[result]}`; EL_PLScore.textContent = score[0]; EL_AIScore.textContent = score[1];}
// EVENTS:document.querySelectorAll("[data-playermove]") .forEach(el => el.addEventListener("click", game));
<button data-playermove="0">ROCK</button><button data-playermove="1">PAPER</button><button data-playermove="2">SCISSORS</button>
<br>
YOU | <span id="PLScore">0</span>:<span id="AIScore">0</span> | AI
<div id="result"></div>

Rock Paper Scissors coding challenege

[Here's a super useful example][1] on how to tackle the Rock, Paper, Scissors game logic using buttons.

Besides that, you don't need multiple functions, programming is not about copy/pasting code around a file, but to determine the characteristics we can reuse.

Use data-* attributes to store the figure index:

function play() {
const player = Number(this.dataset.player); // Get 0, 1, 2 from button data-player
const computer = Math.floor(Math.random() * 3); // Generate random 0, 1, 2 integer
console.log(`PLAYER: ${player} COMPUTER:${computer}`);

// Game logic goes here
}

const buttons = document.querySelectorAll("[data-player]");

buttons.forEach(function(el) {
el.addEventListener("click", play);
});
<button data-player="0" type="button">ROCK</button>
<button data-player="1" type="button">PAPER</button>
<button data-player="2" type="button">SCISSORS</button>

How do I make a function that reset the game on click

Firstly, you need to remove position: absolute; for img which was causing the overlapping.

Secondly, each time you call cpuChoice(), you need to hide the previous element before showing the current element.

const userChoice = document.querySelectorAll('.choice')const cpuScissors = document.querySelector('.cpu-scissors')const cpuPaper = document.querySelector('.cpu-paper')const cpuRock = document.querySelector('.cpu-rock')let currentItem;
function cpuChoice() { const rand = Math.random(); if (currentItem) { currentItem.style.display = 'none'; } if (rand < .34) { cpuPaper.style.display = 'inline-block'; currentItem = cpuPaper; } else if (rand >= .67) { cpuRock.style.display = 'inline-block'; currentItem = cpuRock; } else { cpuScissors.style.display = 'inline-block'; currentItem = cpuScissors; }}
userChoice.forEach(userChoice => userChoice.addEventListener('click', cpuChoice));
.cpu-scissors {  display: none;}
.cpu-paper { display: none;}
.cpu-rock { display: none;}
.cpu-result img { height: 5rem;}
<div class="main-container">  <div class="score">    <p>You:0</p>    <p>Computer:0</p>  </div>
<div class="user-choice"> <img id="rock" class="choice" src="icons/rock.png"> <img id="paper" class="choice" src="icons/paper.png"> <img id="scissors" class="choice" src="icons/scissors.png"> </div> <div class="cpu-result"> <img class="cpu-rock" src="icons/rock.png"> <img class="cpu-paper" src="icons/paper.png"> <img class="cpu-scissors" src="icons/scissors.png"> </div></div>


Related Topics



Leave a reply



Submit