Why is the 'o' is true? Javascript(Angular) - javascript

Help me please, I'm trying to make a rule for the little game and there is the problem.
I'm creating winning combination and say if the cell && cell+1 && cell+2 == to 'X' then you win, but when between two "X"s presents "o" it also says that "X" wins. Why? Please see my code and the game example on link a the bottom.
this.rezult = function(){
this.arr2.forEach(function(arr, i, innerArr){
arr.forEach(function(val, j){
var wincomb = innerArr[i][j] && innerArr[i][j+1] && innerArr[i][j+2];
var wincomb2 = innerArr[i][j] && innerArr[i+1][j] && innerArr[i+2][j];
var wincomb3 = innerArr[i][j] && innerArr[i+1][j+1] && innerArr[i+2][j+2];
console.log(wincomb == "X" && innerArr[i][j] !== "o");
// console.log(innerArr);
// THE RULE
if(wincomb == "X"){
alert(' X wins!');
}
});
});
};
Link to JSFiddle

In JavaScript, the && operator has interesting behavior with non-boolean values.
If the left-side of && is "truthy", the result is the right-side.
If the left-side of && is "falsey", the result is the left-side.
All non-empty strings are "truthy".
So, consider these examples:
("A" && "B" && "C") === "C"
("" && "B" && "C") === ""
(0 && "B" && "C") === 0
("X" && "X" && "O") === "O"
("O" && "O" && "X") === "X"
By the looks of it, you're trying to check if all 3 values are equal. You shouldn't use && for that, you should use === for that.
At the risk of doing your homework for you ;) here's a good way to do this:
function areTheSame(a,b,c) {
return a === b && b === c;
}
var down = areTheSame(innerArr[i][j], innerArr[i][j+1], innerArr[i][j+2]);
var across = areTheSame(innerArr[i][j], innerArr[i+1][j], innerArr[i+2][j]);
var diagonal = areTheSame(innerArr[i][j], innerArr[i+1][j+1], innerArr[i+2][j+2]);
if (down || across || diagonal) {
var winner = innerArr[i][j];
alert( winner + " wins!");
}

Related

Is there any mistake in comparing strings in JS?

I'm making tic tac toe game and I'm facing issue. If user's input is not equals to X or O then it should print the message Enter correct signs but I have no idea what's wrong in my code. Only else if's block is not working properly.
here is code of that function :
let p1, p2, s1, s2;
function startGame() {
playAgain();
p1 = document.getElementById("p1").value;
p2 = document.getElementById("p2").value;
s1 = document.getElementById("s1").value;
s2 = document.getElementById("s2").value;
if (p1 == "" || p2 == "" || s1 == "" || s2 == "") {
alert("Enter the details.");
playAgain();
} else if (
s1 != "X" ||
s1 != "x" ||
s1 != "O" ||
s1 != "o" ||
s2 != "X" ||
s2 != "x" ||
s2 != "O" ||
s2 != "o"
) {
alert("Enter correct signs.");
playAgain();
} else {
alert("You can start the game." + p1 + s1 + p2 + s2);
isStarted = true;
}
}
Thank you :D
Try to "and" your conditions instead of "oring" them.
else if (
(s1 != "X" &&
s1 != "x" &&
s1 != "O" &&
s1 != "o") ||
(s2 != "X" &&
s2 != "x" &&
s2 != "O" &&
s2 != "o")
)
I personally would make use of every function to make it even shorter and less repetitive:
const validInputs = ["X", "x", "O", "o"]
else if (validInputs.every((item) => s1 !== item)
|| validInputs.every((item) => s2 !== item)) {
...
It seems line a logic error on the if statement, i tried this and it works properly
if (
s1 != "X" &&
s1 != "x" &&
s1 != "O" &&
s1 != "o" ||
s2 != "X" &&
s2 != "x" &&
s2 != "O" &&
s2 != "o"
) {
But you also need to validate that s1 isn't equal to s2 because the users can type something like s1='X', s2='x' and it would be valid

Javascript filtering with multiple parameters

I need to filter my content with multiple parameters that I am taking from fields. The fields could also be empty, so I need to get all the values that are not empty. And filter by those.
What is the best way to achieve this without making a lot of if and else if conditions like this:
if (a !== '' && b !== '' && c !== '' && d !== '' && e !== ''){
// none is empty, filter by a & b & c & d & e
}
else if ( b !== '' && c !== '' && d !== '' && e !== ''){
// a is empty, filter by b & c & d & e
}
else if ( a !== '' && c !== '' && d !== '' && e !== ''){
// b is empty, filter by a & c & d & e
}
else if ( b !== '' && a !== '' && d !== '' && e !== ''){
}
else if ( b !== '' && c !== '' && a !== '' && e !== ''){
}
else if ( b !== '' && c !== '' && d !== '' && a !== ''){
}
else if ( c !== '' && d !== '' && e !== ''){
}
else if ( b !== '' && d !== '' && e !== ''){
}
else if ( b !== '' && c !== '' && e !== ''){
}
else if ( b !== '' && c !== '' && d !== ''){
}
else if ( a !== '' && d !== '' && e !== ''){
}
and so on...
Alternatively, how can I get all the unique possible combination of these 5 letters?
Edit ::
The actual code would look something like this
//a/b/c take value of dropdown items, that match with data on an object
if (a != '' && b != '' && c != '') {
for (const i in ParticipationList.TaskMetadata) {
if (ParticipationList.TaskMetadata[i].attendance == a && ParticipationList.TaskMetadata[i].monitoring_status == b && ParticipationList.TaskMetadata[i].monitoring_status == c) {
filteredaudience[i] = { ['id']: i }
}
console.log(filteredaudience)
// get all the items that match with the object properties
}
}
So if a or b or c is empty, I can't still make the same call, as it would not match anything on the object.
The logic:
Since javascript has short-circuit evaluation, we'll just use a bunch of conditions in the format:
field === "" || (condition to filter using field)
Because of said "short-circuiting", the right side part will only be reached if the field is not empty (i.e. if the left side is false because field !== ""). However, if the field is empty then field === "" will be true and the right side part won't be reached and the whole condition will yield true resulting in the filtering for this field to be skipped.
Multiple conditions should be joined together by the logical && operator and each one of those conditions should be wrapped in parenthesis () because the operator && is higher in precedence than the || operator.
If the data to filter is an array:
For arrays, just use the conditions as the value returned from the callback of filter like so:
let filteredData = data.filter(item =>
(a === "" || (condition for field 'a' against 'item'))
&&
(b === "" || (condition for field 'b' against 'item'))
&&
(c === "" || (condition for field 'c' against 'item'))
&&
(d === "" || (condition for field 'd' against 'item'))
&&
(e === "" || (condition for field 'e' against 'item'))
);
If the data to filter is an object:
In case the data is an object and you can't use filter like above, you can still use the same logic, you just have to use the conditions inside if like so:
let filteredaudience = {};
for (const i in ParticipationList.TaskMetadata) {
if ((a === "" || ParticipationList.TaskMetadata[i].attendance === a)
&& (b === "" || ParticipationList.TaskMetadata[i].monitoring_status === b)
&& (c === "" || ParticipationList.TaskMetadata[i].monitoring_status === c)
&& (d === "" || ParticipationList.TaskMetadata[i].?????????? === d)
&& (e === "" || ParticipationList.TaskMetadata[i].?????????? === e)) {
filteredaudience[i] = { id: i };
}
}
Depending on how the actual filtering process works, it might be possible to incrementally filter your result instead of doing it simultaneously.
For example, if your data is an array, you might write:
let data = ...;
if (a != '') {
data = data.filter(elem => checkForA(a, elem));
}
if (b != '') {
data = data.filter(elem => checkForB(b, elem));
}
...
Maybe you can also incrementally augment the filter object itself and THEN apply the built filter.
Please enter more details ...
For now, what I understood was that you want to get all the
values that are not empty.
for this:
let allElements = [a, b, c, d, e]
let notEmpty = []
allElements.forEach(element => {
if (element !== '')
notEmpty.push(element)
});
console.log(notEmpty)
A common mistake for new developers is to create long, complicated and repetative if statements with tons of && and || symbols or long strings of if/else if
Instead of this, write a simple search predicate. This is a function which takes some parameters, and reduces them to either true or false.
Within said function, run each filter one at a time. As soon as one fails, return false.
var data = [
{ colour : "red", weight : 2, name : "Example 1"},
{ colour : "orange", weight : 15, name : "Example 2"},
{ colour : "yellow", weight : 10, name : "Test 1"},
{ colour : "green", weight : 24, name : "Test 2"}
];
console.log(search(data, "red", [], ""));
console.log(search(data, "", [5,20], ""));
console.log(search(data, "", [], "Test"));
function search(data, colour, weights, name) {
return data.filter(row=>testRow(colour, weights, name, row));
}
// much easier to read.
function testRow(colourFilter, weightFilter, nameSearchFilter, row) {
// run each filter one at a time. If any fail, "short circuit" out.
if (colourFilter != "" && row.colour == colourFilter) {
return false;
}
// sometimes, a double if statemnt is easier to read.
if (weightFilter.length > 0) {
if (row.weight < weightFilter[0] || row.weight > weightFilter[1]) {
return false;
}
}
// sometimes, the actual rule is a bit complex.
if (nameSearchFilter != "") {
if (row.name.indexOf(nameSearchFilter) < 0) {
return false;
}
}
// we survived all filters.
return true;
}

Checking 3 values if are the same with If Statement

I am building a Tic Tac Toe game and I am wondering if this syntax could be valid. It seems the program sometimes is running correctly and sometimes not so i would like your opinion.
If ( (spacesArray[0] &&
spacesArray[1] &&
spacesArray[2] == (userDraw || compDraw))){
}
So basically i am checcking positions 0,1,2 in an Array if they have the same value ("x" OR "o"). Is this syntax correct?
**Edit
For anyone that want to see the full project here it is.
https://codepen.io/Ispaxan/pen/ZaRjZW?editors=0001
You mean the same value. So the first thing you need to check is 3 item was equally.
When 3 values was equally, you just need to check one of them equal userDraw or compDraw and done.
By this way. You can make your if statement run faster because when first or second condition was fail, javascript engine will not do a check for remain conditions.
if (spacesArray[0] === spacesArray[1] &&
spacesArray[0] === spacesArray[2] &&
(spacesArray[0] === userDraw || spacesArray[0] === compDraw) )
Edited: I was checking the Codepen and noticed that. This is gonna a bug if you check spacesArray[0] === (userDraw || compDraw). because (userDraw || compDraw) will always return userDraw.
I would have a separate check for if userDraw or compDraw so you can tell who wins. Also, use === instead of == for javascript quirky equality reasons.
// destructure array
const [a, b, c] = spacesArray;
// check if a is not null or undefined
// check if a and b are equal
// check if a and c are equal
if (a && a === b && a === c) {
// all 3 are the same value
// check if userDraw wins
if (a === userDraw) {
console.log(`${userDraw} wins`;
}
// check if compDraw wins
if (a === compDraw) {
console.log(`${compDraw} wins`;
}
}
** Elaborating on why the || won't work in this case. **
Setup:
const userDraw = 'x';
const compDraw = 'y';
const spacesArray = ['y', 'y', 'y'];
// (userDraw || compDraw) will be 'x'
Case:
if (spacesArray[0] &&
spacesArray[1] &&
spacesArray[2] == (userDraw || compDraw)
Here's where it fails:
if ('y' && // -> true
'y' && // -> true
'y' === 'x') // -> false
Case:
if (spacesArray[0] === spacesArray[1] &&
spacesArray[0] === spacesArray[2] &&
spacesArray[0] === (userDraw || compDraw))
Here's where it fails:
spacesArray[0] === spacesArray[1] // 'y' === 'y' -> true
spacesArray[0] === spacesArray[2] // 'y' === 'y' -> true
spacesArray[0] === (userDraw || compDraw) // 'y' === 'x' -> false
I think when you put just spacesArray[0] by itself then it checks if it is true or false.
you might want to try:
if ( (spacesArray[0] == (userDraw || compDraw) &&
spacesArray[1] == (userDraw || compDraw) &&
spacesArray[2] == (userDraw || compDraw))){
}
First verify the equality between answers, and finally if its O or X
if ( spacesArray[0] == spacesArray[1] &&
spacesArray[0] == spacesArray[2] &&
spacesArray[0] == (userDraw || compDraw))
First, it's if, not If and second, no, that's not the right syntax. Each test must be complete and independent of the others, as in:
if (spacesArray[0] == (userDraw || compDraw) &&
spacesArray[1] == (userDraw || compDraw) &&
spacesArray[2] == (userDraw || compDraw)){
}
But, in your case, none of that is necessary because you are performing the wrong test in the first place. You should be checking to see if all 3 elements in the spacesArray are the same value, that would mean that they are all "X's" or all "O's" and that can be most efficiently done with the Array.prototype.every() method.
function allX(currentValue) {
return currentValue === "X";
}
function allO(currentValue) {
return currentValue === "O";
}
var spacesArray1 = ["X", "O", "O"];
var spacesArray2 = ["X", "X", "O"];
var spacesArray3 = ["X", "X", "X"];
var spacesArray4 = ["O", "O", "O"];
console.log(spacesArray1.every(allX), spacesArray1.every(allO));
console.log(spacesArray2.every(allX), spacesArray2.every(allO));
console.log(spacesArray3.every(allX), spacesArray3.every(allO));
console.log(spacesArray4.every(allX), spacesArray4.every(allO));
// So, to test for tic-tac-toe:
function test(player){
if(spacesArray3.every(allX) || spacesArray3.every(allO)){
console.log(player + " wins!");
} else {
console.log("Not yet!");
}
}
test("Scott");

Validate CreditCard Number and checked radio button javascript

I have radio buttons radioVisa, and radioMaster. If either one is checked, I need to first check to see which one is selected and then validate that the card number entered is valid. I also need to make sure that only numbers are entered.... I am not allowed to use any regular expression techniques.... If the radioVisa is checked, it seems to work but when I added the code for the radioMaster, if it is checked it does't work.... Can someone tell me what I am doing wrong please....
function isValidCardNumber(num, isVisa, isMaster){
var card = new Array();
if (document.getElementById('radioVisa').checked){
card = isVisa;
}
if (num[0] != '4' || num.length != 16 ){
return false;
} else {
return true;
} else if (document.getElementById('radioMaster').checked){
card = isMaster;
}
if (num[0] != '51' || num[0] != '52' || num[0] != '53' ||
num[0] != '54' || num[0] != '55' || num.length != 16 ){
return false;
} else {
return true;
}
if (num[0] != '51' || num[0] != '52' || num[0] != '53' ||
num[0] != '54' || num[0] != '55' || num.length != 16 )
You can not combine all those numbers.You need to specify individually.
or
var numbers= ["51", "52", "53", "54",55];
var index = numbers.indexOf(num[0]);
It will return -1 if that is not exist otherwise return the index

how to fix jslint The '&&' subexpression should be wrapped in parens error

I put everything in parentheses but code below still throws error in jslint:
Problem at line 5 character 104: The '&&' subexpression should be wrapped in parens.
if ((typeof (c1) === 'string') && (typeof (c2) === 'string') && (c1 !== n...
How to fix ?
"use strict";
function t() {
var c1, c2;
if (((typeof (c1)) === 'string') && ((typeof (c2)) === 'string') && (c1 !== null) && (c2 !== null) && ((c1.trim()) === '') || ((c2.trim()) !== '')) {
return;
}
}
It's complaining about the form if(a && b && c || d) because (I suppose) it's not immediately obvious whether && or || will take precedence. Fix it to look like if(a && b && (c || d)) and it will stop complaining.
I think it wants this:
if (((typeof (c1) === 'string') && (typeof (c2) === 'string') && (c1 !== null) && (c2 !== null)) && ((c1.trim()) === '') || ((c2.trim()) !== '')) {
wrap the 4 anded expressions on the left of the && at 100.
I'm fairly certain you want the following:
function t() {
var c1, c2;
if (typeof c1 === 'string' && typeof c2 === 'string' && c1 !== null && c2 !== null && (c1.trim() === '' || c2.trim() !== '')) {
return;
}
}
Not everyone knows the precedence for boolean logic, so they want you to wrap the c1.trim() || c2.trim() statements in parenthesis so it's clear how they get operated.
As a side note, I think it's ridiculous that jslint wants spaces between my operators and my operands. I think it's much more clear when there is NOT a space.

Categories

Resources