Greetings to everyone,
There is a game frequently played in Turkey. Its name is Scratch.
The rules of the game are as follows:
- If the same three numbers appear in any matrix (3x3, 4x4, 4x3), that number wins.
- There cannot be more than one winning number in a matrix.
Let's consider a 3x3 matrix.
// In this matrix, both 50, 20, and 5 win. This is a mistake.
[ [ 50, 20, 50 ], [ 5, 5, 20 ], [ 50, 5, 20 ] ]
// There are four 50's in this matrix. There can be a maximum of three of a number.
[ [ 50, 20, 50 ], [ 5, 50, 20 ], [ 10, 5, 50 ] ]
// There is no winner in this matrix, but the rules are correct.
[ [ 50, 20, 50 ], [ 5, 5, 20 ], [ 10, 40, 10 ] ]
// The number 10 wins in this matrix. And it is true.
[ [ 50, 20, 50 ], [ 5, 10, 20 ], [ 10, 40, 10 ] ]
I couldn't write a NodeJS algorithm that created this.
exports.scratchCard = async (req, res) => {
let numArray = [5, 10, 20, 40, 100, 5, 5, 10, 5, 20, 5, 40];
let matrix;
matrix = create3x3Matrix(numArray);
console.log("Matrix:", matrix);
let winningNumber = findWinningNumber(matrix);
console.log("Winning Number:", winningNumber);
return res.json({ matrix, winningNumber });
};
function create3x3Matrix(numArray) {
let matrix = [];
for (let i = 0; i < 3; i++) {
let row = [];
for (let j = 0; j < 3; j++) {
let randomNumber;
do {
let randomIndex = Math.floor(Math.random() * numArray.length);
randomNumber = numArray[randomIndex];
} while (
(findNumberCount(matrix, randomNumber) >= 3) &&
(findWinningNumber(matrix) != undefined)
);
row.push(randomNumber);
}
matrix.push(row);
}
return matrix;
}
function findNumberCount(matrix, searchingNumber) {
let count = 0;
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
if (matris[i][j] === searchingNumber) {
count++;
}
}
}
return count;
}
function findWinningNumber(matrix) {
let numberCounts = {};
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix.length; j++) {
let number = matrix[i][j];
if (numberCounts[number]) {
numberCounts[number]++;
} else {
numberCounts[number] = 1;
}
}
}
let winningNumber;
for (let number in numberCounts) {
if (numberCounts[number] === 3) {
winningNumber = number;
break;
}
}
return winningNumber;
}
Some returns
Matrix: [ [ 40, 5, 20 ], [ 40, 10, 5 ], [ 10, 20, 100 ] ]
Winning Number: undefined
Matrix: [ [ 5, 5, 40 ], [ 5, 5, 5 ], [ 20, 20, 40 ] ]
Winning Number: undefined
Matrix: [ [ 5, 5, 5 ], [ 10, 10, 40 ], [ 10, 20, 100 ] ]
Winning Number: 5
Matrix: [ [ 40, 10, 20 ], [ 40, 5, 5 ], [ 20, 10, 10 ] ]
Winning Number: 10
Matrix: [ [ 5, 20, 5 ], [ 5, 20, 5 ], [ 20, 10, 40 ] ]
Winning Number: 20
Matrix: [ [ 10, 5, 10 ], [ 5, 40, 40 ], [ 5, 10, 5 ] ]
Winning Number: 10
Matrix: [ [ 5, 5, 40 ], [ 20, 20, 20 ], [ 100, 5, 5 ] ]
Winning Number: 20
Matrix: [ [ 10, 40, 5 ], [ 5, 100, 10 ], [ 10, 100, 5 ] ]
Winning Number: 5
Matrix: [ [ 5, 40, 100 ], [ 40, 5, 10 ], [ 5, 5, 5 ] ]
Winning Number: undefined
I want to make a valid scratch card. It must comply with the rules I mentioned above. There is no win condition. It may lose.
If you just want to check a given card if there is a winning situation on it, the simplest probably would be the following
Ie flatten the nested array in a flat array of numbers and sort them ascending. Then iterate over the array and whenever you find an index
i
where the number at indexi
is equal to its two precessors, it's a possible winning number.If you find such a possible winning number, but you already discovered a potential winning number earlier, you have an invalid scratch card, so return a "no win" situation (I encode this with a return value of
-1
).If you find exactly one winning situation return the winning number
If you find no winning situation at all, return again
-1
for "no win"To create a valid scratch card you can use this simple algorithm
Initialize an empty scratch card with rows and columns
Whenever you create a new random number check, if you can add it to the card without violating the rules
It's either used less than 2 times currently
It's used exactly two times and there is no other winning number already on the card
Be aware, this way of filling the scratch card may lead to an infinite loop if the size of the card and the range of possible numbers don't fit together. For instance you won't be able to fill a 10x10 card with numbers only in the range 1..20