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 values0, 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 win1
= AI win2
= 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
Detect Browser Character Support in JavaScript
How to Read/Parse Individual Transform Style Values in JavaScript
Change Svg Text to CSS Word Wrapping
Invert Filter Not Working on Ie and Safari
How to Disable Ie10 History Swipe Gesture
How to Disable JavaScript for Responsive Design
Alter CSS Class Attributes with JavaScript
Save Images After Using CSS Filter
How to Show Extended Option in Select List
Check If Window Is Already Open Window.Open
Attribute Onclick="Function()" Not Functioning as Intended
Changing the Default Font Family in Tinymce
Get All CSS Styles for a Dom Element (A La Firebug)
Cannot Apply Any Bootstrap Style in Using React-Bootstrap Library
How to Zoom in an Image and Center It