I'm trying to make a tictactoe game using javascript. I have the winning conditions in a nested array
const winConditions = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
]
and I have my current player's marked boxes indices in an array
let squaresIndices = [0,4,8]
I'm trying to stop the game when any of the winning conditions occur. I have tried each of the following and I can't figure out why they don't work.
winConditions.forEach((array) => {
if (array === squaresIndices){
alert("Game Over")
}
//////
if (winConditions.includes(squaresIndices)){
alert ("Game Over")
}
//////
winConditions.some((arr) =>{
if (arr.every((square) => {
squaresIndices.includes(square)
})) {
alert("Game Over")
}
})
First of all
Array cannot be compared
Try this example
let a = [0,2,3]
let b = [0,2,3]
alert( a === b )
What you need to understand is that
when you save an array. What you actually doing is created a reference to that array in memory.
Then again try this example
let a = [0,2,3]
let b = a
alert( a === b )
You will get true, Why? Because in first case you are trying to two separate addresses in memory. Meaning that a & b got different addresses but same kind of apartment. But in second case you are comparing the same address.
So the easiest way you can do is convert them into string then try to compare them.
JSON.stringify(a)==JSON.stringify(b)
Then you will get your desire result. While this could work if the order of the properties will always the same for those array instances, this leaves the door open for extremely nasty bugs that could be hard to track down.
Your last example is correct if not for forgetting to return the value and moving the if outside.
const winConditions = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
const squaresIndices = [0, 4, 8];
const isWin = winConditions.some(
(arr) =>
{
// return if this combination is matching or not
return arr.every(
(square) =>
{
// return if the value matches or not
return squaresIndices.includes(square);
}
);
}
);
// Then test the result
if (isWin)
{
alert("Game Over");
}
winConditions.forEach((array) => {
if(JSON.stringify(array)==JSON.stringify(squaresIndices)){
alert("Game Over")
}
})
You cannot compare two arrays directly in javascript. You need to convert it to string for comparison. You can also use toString() instead of JSON.stringify()
Related
This question already has answers here:
How to check if an array contains another array?
(6 answers)
javascript search array of arrays
(12 answers)
Closed 3 months ago.
How I can scan my array within array if there is equal array element.
I want to check if its true or false
// the array to be scan
const array = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
]
// the new array
const newArray = [0, 1, 2]
Based on anwser from how-to-compare-arrays-in-javascript,you just need to iterate the first array and then compare them
const array = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
]
// the new array
const newArray1 = [0, 1, 2]
const newArray2 = [0, 1, 3]
const checkArray = (array1,array2) => {
for(let arr of array1){
if(arr.length === array2.length && arr.every((v,i) => v === array2[i])){
return true
}
}
return false
}
console.log(checkArray(array,newArray1))
console.log(checkArray(array,newArray2))
You can use every method to check all the items.
array.filter((arr)=>arr.every((item,index)=>newArray[index]===item))
run a foreach or for loop with a combination of name.find(x => x.ref === value);
or use array.filter((arr)=>arr.every((item,index)=>newArray[index]===item))
const array = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
];
const newArray = [0, 1, 2]
let isPresent = false;
for (let i = 0; i < array.length; i++) {
if (JSON.stringify(array[i]) == JSON.stringify(newArray)) {
isPresent = true
break
}
}
console.log(isPresent)
After stringifying the array you are able to compare directly in js and If it matches I changed the boolean value to true.
In case you have any doubts feel free to comment.
I have an array of 3 value arrays, and I need to convert them into a set of arrays where each array is made up of the values which were common between arrays, so my input of
[[2,3,9], [1,4,7], [3,6,9], [1,7,5], [7,5,8], [9,6,10], [3,6,10], [1,8,5]]
becomes
[[2,3,6,9,10],[1,4,5,7,8]]
Order is not important. I've found similar questions such as Group same values in an array within an array in JS but it seems slightly different to my case, but I imagine using reduce is the way to go, but I don't entirely understand how. I have tried creating an object using the following format, but couldn't get from there to an answer:
{
vertex: 3,
triangles: [2,3,9], [3,6,9], [3,6,10]
}
Here is one algorithm. Take first item from array and check first item array has any common array. If they have common item, then merge it and move the merged array to first item of array. If no common item, then add to result array.
const merge = (arr) => {
const result = [];
while (arr.length > 0) {
let first = arr.shift();
const idx = arr.findIndex((items) =>
items.some((item) => first.includes(item))
);
if (idx !== -1) {
first = first.concat(arr[idx]);
arr.splice(idx, 1);
arr.unshift(first);
} else {
result.push(first);
}
}
return result.map(items => [...new Set(items)]);
};
const data = [
[2, 3, 9],
[1, 4, 7],
[3, 6, 9],
[1, 7, 5],
[7, 5, 8],
[9, 6, 10],
[3, 6, 10],
[1, 8, 5],
];
console.log(merge(data));
Here's a sample of the problem I'm having in JavaScript:
first array [1, 2, 3, 4, 5, 6, 7]
second array [7, 8, 9, 4, 2, 5, 7]
In this case, I need to be able to find and eliminate "4" and "7" from both arrays, eliminating both. This is based on their location and matching value.
I haven't been able to find anything other than eliminating matching values. In this case, however, the values must be in the same place and also be matching.
I've tried this so far:
function findCommonElements3(array1, array2) {
return arr1.some(item => arr2.includes(item))
}
it looks like it only looks for matching elements, whereas I need to find matching corresponding elements and then remove them.
As mentioned in the comments, you may use the splice method to remove one or more elements of an array in JavaScript.
First of all I would store the indexes of the elements I should remove looping the array as so:
const array1 = [1, 2, 3, 4, 5, 6, 7];
const array2 = [7, 8, 9, 4, 2, 5, 7];
//Indexes of same elements
var sameIndexes = [];
function findSameIndexes(element, index) {
if (array1[index] == array2[index]) {
sameIndexes.push(index);
}
}
array1.forEach(findSameIndexes);
Calling console.log(sameIndexes) should give this result:
Array [3, 6]
The problem is that if you loop again the array and remove the elements in that order, the indexes would not correspond to the elements anymore.
For example if you remove the 3rd element, the number 7 wouldn't be at index 6 anymore, to solve this issue I'd use the reverse method so you won't lose track of the indexes
// A simple function to remove the elements in both arrays
function removeElements(index) {
array1.splice(index,1);
array2.splice(index,1);
}
sameIndexes.reverse().forEach(removeElements);
And the final results would be
Array [1, 2, 3, 5, 6]
Array [7, 8, 9, 2, 5]
Which hopefully is what you were looking for, of course there are better ways to write it down, but maybe this will help you find a solution.
You could just use a for loop and use index. something like this
const firstarray = [1, 2, 3, 4, 5, 6, 7]
const secondarray = [7, 8, 9, 4, 2, 5, 7]
for (let i = 0; i <= firstarray.length - 1; i++) {
if (firstarray[i] === secondarray[i]) {
console.log(`found ${firstarray[i]} at index ${i}`);
firstarray.splice(i, 1);
secondarray.splice(i, 1);
}
}
console.log(firstarray, secondarray);
const excludeCommon = (ar1, ar2) => {
const both = [...ar1, ...ar2].filter((v, i, ar) => v !== ar[i + (2 * (i < ar1.length) - 1) * ar1.length]);
return [both.slice(0, both.length / 2), both.slice(both.length / 2)];
}
console.log(excludeCommon([1, 2, 3, 4, 5, 6, 7], [7, 8, 9, 4, 2, 5, 7]));
I have to make a tic tac toe game, and for it to work I need to have a function to check if there are 3 in a row.
the grid is like this
012
345
678
It means 012, 345, 678, 036, 147, 258, 048, 246 are all possible combinations.
I tried:
if(clickedCells[0] && clickedCells[1] && clickedCells[2] !== "" && clickedCells[0] === clickedCells[1] && clickedCells[0] === clickedCells[2]){
done();
}
But it doesn't work because it is invalid.
I would like to know the best way to get such a thing working, because I have never had to so much if-statements in a row and it looks like a total mess if I check each thing independently.
You can store every valid combination in an array.
var combinations = new Array([0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]);
Now instead of setting up an if-condition for a single combination you can loop over the entire array and check your board at the position specified.
if (board[combinations[a][0]] == id && board[combinations[a][1]] == id && board[combinations[a][2]] == id)
Here's the compelte example:
var board = new Array(
1, 0, 0,
0, 1, 0,
0, 0, 1
);
function check(id) {
var ret = null;
var combinations = new Array([0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]);
var found;
for (var a = 0; a < combinations.length; a++) {
if (board[combinations[a][0]] == id && board[combinations[a][1]] == id && board[combinations[a][2]] == id) {
ret = combinations[a];
break;
}
}
return ret;
}
console.log(check(1));
clickedCells[0] && clickedCells[1] && clickedCells[2] !== ""
This code seems to compares 3 boolean variables to an empty string.
But if the clickedCells contains strings the proper way to compare would be
clickedCells[0] + clickedCells[1] + clickedCells[2] !== ""
You can create a multidimensional array which contain all the possible combinations.
let arr = [[0,1,2],[3,4,5]....]
Then use some() with every(). Consider that you array is called game. So you can check for winning like below.
arr.some(x => x.every(a => game[a] === game[x[0]]))
Explanation:
some() is array method which takes a callback and checks if atleast one of the element of array matches the condition. So here different array means x will be
[0,1,2],[3,4,5]...
Now for each of the nested array we need to check if they are same in the game which is 1D array representing tic tac toe game.
x.every(a => game[a] === game[x[0]])
The above line checks for each of the nested array if any one that have all same elements when they are used and indexes for game board.
It means 012, 345, 678, 036, 147, 258, 048, 246 are all possible combinations
So just hard-code that combinations
const winningSets = [[0, 1, 2], [3, 4, 5], ...];
return winningSets.some((winningSet) =>
winningSet.every((cell) => cell === 'O'));
See, typically we would like avoid hard-coding values but for this specific case index-based math would look complicated and less readable. Especially when matrix is represented as linear array.
I want to get values from an array of arrays, and I'm having difficulties doing it.
I have the following:
var id = 1; //value I want to use for the search
var _restrictions = [[1, 2], [2, 4], [5, 1], [1, 6]]; //arrays that I want to check
var arrVal = [];
By using the id, I want to retrieve all of the values, inside the arrays, where the id exits and store them in the array "arrVal".
For example:
_restrictions = [[1, 2], [2, 4], [5, 1], [1, 6]];
//arrVal will be: [2, 5, 6], because the id existing inside the arrays [1,2],
//[5,1] and [1,6]
The "_restrictions" array is a array of arrays that contain restrictions. They are independent values (the first one isn't the index or id).
How can I do that?
Thanks in advance!
Here's a version that will work for any size of nested array. It returns an flattened array of all values not including the id.
var id = 1;
var _restrictions = [[1, 2, 9], [2, 4], [5, 1], [1, 6]];
var arrVal = _restrictions.reduce((acc, c) => {
// Find the index of the id in each nested array
const i = c.findIndex(arr => arr === id);
// If it exists, splice it out and add it
// to the accumulator array
if (i > -1) {
c.splice(i, 1);
acc.push(...c);
}
return acc;
}, []);
console.log(arrVal);
EDIT: Updated code after the question is edited.
The question lacks a bit of clarity. I am assuming you want to filter the sub-arrays which have id in them i.e. contains the value 1.
let id = 1; //value I want to use for the search
let _restrictions = [[1, 2], [2, 4], [5, 1], [1, 6]];
let arrVal = _restrictions.filter((item) => {
return item.includes(id);
});
let new_array = arrVal.concat.apply([], arrVal).filter(x => x !== id);
console.log(new_array);
// [2, 5, 6]