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
Related
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;
}
I'm new with JS, I'm trying to figure out, what causes this result in condition:
if ((y1 == true || y2 == true || y3 == true || y4 == true || y5 ==true || y6 == true || y7 == true || y8 == true) && (n1 == false || n2 == false || n3 == false)) {
document.getElementById("demo1").innerHTML = "YES";
} else if ((y1 == false || y2 == false || y3 == false || y4 == false || y5 ==false || y6 == false || y7 == false || y8 == false) && (n1 == true || n2 == true || n3 == true)) {
document.getElementById("demo1").innerHTML = "NO" ;
} else if ((y1 == true || y2 == true || y3 == true || y4 == true || y5 ==true || y6 == true || y7 == true || y8 == true) && (n1 == true || n2 == true || n3 == true)){
document.getElementById("demo1").innerHTML = "BOTH TRUE";
} else if ((y1 == false || y2 == false || y3 == false || y4 == false || y5 ==false || y6 == false || y7 == false || y8 == false) && (n1 == false || n2 == false || n3 == false)){
document.getElementById("demo2").innerHTML = "BOTH FALSE";
}
if I have number of different words to find specific words in string by content with bool value:
var input = "hello, yes and no"; // "hello, yes"; "hello no"; "hello"
var i = input.trim().toLocaleLowerCase();
var y1 = i.includes("yes");
var y2 = i.includes("sure");
var y3 = i.includes("i want");
var y4 = i.includes("yes i want");
var y5 = i.includes("ok");
var y6 = i.includes("oks");
var y7 = i.includes("okay");
var y8 = i.includes("okey");
var n1 = i.includes("no");
var n2 = i.includes("nope");
var n3 = i.includes("not now");
this way result looks correct:
if (y1 == true && n1 == false) {
document.getElementById("demo2").innerHTML = "YES";
} else if (y1 == false && n1 == true) {
document.getElementById("demo2").innerHTML = "NO" ;
} else if (y1 == true && n1 == true){
document.getElementById("demo2").innerHTML = "BOTH TRUE";
} else if (y1 == false && n1 == false){
document.getElementById("demo2").innerHTML = "BOTH FALSE";
}
if input "hello, yes" result is YES
if input "hello, no" result is NO
if input "hello, yes and no" result is BOTH TRUE
if input "hello" result is BOTH FALSE
but if I want this result with number of values, in this case listed directly in condition with logical statement result is incorrect:
if input "hello, yes" result is YES
if input "hello, no" result is NO
if input "hello, yes and no" result is YES (Incorrect)
if input "hello" result is BOTH FALSE
I'm not sure if it is logical error or I've missed something, looks like includes also accepts "ko" as content of "ok", so maybe this method is not the correct way to get desired result. Maybe it is easier just to split string and check each value. Anyway, I'm looking for the proper solution to find specific words in string, so any basic advice would be very helpful
(n1 == false || n2 == false || n3 == false) will be true as long as at least one of no, nope or not now is not present in your string. (See: DeMorgan's Law.)
You can try to create a function that validates and return the string.
Idea:
Create list of words for yes and no.
Now loop over these words and check for availability. You can use modern function like Array.some for this.
Now you have 2 flags which needs to be validated. As binary permutation, you just have 4 combination,
0 0 (both false)
0 1 (no yes word but no word exists)
1 0 (yes word exists but no no exists)
1 1 (both words exists)
Based on this, return necessary string.
Few suggestions:
Most expensive part of a code is the part where human interacts with it. So keep it as simple/ readable. Having so many || conditions will confuse developer that takes charge after you go.
Use meaningful names. y1... does not specify its purpose and anyone debugging will have to read the code to understand what is going on.
If you notice your code, y1 == false/true ... or n1 == false... is repeated multiple times in same function. Its better to create a variable and store its value. Its simpler and you are not being redundant.
Try to break your code in smaller parts. In your case, you can have following parts:
Interact with DOM. Accept value and set processed result.
Process accepted input and perform logic.
This way, your code will be more modular and scalable.
Sample code
function processInput(input) {
const yesWords = ["yes", "sure", "i want", "yes i want", "ok", "oks", "okay", "okey"];
const noWords = ["no", "nope", "not now"];
input = input.trim().toLocaleLowerCase();
const containsYesWord = yesWords.some((word) => input.includes(word));
const containsNoWord = noWords.some((word) => input.includes(word));
if (containsYesWord && !containsNoWord) {
return "YES";
} else if (!containsYesWord && containsNoWord) {
return "NO";
} else if (containsYesWord && containsNoWord) {
return "BOTH TRUE";
} else if (!containsYesWord && !containsNoWord) {
return "BOTH FALSE";
}
}
const sampleInput = [
"hello, yes",
"hello, no",
"hello, yes and no",
"hello"
];
sampleInput.forEach((input) => console.log(input, processInput(input)))
As Scott Hunter stated, while checking the absence of the string in your way, you're always getting true.
The right version of your condition is:
if ((y1 == true || y2 == true || y3 == true || y4 == true || y5 ==true || y6 == true || y7 == true || y8 == true) && (n1 == false && n2 == false && n3 == false)) {
document.getElementById("demo1").innerHTML = "YES";
} else if ((y1 == false && y2 == false && y3 == false && y4 == false && y5 ==false && y6 == false && y7 == false && y8 == false) && (n1 == true || n2 == true || n3 == true)) {
document.getElementById("demo1").innerHTML = "NO" ;
} else if ((y1 == true || y2 == true || y3 == true || y4 == true || y5 ==true || y6 == true || y7 == true || y8 == true) && (n1 == true || n2 == true || n3 == true)){
document.getElementById("demo1").innerHTML = "BOTH TRUE";
} else if ((y1 == false && y2 == false && y3 == false && y4 == false && y5 ==false && y6 == false && y7 == false && y8 == false) && (n1 == false && n2 == false && n3 == false)){
document.getElementById("demo2").innerHTML = "BOTH FALSE";
}
Notice that now there are ANDs instead of ORs between the false checks, and that's because none of them should be present.
I think you want to have a look at this
var input = "hello, yes and no"; // "hello, yes"; "hello no"; "hello"
var inp = input.trim().toLocaleLowerCase().split(/[^\w]/);
console.log(inp)
const y = ["yes",
"sure",
"i want",
"yes i want",
"ok",
"oks",
"okay",
"okey"]
const n = ["no","nope","not now"];
var found = {y:0,n:0}
for (let i=0;i < inp.length;i++) {
found["y"] += inp[i] && y.indexOf(inp[i]) !=-1 ? 1 : 0;
found["n"] += inp[i] && n.indexOf(inp[i]) !=-1 ? 1 : 0;
}
console.log(found)
if (found.y > 0 && found.n === 0) {
text = "YES";
} else if (found.y === 0 && found.n > 0) {
text = "NO";
} else if (found.y > 0 && found.n > 0) {
text = "BOTH TRUE";
} else if (found.y === 0 && found.n === 0) {
text = "BOTH FALSE";
}
document.getElementById("demo2").innerHTML = text;
<span id="demo2"></span>
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!");
}
I am trying to make a Tic-Tac-Toe with Javascript.
I used a method to compare the current input with the winning combination.
1)How to determine player 1 and player 2 input ?
2)i can compare 3 , but i can't figure out the 4th click for each player.
Kindly Advise.
var check = [[0,0,0],[0,0,0]]; //check[0] for player 1 , check[1] for player 2 , but i can't figure out how to increase the counter for each player on each click.
function playercol(ideal) //main
{
var idname = "box"+idval;
var currentcount = (playercount%2);
if( currentcount == 0 )
{
document.getElementById(idname).innerHTML="O";
}
else
{
document.getElementById(idname).innerHTML="X";
}
document.getElementById("player").innerHTML="Player "+((playercount%2)+1);
checkwin(check,0);//to check //0 is the current player index
playercount++;
}
My Fiddle
http://jsfiddle.net/1br5LLrj/3/
I tried to modify your code as little as possible http://jsfiddle.net/rrj24ze9/1
The essential part is the win check:
You don't need to remember what the player has clicked and compare that to a winning combo. Instead, iterate through the winning combinations and check if one of them contains only fields that are taken by the player.
var winning = [
[1, 2, 3], [4, 5, 6], [7, 8, 9],
[1, 4, 7], [2, 5, 8], [3, 6, 9],
[1, 5, 9], [3, 5, 7]
];
function checkwin(player) {
for (var i = 0; i < winning.length; i++) {
var combo = true;
for (var j = 0; j < 3; j++) {
if (document.getElementById('box' + winning[i][j]).innerHTML != markers[player]) {
combo = false;
}
}
if (combo) return true;
}
return false;
}
There is a lot of potential for improvement, like not using innerHTML (separation of data from view), or even preventing two clicks on the same field, but again, I tried to leave your code intact where possible.
Just made a tic tac toe in about 20 minutes from scratch for you.
JS Bin Here
Just alternating players right now... modify it to your own needs.
all win conditions will alert who winner is:
$(document).ready( function(){
function checkwin() {
if (
$('#a1').html() == "X" && $('#b1').html() == "X" && $('#c1').html() == "X" || $('#a2').html() == "X" && $('#b2').html() == "X" && $('#c2').html() == "X" || $('#a3').html() == "X" && $('#b3').html() == "X" && $('#c3').html() == "X" || $('#a1').html() == "X" && $('#a2').html() == "X" && $('#a3').html() == "X" || $('#b1').html() == "X" && $('#b2').html() == "X" && $('#b3').html() == "X" ||
$('#c1').html() == "X" && $('#c2').html() == "X" && $('#c3').html() == "X" ||
$('#a1').html() == "X" && $('#b2').html() == "X" && $('#c3').html() == "X" ||
$('#a3').html() == "X" && $('#b2').html() == "X" && $('#c1').html() == "X"
)
{
alert("winner is: X");
}
if (
$('#a1').html() == "O" && $('#b1').html() == "O" && $('#c1').html() == "O" || $('#a2').html() == "O" && $('#b2').html() == "O" && $('#c2').html() == "O" || $('#a3').html() == "O" && $('#b3').html() == "O" && $('#c3').html() == "O" || $('#a1').html() == "O" && $('#a2').html() == "O" && $('#a3').html() == "O" || $('#b1').html() == "O" && $('#b2').html() == "O" && $('#b3').html() == "O" ||
$('#c1').html() == "O" && $('#c2').html() == "O" && $('#c3').html() == "O" ||
$('#a1').html() == "O" && $('#b2').html() == "O" && $('#c3').html() == "O" ||
$('#a3').html() == "O" && $('#b2').html() == "O" && $('#c1').html() == "O"
)
{
alert("winner is: O");
}
}
var player = 1;
$('td').click(function(){
if(player == 1){
$(this).html("X").removeClass('o').addClass('x');
checkwin();
player++;
}
else if (player == 2){
$(this).html("O").removeClass('x').addClass('o');
checkwin();
player--;
}
});
});
Dont forget to use Jquery Library!
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
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