Rock, Paper, Scissors using onclick function to populate player results - javascript

I'm currently working through a prep course for a bootcamp and the last assignment is to put some basic JavaScript functions into a rock, paper, scissors game. I'm stuck trying to finish this onclick function.
What is the best way to populate the users choice when they click the buttons?
I've currently got my choices defined and set-up in an array. So, I guess I'm trying to get the defined choices to equal the buttons pushed. If I'm thinking correctly I want ex: choices[1] to also be my "Papyrus" button. I've attempted const () =, but I get a no "initializer" warning.
UPDATED ONCLICK FUNCTION. Everywhere I looked and on my lessons it had function(e) with e.target.id and I changed the querySelector to querySelectorAll to grab all the buttons. But still not seeing the console.log output nor seeing the compareChoice results on the screen.
const firstChoice = "Lapis";
const secondChoice = "Papyrus";
const thirdChoice = "Scalpellus";
const choices = ['Lapis', 'Payrus', 'Scalpellus'];
player.currentChoice = document.querySelectorAll('button').onclick = function(e) {
console.log(e.target.id);
}
//Example of on of the choice outcomes
else if(computer.currentChoice === choices[0]){
if(player.currentChoice === choices[1]){
displayResults("The player wins! The computer chose " + computer.currentChoice + " and the player chose " + player.currentChoice);
}else{
displayResults("The computer loses! The computer chose " + computer.currentChoice + " and the player chose " + player.currentChoice);

I assume you have player Obj and multiple buttons where user can pick from
let player = {
currentChoice: ''
},
computer = {
computerSelection: ['Lapis', 'Payrus', 'Scalpellus'],
currentChoice: ''
};
const allButtons = document.querySelectorAll('button')
for (var i = 0; i < allButtons.length; i++) {
allButtons[i].addEventListener('click', getUserSelection);
}
function compare() {
let playerChoice = player.currentChoice,
computerChoice = computer.currentChoice,
outcome = '';
if (playerChoice === computerChoice) {
outcome = 'draw';
} else if (playerChoice === 'Lapis' && computerChoice === 'Scalpellus' || (playerChoice === 'Papyrus' && computerChoice === 'Lapis') || (playerChoice === 'Scalpellus' && computerChoice === 'Papyrus')) {
outcome = 'You win';
} else {
outcome = 'You lose'
}
displayResults(outcome)
displayResults(`You picked ${playerChoice}`)
displayResults(`Computer picked ${computerChoice}`)
}
function getUserSelection(e) {
player.currentChoice = this.id;
// From here trigger a function that compares
// User slection against computers random selection
startTheFight();
}
function setComputerChoice() {
let random = Math.floor(Math.random() * (computer.computerSelection.length - 1)) + 1;
computer.currentChoice = computer.computerSelection[random];
}
function startTheFight() {
// Get a random selection
setComputerChoice();
compare();
}
function displayResults(result) {
const resultText = document.createElement('p');
resultText.innerText = result;
document.body.appendChild(resultText);
}
<button id="Lapis">
Lapis
</button>
<button id="Papyrus">
Papyrus
</button>
<button id="Scalpellus">
Scalpellus
</button>
Edit:In your case, can show the result ultimatium like in the example

The first thing I can see from your code is that you are not defining your onclick callback correctly.
You should use the addEventListener function instead, with the first parameter being the event you want to listen to ( "click" in your case ) and the second being your callback.
Note that the callback can take a parameter, which is the event.
document.querySelectorAll('button').addEventListener("click", function(event) {
// do something once the button is clicked.
});
A callback is just a function that will be executed at some point. And since you seams to be using the "Return value" of the callback in the rest of the code, it is not going to be executed properly. Take the example bellow.
const myButton = document.querySelector('#button');
let myVariable;
// proper way to define an event listener.
myButton.addEventListener('click', function(event) {
myVariable = "Some string";
});
console.log(myVariable); // will always be undefined.
<button id="button">Click me !</button>
Notice how the console always output undefined when you run the code ?
This is because, the callback and the rest of the code are not executed at the same time. Even though the console.log part comes after the callback, it is run at with the rest of the code, not when the callback is trigger. Only the code in the callback will be run when the event we listen to is triggered.
That being said, you can define variable outside the callback and use it inside. This could be useful to keep track of what each player has chosed.
With that in mind, you need to move the logic that check whether or not the player has won, in your callback.
document.querySelectorAll('button').addEventListener("click", function(event) {
if(player.currentChoice === choices[1]){
// player wins
} else {
// computer wins.
}
});
As for the populate the users choice part, you don't really need an external variable. You can simply listen to the click and get the player's choice using the event.target.id like you did previously. Then compare that with a predefined computer move.
Here is a somewhat working example.
const choices = ['Lapis', 'Payrus', 'Scalpellus'];
const allButtons = document.querySelectorAll('button');
// we register the listener on the `click` event, for each buttons.
for(let i = 0; i < allButtons.length; i ++) {
allButtons[i].addEventListener('click', function(event){
// we retrieve the player's choice from the id of the clicked button.
const playerChoice = event.target.id;
// we get a random id for the computer's move.
const randomChoiceId = Math.floor(Math.random() * choices.length);
const computerChoice = choices[randomChoiceId];
// we check if the player wins.
// I don't know the logic and comparing each element might
// not be the more efficient way to achieve this. But it works for now.
if(playerChoice === "Lapis" && computerChoice === "Payrus") {
console.log('Player Wins ! ');
} else {
console.log('Computer wins... ');
}
});
}
<button id="Lapis">Lapis</button>
<button id="Payrus">Payrus</button>
<button id="Scalpellus">Scalpellus</button>
Hopefully, this brief overview of callback was clear enough to help you go forward in your project. Good luck !

Related

How to use a while loop to prompt user until they enter 1 of 4 inputs

I'm stuck on how to get this while loop to function properly. I want the program to prompt the user with a question 'Rock, paper, or scissors?' to which they can correctly enter 'rock', 'paper', 'scissors', or 'bomb' (cheat code for auto-win... lol). If they type in anything other than those 4 acceptable inputs, an alert should appear. Then they should be prompted with the same question again. This should repeat until they enter one of those 4 acceptable inputs.
So far, it works if they type in their choice correctly the first time the prompt appears. However, if they type something other than the above 4 acceptable inputs, triggering the alert and the prompt in the while loop, the program does not run correctly even if they enter one of the 4 inputs the next time they are prompted. It gets stuck alternating between the alert and the prompt for eternity.
So how can I get this while loop to work?
function playGame () {
var input = prompt ('Rock, paper, or scissors?').toLowerCase();
// testing 123
// console.log (input);
var jkl = 0;
if (input === 'rock' || input === 'paper' || input === 'scissors' || input === 'bomb') {
jkl++
};
while (jkl === 0) {
alert ('ErRoR eRrOr 3rR0r!!!!11');
prompt ('Rock, paper, or scissors?').toLowerCase();
if (input === 'rock' || input === 'paper' || input === 'scissors' || input === 'bomb') {
jkl++
};
}
console.log (input);
var userChoice = getUserChoice (input);
var computerChoice = getComputerChoice ();
console.log (`You: ${userChoice}`);
console.log (`Computer: ${computerChoice}`);
console.log (determineWinner (userChoice, computerChoice));
};
playGame ();
After the attempted while loop there is more code that pertains to functions appearing earlier in the program. Ignore that I suppose. Unless anyone thinks it's relevant, in which case I can post that too. Just didn't want to paste a massive wall of code in here.
You can change this line
prompt ('Rock, paper, or scissors?').toLowerCase();
to
input = prompt ('Rock, paper, or scissors?').toLowerCase();
Your code is checking the input variable without updating it.
You need to update the input variable in the loop.
const options = ['rock', 'paper', 'scissors', 'bomb']
const getOptionPrompt = () => prompt('Rock, paper, or scissors?').toLowerCase();
const checkOption = (input, options) => options.includes(input)
function playGame() {
let input = getOptionPrompt();
// testing 123
// console.log (input);
var jkl = 0;
if (checkOption(input, options)) {
jkl++
};
while (jkl === 0) {
alert('ErRoR eRrOr 3rR0r!!!!11');
input = getOptionPrompt();
if (checkOption(input, options)) {
jkl++
};
}
console.log(input);
// the functions after this are not defined in the example
/*
var userChoice = getUserChoice(input);
var computerChoice = getComputerChoice();
console.log(`You: ${userChoice}`);
console.log(`Computer: ${computerChoice}`);
console.log(determineWinner(userChoice, computerChoice));
*/
};
playGame();
But I would definitely update the logic a bit:
const options = ['rock', 'paper', 'scissors', 'bomb']
const getOptionPrompt = () => prompt('Rock, paper, or scissors?')?.toLowerCase() || null;
const checkOption = (input, options) => options.includes(input)
function playGame(options) {
const input = getOptionPrompt();
if (!checkOption(input, options) && input != null) {
alert('ErRoR eRrOr 3rR0r!!!!11');
playGame(options)
} else if (input == null) {
console.log("game canceled")
} else {
console.log("result:", input)
}
};
playGame(options);
This way you don't need the jkl variable, no need for the while loop - if an answer is typed in that is not acceptable, then an error alert shows & the game starts anew.

Rock Paper Scissors coding challenege

I'm trying to make a Rock Paper Scissors coding challenge for myself, and I got a simple version with a text box, so no I'm trying to make it with buttons, I have made it very far through, I'm just on the last step.
So what I want to do is take the info from the rock(), paper(), and scissors() functions and go further
This is what I have so far
var playerInput = "blank"
function rock(playerInput) {
this.playerInput = playerInput;
playerInput = "rock";
}
function paper(playerInput) {
this.playerInput = playerInput;
playerInput = "paper";
}
function scissors() {
this.playerInput = playerInput;
playerInput = "scissors";
}
and what I want to do from there is take it into another function where I have already created the game itself.
I've tried
var rock = rock();
console.log(rock.playerInput);
and it didn't work please help.
[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>
Given the above, you got pretty much all the needed data.
Both player and computer values are an integer 0 (rock), 1 (paper), 2 (scissors)
Example of Rock Paper Scissors game with result
const fig = ["Rock", "Paper", "Scissors"];
const msg = ["You won!", "You lost :(", "It's a draw"];
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
// Game logic goes here
// See: https://stackoverflow.com/a/53983473/383904
let result;
if (player === computer) {
result = 2; // Draw
} else if ((computer + 1) % 3 === player) {
result = 0; // Player wins
} else {
result = 1; // Computer wins
}
console.log(`PLAYER:${fig[player]} COMPUTER:${fig[computer]} ${msg[result]}`);
}
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>
Another resource that explains the logic is here
[1]: https://stackoverflow.com/a/53983473/383904
function rock(playerInput) {
this.playerInput = playerInput;
}
var playerInput = 'blank'
var myRock = new rock(playerInput);
console.log(myRock.playerInput) // Should output "Blank"
If you want to make an object with function notation, you need to use the new keyword:
var myRock = new rock();
And you should be passing the info to the object when you create it, not before. Try something like this.
function rock(playerInput) {
this.playerInput = playerInput;
}
var myRock = new rock("Blank");
console.log(myRock.playerInput) // Should output "Blank"

Javascript Mini Game with Arrays

I am trying a very simple version of the game "rock, paper or scissors" with javascript. (Mostly to learn functions and although i think my code makes sense and it should print in the console the outputs on each If Else statement it doesnt print anything.
Any hint?
Code below
const startGame = document.getElementById('start-game-btn');
const choicePlayer = ["Rock" , "Scissor", "Paper"];
const defaultChoise = "Rock";
function startTheGame(choicePlayer,defaultChoise) {
alert("Choose Rock , Scissor or Paper");
prompt(choicePlayer[0], choicePlayer[1]);
for (var i=0; i<choicePlayer.length; i++) {
if(choicePlayer[i]===choicePlayer[0] || choicePlayer[i] === choicePlayer[1] || choicePlayer[i] === choicePlayer[2]) {
console.log("asdf");
return choicePlayer[i];
}
else {
console.log("we choose for you");
return defaultChoise;
}
}
}
startGame.addEventListener('click' , startTheGame);
prompt works by returning a value, meaning you should use it like this:
choicePlayer[0] = prompt("Player 1 - Choose Rock , Scissor or Paper", choicePlayer[0]);
choicePlayer[1] = prompt("Player 2 - Choose Rock , Scissor or Paper", choicePlayer[1]);
Plus - having a function argument called choicePlayer will override your global variable choicePlayer, meaning that the choicePlayer inside the function holds the event argument.
in order to save the user input from the prompt function, you should save it in a variable like so: const result = prompt("text that will show in the prompt");
you can check the snippet I added for a solution for a few other fixes.
const startGame = document.getElementById('start-game-btn');
const choices = ["rock" , "scissor", "paper"];
const defaultChoice = "rock";
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
}
function gameInit() {
const playerChoice = prompt("Choose Rock , Scissor or Paper");
if(choices.includes(playerChoice.toLowerCase())) {
//return playerChoice;
console.log(capitalizeFirstLetter(playerChoice));
} else {
console.log("we choose for you");
//return defaultChoice;
console.log(capitalizeFirstLetter(defaultChoice));
}
}
startGame.addEventListener('click' , gameInit);
<button id="start-game-btn">Start</button>

Counter value is not increasing, value remains constant in javascript

why does my variable pc_score and my_score not increase? The output is 0.
I have two more functions of the eventListener format that I omitted from the code, but it should not affect the results. .
I edited the post for runnable code. Thank you.
Thanks for looking at my question.
<script>
var options = ['rock','paper','scissors']
let my_score = 0;
var pc_score = 0;
let computerChoice ;
function computerSelection() {
computerChoice = options[Math.floor(Math.random()*options.length)]
return computerChoice;
}
var results = document.getElementById("result")
document.getElementById("rock").addEventListener("click", ()=> {
playerChoice=rock;
computerSelection();
if (computerChoice=='rock'){
results.innerHTML="It is a tie";
} else if (computerChoice=='paper'){
results.innerHTML="It is a loss";
pc_score += 1;
}else if (computerChoice=='scissors'){
results.innerHTML="It is a win";
my_score+= 1
}
})
const you = document.getElementById("You")
you.innerHTML= my_score
const computer = document.getElementById("Computer")
computer.innerHTML=pc_score
</script>
Since you are assigning the value outside the event handler function that code does not get executed when click happens (instead those code is executed on page load with the initial value). You have to update the HTML inside the event handler function.
Also I will suggest you to use innerText or textContent if the text is plain text (not htmlString).
Try the following:
var my_score = 0;
var pc_score = 0;
const you = document.getElementById("You");
const computer = document.getElementById("Computer");
document.getElementById("scissors").addEventListener("click", ()=> {
playerChoice=scissors;
computerSelection();
if (computerChoice == "rock"){
results.textContent = "It is a loss";
pc_score++;
} else if (computerChoice == "paper"){
results.textContent = "It is a win";
my_score++;
}else if (computerChoice=="scissors"){
results.textContent = "It is a tie";
}
you.textContent = my_score;
computer.textContent = pc_score;
});
You are updating the score variables, but not the innerHTML's of the elements showing that score. There surely is a better/cleaner way to do this, but just call computer.innerHTML=pc_score and you.innerHTML= my_score again after changing the value

Creating multiples of the same DOM Element Image

I am a new Developer and am working on a Tic Tac Toe SPA. I have a working game, but I want to customize the game tokens. I have tried creating a DOM element a few different ways, which were all successful. Here is the problem:
Every time I go to make a second move for a player, the DOM image disappears and reappears in the new square selected. Obviously this is not the desired action. Is there something I don't know about creating a DOM element. I have googled this and read countless articles and watched countless videos.
const stark = document.createElement('img')
stark.src = 'https://i.imgur.com/d70XlET.png'
stark.height = 80
stark.width = 80
const lanister = document.createElement('img')
lanister.src = 'https://i.imgur.com/d70XlET.png'
lanister.height = 80
lanister.width = 80
const play = (event) => {
if (gameOver === false) {
if (event.target.innerHTML === '') {
$('#' + event.target.id).append(turn)
}
}
}
'turn' is a variable that works with a toggle function to switch between players and stores whichever players turn it is(i.e. 'stark')
I would be really grateful if someone could point me in the direction of a resource where I could learn more about this.
const player1 = stark
const player2 = lanister
let turn = player1
let prevTurn = player2
const togglePrevTurn = () => {
if (!gameOver) {
if (prevTurn === player1) {
prevTurn = player2
} else {
prevTurn = player1
}
}
}
const toggleTurn = () => {
if (!gameOver) {
if (turn === player1) {
turn = player2
} else {
turn = player1
}
$('#message').text(turn + " 's turn")
}
}
Whenever you use Javascript's appendChild or jQuery's append, when you pass it an element, that element gets removed from its previous location in the DOM (if it's in the DOM), and then gets inserted at the new position. It sounds like what you need to do is explicitly create a new element each time, which you might do with cloneNode().
Also, probably best to name your variables precisely - if turn is an image, name it to make it clear that it's an image, perhaps currentPlayerImage.
In addition, because you already have a reference to the event.target, there's no need to reselect it with $('#' + event.target.id) - just select event.target:
const play = (event) => {
if (gameOver === false) {
if (event.target.innerHTML === '') {
$(event.target).append(currentPlayerImage.cloneNode());
}
}
}

Categories

Resources