Unable to get Tic Tac Toe game to change player to turn - javascript

I have been trying different ways to get the currentPlayers and playerTitle to change. I am not sure if I am correctly implementing the if statement because the else if is not executing.
`"use strict";
const gameClock = document.querySelector(".clock");
const playerTitle = document.querySelector(".player-title");
const ticTacToeBoard = document.querySelector(".tic-tac-toe-container");
const cells = document.querySelectorAll(".cell");
const startPauseBtn = document.querySelector("start-btn");
const resetBtn = document.querySelector(".resetBtn");
let currentPlayer = "X";
ticTacToeBoard.classList.add("player-turn");
//functions
const playerMove = () =\> {
cells.forEach((cell) =\> {
if (ticTacToeBoard.classList.contains("player-turn")) {
cell.addEventListener("click", () =\> {
cell.append(currentPlayer);
playerTitle.innerHTML = "Player: 2";
currentPlayer = "O";
ticTacToeBoard.classList.toggle("player-turn");
});
} else if (ticTacToeBoard.classList.contains("player-turn") === false) {
cell.addEventListener("click", () =\> {
cell.append(currentPlayer);
playerTitle.innerHTML = "Player: 1";
currentPlayer = "X";
ticTacToeBoard.classList.toggle("player-turn");
});
}
});
};`
playerMove();
I have tried to get the currentPlayer to switch back from "O" to "X" and playerTitle back to "Player: 1" with ticTacToeBoard.classList.contains() as the condition within an if statement but it does not execute the if else statement. So currentPlayer remains "O" and playerTitle remains "Player: 2".

You only check if ticTacToeBoard.classList contains "player-turn" at the beginning of the game, which means each cell is hardcoded to change the turn to "O". You need to move the if statement inside the cell event listener so that each cell actually checks whether ticTacToeBoard.classList contains "player-turn".
Also, you don't need to check if ticTacToeBoard.classList.contains("player-turn") is false, a simple else is enough.

Related

I have a usestate that I want to set I want to set to a value !==null within a function

I am trying to set a state var within a function so when a form button is pressed, the value of the usestate will not equal null anymore. Because the form will not equal null this will perform a different action in my code if this button has been pressed.
Only issue is it seems the variable setReg cannot be set inside of a function as it will not be a global variable. Is there a workaround here?
//the usestate
const [Reg, setReg] = useState(null)
//the function
const updateEthers = () => {
let tempProvider = new ethers.providers.Web3Provider(window.ethereum);
setProvider(tempProvider);
let tempSigner = tempProvider.getSigner();
setSigner(tempSigner);
//Here I am saying if setreg is null as set in the state then perform this
if (setReg == null) {
let tempContract = new ethers.Contract(
phonecontractAddress,
Register_abi,
tempSigner)
setContract(tempContract)
}
//Else use a different function
else {
let
tempContract = new ethers.Contract(
codecontractAddress,
Code_abi,
tempSigner)
setContract(tempContract)
}
}
//I have a button when pressed calls this
const setRegister = async (event) => {
event.preventDefault();
const Hash = await ipfsbcupload(event.target.setText.value);
console.log("sending " + event.target.setText.value + " to the contract");
contract.set(Hash);
setPhoneNum(event.target.setText.value)
let setReg = 1
//let setReg = 1 so that the setReg will no longer be null is the theory so the form will choose the other option when pressed now.
//...
}
setReg() is available globally; however you're missing the function brackets at the end (setReg vs setReg()). That said, what I believe you want to reference is reg.
/* Note that I've made `reg` lowercase to follow camelCase rules */
const [reg, setReg] = useState(null)
const updateEthers = () => {
// this will run fine and is likely the code you want
if (reg == null) { }
// this will return an error - setReg is a function and so needs the parentheses behind it as setReg() - otherwise it will say it's not defined
if (setReg == null) { }
// this doesn't make sense because setReg is just setting what reg should be, it's not a value itself
if (setReg() == null) { }
}

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

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 !

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());
}
}
}

Javascript basic loop help - basic

Im learning Javascript now and I got a question that's been bugging me!
So, all I needed to do here is to type a color on this input box, click the button and change the headline to the color typed only if that typed color is in the array specified in the variable.
My code is half working... it does check if whatever color typed is inside the array, but the alert button pops up each time, is there a way to make the alert pop up only if the color typed isn't in the array please?
Working code: https://codepen.io/anon/pen/ddPWLP
Javascript code:
const myHeading = document.getElementById('myHeading');
const myButton = document.getElementById('myButton');
const myTextInput = document.getElementById('myTextInput');
var colors = ["red", "black", "blue"];
myButton.addEventListener('click', () => {
for (var i=0; i<colors.length; i++){
if (myTextInput.value === colors[i]){
myHeading.style.color = myTextInput.value
} else {
alert("no color")
}
}
});
Don't do it inside the loop. Use a variable to flag when you find a match, and then after the loop check that flag and display the alert accordingly. Try this:
myButton.addEventListener('click', () => {
var found = false;
for (var i = 0; i < colors.length; i++) {
if (myTextInput.value === colors[i]) {
myHeading.style.color = myTextInput.value
found = true;
}
}
if (!found)
alert("no color");
});
By the way, you don't need a loop for that. You can simply use the indexOf() methods. If the value exists in the array, it returns its index, otherwise it returns -1. Try this:
myButton.addEventListener('click', () => {
if (colors.indexOf(myTextInput.value) > -1)
myHeading.style.color = myTextInput.value
else
alert("no color");
});

Categories

Resources