Interesting if/else if conditional chain problem - javascript

I am having a hard time figuring out why this code is working the way it is. Below, I have all of the code that produces my tic tac toe game. The game works as intended until we come to a full board that SHOULD result in a win for either 'O' or 'X'. My current logic sometimes will work as intended and pick the correct winner but a majority of the time, it will produce a 'DRAW', even if the last move on the last square should result in a win. Given the if/else if chain, I don't see how that would work? The applicable if/else if statement is the second set.
Here is my code:
$(document).ready(function() {
let addX = "<h1>X</h1>"
let addO = "<h1>O</h1>"
let turn = []
let board = [$("#one"), $("#two"), $("#three"), $("#four"), $("#five"),$("#six"), $("#seven"), $("#eight"), $("#nine")]
let combos = [[0,1,2], [3,4,5], [6,7,8], [0,3,6], [1,4,7], [2,5,8], [0,4,8], [6,4,2]]
for (let i = 0; i < board.length; i++){
board[i].click(function(){
if (turn.length === 0){
turn.push(board.indexOf(board[i].html(addX)) + "X")
} else if (turn.length % 2 !== 0 && board[i].html() === ''){
turn.push(board.indexOf(board[i].html(addO)) + "O")
} else if (turn.length % 2 === 0 && board[i].html() === ''){
turn.push(board.indexOf(board[i].html(addX)) + "X")
}
for(let i = 0; i < combos.length; i++){
if (turn.includes(combos[i][0] + 'O') && turn.includes(combos[i][1] + 'O') && turn.includes(combos[i][2] + 'O') ){
alert('O IS WINNER!')
setTimeout(function() {$("#ttt_table tbody tr td").html(""); }, 1500);
turn.length = 0
} else if(turn.includes(combos[i][0] + 'X') && turn.includes(combos[i][1] + 'X') && turn.includes(combos[i][2] + 'X') ){
alert('X IS WINNER!')
setTimeout(function() {$("#ttt_table tbody tr td").html(""); }, 1500);
turn.length = 0
break
} else if (turn.length === 9){
alert('DRAW!')
setTimeout(function() {$("#ttt_table tbody tr td").html(""); }, 1500);
turn.length = 0
}
}
})
}
});
Here is a codepen to test out the game itself:
https://codepen.io/tylerp33/pen/NeOxyY
Basically, shouldn't the game see there's a winning combo in:
else if(turn.join("").includes(combos[i][0] + 'X') && turn.join("").includes(combos[i][1] + 'X') && turn.join("").includes(combos[i][2] + 'X')
before the last
else if (turn.length === 9) produces a 'DRAW'?
Thanks for your help!

Without changing or doing much refactoring, adding this to the last condition worked. Basically, making the if/else run through all the combos before deciding on a draw did the trick. Thanks for all the help!
else if (turn.length === 9 && combos[i] === combos[combos.length - 1]) {
alert('DRAW!')
setTimeout(function() {$("#ttt_table tbody tr td").html(""); }, 1500);
turn.length = 0
}

Related

I can't solve the Counting Cards problem on freeCodeCamp [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 10 months ago.
Improve this question
This is the freeCodeCamp Counting Cards activity.
https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/basic-javascript/counting-cards
My solution was
let count = 0;
function cc(card) {
// Only change code below this line
if (card = 2 || 3 || 4 || 5 || 6) {
count + 1;
} else if (card = 7 || 8 || 9) {
return;
} else if (card = 10, "J", "Q", "K", "A")
count - 1;
}
if (count > 0) {
return count + " " + "Bet";
} else if {
return count + " " + "Hold";
}
// Only change code above this line
}
cc(2); cc(3); cc(7); cc('K'); cc('A');
I checked the solution and it seemed similar. Why didn't it work?
A Few Modifications were necessary for this code to work.
= is assignment operator while == is comparing operator.
else if can be replaced with just else if there is no condition.
the third else if (card = 10, "J", "Q", "K", "A") didnt have closing or opening brackets.
avoid using return at else if (card == 7 || 8 || 9) { and instead use count += 0
You need too add a condition for || Or operator like this card == 7 || card == 8 and not like card == 7 || 8
Use count++ and count-- instead of count + 1 and count - 1
After all these changes the below code works fine.
let count = 0;
function cc(card) {
// Only change code below this line
if (card == 2 || card == 3 || card == 4 || card == 5 || card == 6) {
count++;
} else if (card == 7 || card == 8 || card == 9) {
count += 0;
} else if (card == 10|| card == "J"|| card == "Q"|| card == "K"|| card == "A"){
count--;
}
if (count > 0) {
return count + " " + "Bet";
} else {
return count + " " + "Hold";
}
}
cc(2); cc(3); cc(7); cc('K'); cc('A');
There are two main issues with your code.
Wrong if condition
Your if condition card = 2 || 3 || 4 || 5 || 6 does not work like you think it does. You would need to use car === 2 || card === 3 || car === 4 || card === 5 || car === 6. You cannot use the assignment operator = like this. You should use the strict comparison operator instead.
It's even easier to use an array and includes() like this [2, 3, 4, 5, 6].includes(card).
count is not updated
You need to assign the new value to count when you increment/ decrement it. You can use count++ instead of count + 1 which is the equivalent to count = count + 1.
let count = 0;
function cc(card) {
// Only change code below this line
if ([2, 3, 4, 5, 6].includes(card)) {
count++;
} else if ([10, "J", "Q", "K", "A"].includes(card)) {
count--;
}
if (count > 0) return `${count} Bet`;
return `${count} Hold`;
}
cc(2); cc(3); cc(7); cc('K'); cc('A');
= is used to assign a value and not to make comparison. In javascript we use == or === to make comparison, and also count - 1 will not update count. use count = count - 1 or count++
let count = 0;
function cc(card) {
// Only change code below this line
if ( card >= 2 && card <= 6) {
count = count + 1;
} else if (card >= 7 && card <= 9) {
return;
} else if (card === 10 || card === "J" || card === "Q" || card === "K" || card === "A")
count = count - 1;
}
if (count > 0) {
return count + " " + "Bet";
} else if {
return count + " " + "Hold";
}
// Only change code above this line
}
cc(2); cc(3); cc(7); cc('K'); cc('A');

JavaScript shortening long if-else

I am building an application similar to minesweeper where a user will click a square on a grid and the app will tell the user how many of the surrounding squares contain an 'X'. I have my code working when I only check up, down, left, and right. My code is beginning to get very long since there are quite a few edge cases to account for. I am going to begin checking diagonals for 'X's and I want to come up with a shorter way to check these cases.
Can anyone help me develop a for loop or other short hand way to write this code. Here is what I have so far for a 8x8 grid.
Here is my sandbox: https://codesandbox.io/s/6y6wzo001w
showNumber= () => {
let Xcounter = 0;
console.log(this.props.keys)
console.log(this.props.reduxState.reducer.board[this.props.keys])
if(this.props.keys% 8 ===0){
if(this.props.reduxState.reducer.board[this.props.keys +1] === 'X'){
Xcounter++
}
}
if(this.props.keys% 8 ===7){
if(this.props.reduxState.reducer.board[this.props.keys -1] === 'X'){
Xcounter++
}
}
if(this.props.keys/8 <1){
if(this.props.reduxState.reducer.board[this.props.keys +8] === 'X'){
Xcounter++
}
}
if(this.props.keys/8 >=7){
if(this.props.reduxState.reducer.board[this.props.keys -8] === 'X'){
Xcounter++
}
}
if(this.props.keys % 8 !== 0 && this.props.keys % 8 !== 7){
if(this.props.reduxState.reducer.board[this.props.keys +1] === 'X'){
Xcounter++
}
if(this.props.reduxState.reducer.board[this.props.keys -1]=== 'X'){
Xcounter++
}
}
if(Math.floor(this.props.keys)/8 > 0 && Math.floor(this.props.keys)/ 8 < 7){
if(this.props.reduxState.reducer.board[this.props.keys +8] === 'X'){
Xcounter++
}
if(this.props.reduxState.reducer.board[this.props.keys -8]=== 'X'){
Xcounter++
}
}
if(this.props.id === 'X'){
this.setState({...this.state, clicked: true, counter: 'X'})
return this.state.counter;
}
this.setState({...this.state, clicked: true, counter: Xcounter})
return this.state.counter;
}
Assuming you have an array this.props.reduxState.reducer.boardof length 64 with 'X's or non-'X's, one could simply loop through the x and y directions like so:
let Xcounter = 0;
//save the board for shorter and more readable code
let board = this.props.reduxState.reducer.board;
//the current index we've clicked on
let c = this.props.keys;
//we're going to check if we're at the edge of the board.
//I'll explain these later.
let minX = c%8 == 0 ? 0 : -1;
let maxX = c%8 == 7 ? 0: 1;
let minY = (c-minX)/8 == 0 ? 0 : -1;
let maxY = (c-minY)/8 == 7 ? 0 : 1;
for( let x = minX; x <= maxX; ++x ){
for( let minY = -1; y <= maxY; ++y ){
if( board[c+x+8*y)] == 'X' ){ Xcounter++; }
}
}
//we also checked the square itself, but we didn't want to
if( board[c] == 'X' ){ Xcounter--; }
This assumes the indeces of the board are from right to left, and then top to bottom, not the other way around (i.e. board[7] is the top-right corner, not the bottom-left one).
As far as what this actually does; essentially, we look whether or not we're at the edge of a board, and find the relative x- and y-coordinates we have to check. To visualize:
Here minX=0, because going to the left of the current clicked square c would throw us off the board. maxX=1 though, because we can check to the right of the clicked square. Similarly, we check the y-coordinates.
Assuming that your checks are already correct, let's work with what you already have.
Try to rewrite what you actually have with more condensed style to get an overview as a first step and introduce a board side constant as a second:
showNumber = () => {
const BOARD_SIDE = 8;
let Xcounter = 0;
let keys = this.props.keys;
let board = this.props.reduxState.reducer.board;
console.log(keys);
console.log(board[this.props.keys]);
for (let edge = BOARD_SIDE; edge < BOARD_SIDE * BOARD_SIDE; edge += BOARD_SIDE) {
if (keys % edge === 0 && board[keys + 1] === "X") Xcounter++;
if (keys % edge === (edge - 1) && board[keys - 1] === "X") Xcounter++;
if (keys / edge < 1 && board[keys + edge] === "X") Xcounter++;
if (keys / edge >= (edge - 1) && board[keys - edge] === "X") Xcounter++;
if (keys % edge !== 0 && keys % edge !== (edge - 1)) {
if (board[keys + 1] === "X") Xcounter++;
if (board[keys - 1] === "X") Xcounter++;
}
if (Math.floor(keys) / edge > 0 && Math.floor(keys) / edge < (edge - 1)) {
if (board[keys + edge] === "X") Xcounter++;
if (board[keys - edge] === "X") Xcounter++;
}
}
if (this.props.id === "X") {
this.setState({ ...this.state, clicked: true, counter: "X" });
return this.state.counter;
}
this.setState({ ...this.state, clicked: true, counter: Xcounter });
return this.state.counter;
};

The Conditions In My First While Loop Seems To Not Be Working Properly

<script>
function Play() {
var guesses = 1
var number = 0
var points = 0
var cp = 0
var level = " "
var x = 0
while (level != "a" || "A" || "b" || "B" || "c" || "C" || "d" || "D"){
level = prompt("Select Your Difficulty");
if (level == "a" || "A" || "b" || "B" || "c" || "C" || "d" || "D") {
if (level == "a" || level == "A") {
x = 30;
}
else if (level == "b" || level == "B") {
x = 50;
}
else if (level == "c" || level == "C") {
x = 70;
}
else if (level == "d" || level == "D") {
x = 100;
}
}
else if (level != "a" || "A" || "b" || "B" || "c" || "C" || "d" || "D") {
if (level == null) {
return;
}
else {
alert("You Went Sphagetti On Your Keyboard And Missed");
}
}
}
var answer = Math.floor(Math.random() * x) + 1;
number = prompt("What Is Your First Guess?");
if (number == null) {
return;
}
//The Beginning Of The While Loop
while (guesses <= 4) {
//Give The User A Point And Restart The Guesses
//Generate A New Number For Them To Guess
if (number == answer) {
alert("You Guessed Correctly! You Get One Point!");
alert("The Number Will Now Change, But Will Still Be Within 1-30");
guesses = 1;
points = points + 1;
answer = Math.floor(Math.random() * x) + 1;
number = prompt("What Is Your Guess For The New Number?");
if (number == null){
return;
}
//If The Number The User Guessed Equals The Answer
//Go Back To The Start Of The Loop
else if (number == answer) {
continue;
}
}
if (number < answer) {
alert("Wrong! The Number Is To Low! NACHO CHEESE");
}
else if (number > answer) {
alert("Wrong! The Number Is To High! YOU ARE SHELLFISH!");
}
number = prompt("You've Made " + guesses + " Guess(es)");
if (number == null) {
return;
}
if (number == answer) {
continue;
}
else if (number != answer) {
guesses = guesses + 1;
}
}
//If The User Gets Wrong On All 5 Guesses
//Tell Them They Lost And Give Them The Answer
//Display Their Total Points
alert("You Have Guessed Incorrectly 5 Times. The Number Was " + answer);
cp = points.toString();
document.getElementById("points").innerHTML= "Point Streak: " + cp;
}
</script>-
Hello, I was wondering why the conditions in my first while loop do not seem to be working properly. When I enter in a letter that should break out of the loop since the condition is while it is not equal to one of these letters, it just ends up asking me to again to ("Select Your Difficulty"). Before it was also giving me the "You Went Spaghetti On Your Keyboard And Missed") When I entered in a letter that should break out of the loop... If I am not mistaken if should not even be entering that else if in the first place if I enter in one of those letters right? Please guide me where I went wrong.

Why does the score not equal 0 when I roll a 1?

So I'm making a dice game where if either ofd the dice roll a 1, the score is 1, but I can't seem to make that work. I believe everything else it ok.
var die1 = Math.floor(Math.random()*6 + 1);
var die2 = Math.floor(Math.random()*6 + 1);
var score;
if (die1 === 1 || die2 === 1){
score === 0;
}
if (die1 !== 1 || die2 !== 1){
score = die1 + die2;
}
console.log("You rolled a "+die1+" and a "+die2+" for a score of "+score);
First off, you don't set score to 0. Change score === 0 to score = 0.
Second, your second if is still evaluated. Try making it an else if:
if (die1 === 1 || die2 === 1){
score = 0;
}
else if ...
Tying together all of the great suggestions here:
if (die1 === 1 || die2 === 1) {
score = 1; // "if either of the dice roll a 1, the score is 1"
// Also, use = for assignment, not == or ===
}
else { // No need to check the inverse - just use else
score = die1 + die2;
}
if (die1 === 1 || die2 === 1) {
score = 1; // You are not comparing you are assigning here
}
else if ... // Better use else if than using if as in your code
For more information :-
else if javascript

Javascript Fizzbuzz Issue

I'm trying to do some simple tests to help further my javascript knowledge (which is quite fresh). Goal 1 is to print numbers from 1-100 that aren't divisible by 5 or 3.
I tried the following:
for (var i = 1; i <= 100; i ++)
{
if (i%3 !== 0 || i%5 !== 0){
console.log(i);
}
}
This logs EVERY number from 1-100, and I can't tell why. Probably the simplest simplest questions here but it's doing my head in!
I think you mean &&, not ||. With ||, you're basically testing to see if the number is not divisible by 3 or by 5 - only if a number is divisible by both do you reject it (in other words, multiples of 15).
The typical answer to FizzBuzz is:
if( i%3 == 0 && i%5 == 0) FizzBuzz
elseif( i % 3 == 0) Fizz
elseif( i % 5 == 0) Buzz
else number
So to get directly to the number you need for i%3==0 to be false AND i%5==0 to be false. Therefore, you want if( i%3 !== 0 && i%5 !== 0)
Here's a quite simple FizzBuzz function that accepts a range of numbers.
function fizzBuzz(from, to) {
for(let i = from; i <= to; i++) {
let msg = ''
if(i % 3 == 0) msg += 'Fizz'
if(i % 5 == 0) msg += 'Buzz'
if(msg.length == 0) msg = i
console.log(msg)
}
}
fizzBuzz(1, 25)
As for a more complex solution, that's one way you could define a higher order function which generates customized FizzBuzz functions (with additional divisors and keywords)
function fizzBuzzFactory(keywords) {
return (from, to) => {
for(let i = from; i <= to; i++) {
let msg = ''
Reflect.ownKeys(keywords).forEach((keyword) => {
let divisor = keywords[keyword]
if(i % divisor == 0) msg += keyword
})
if(msg.length == 0) msg = i
console.log(msg)
}
}
}
// generates a new function
const classicFizzBuzz = fizzBuzzFactory({ Fizz: 3, Buzz: 5 })
// accepts a range of numbers
classicFizzBuzz(1, 25)
const extendedFizzBuzz = fizzBuzzFactory({ Fizz: 3, Buzz: 5, Bazz: 7, Fuzz: 11 })
extendedFizzBuzz(1, 25)
I attacked this the same was as Niet the Dark Absol:
for (var n = 1; n <= 100; n++) {
if (n % 3 == 0 && n % 5 == 0)
console.log("FizzBuzz");
else if (n % 3 == 0)
console.log("Fizz");
else if (n % 5 == 0)
console.log("Buzz");
else
console.log(n);
}
However, you can also do it this way:
for (var n = 1; n <= 100; n++) {
var output = "";
if (n % 3 == 0)
output += "Fizz";
if (n % 5 == 0)
output += "Buzz";
console.log(output || n);
}
One of the hardest parts of learning JavaScript - or any language - for me is understanding solutions can come in many ways. I like the first example more, but it's always good to keep thinking and look at other options.

Categories

Resources