0

I'm trying to create a scratch card like system in php that displays a winner or loser based on random generate numbers.

I know i can create a random number using mt_rand or rand ranging from 0-9 but the issue i have is making sure there is no more than one duplicate of 3

9 digit number is out put with 100% no matching digits or a 9 digit number with one number appearing a maximum of 3 times like so 2948410427

the reason i am doing it this way is i have a lot of themed cards each theme has 10 small icons these icons are numbered 0-9 web the user opens my application it will randomly select a theme and then send a request to my server with this theme

the server will then generate the numbers and then these numbers will be output in json like so

{
    "Theme": "Space",
    "one": 3,
    "two": 6,
    "three": 0,
    "four": 7,
    "five": 1,
    "six": 3,
    "seven": 2,
    "eight": 9,
    "nine": 3,
    "winner": true
}

my application will then use these numbers to link to the images

1.png
2.png
3.png

and so on filling up the scratched grid.

this is the best way i can think todo it wile also allowing for random theme selection and random winners.

if anyone else can think of a better way i would be happy to hear it.

Dude2019
  • 95
  • 9
  • 1
    Put all digits three times in a string. Use `str_shuffle` and then print the first 9 digits. – Sindhara Mar 29 '19 at 19:41
  • You need to keep track of numbers drawn and apply the logic which you have specified here – MonkeyZeus Mar 29 '19 at 19:42
  • Should each run create one number with three equal digits and some other, or should it a random thing that it's three equal digits in the series? – Andreas Mar 29 '19 at 19:48
  • @Andreas it should generate a random 9 digit number. but i want to limit it so that if a single digit is duplicated 3 times it will not allow another of that digit or duplicates of any other digit more than twice this way every rumber that is generate is random and there is only ever the change of one number being duplicated by 3 at a time – Dude2019 Mar 29 '19 at 19:54
  • You didn't answer my question – Andreas Mar 29 '19 at 19:55

3 Answers3

1

If you shuffle and slice 3 times, slicing 3 values then you will get 9 values and only ever have at most 3 of any value:

$array = range(1, 9);
$keys  = array('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');

shuffle($array);
$result = array_slice($array, 0, 3);
shuffle($array);
$result = array_merge($result, array_slice($array, 0, 3));
shuffle($array);
$result = array_merge($result, array_slice($array, 0, 3));

$result = array_combine($keys, $result);

I like Severin Pappadeux's answer, with the following changes:

$array = array_merge($r = range(1, 9), $r, $r);
$keys  = array('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');
shuffle($array);
$result = array_combine($keys, array_slice($array, 0, 9));

To check for 3 of the same value, count the values and search for 3:

if($v = array_search(3, array_count_values($result))) {
    echo "You won with $v"; // :-)
} else {
    echo "Loser";           // :-(
}
AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
  • I tested this and i seem to be getting a winner once every 5 or so plays so this seems like a good option – Dude2019 Mar 29 '19 at 20:14
  • Do you know how i can tell if this now contains a winning code or not or am i going to have to loop over the array and check each value for a duplicta e and then coun the duplicates ? – Dude2019 Mar 29 '19 at 20:25
  • How do you define a winning code? I didn't see that in the question. – AbraCadaver Mar 29 '19 at 21:44
  • Not how do you define a winning code how do you tell if the code created is a winner ie contains 3 of the same digit – Dude2019 Mar 29 '19 at 22:12
  • Your amazing bud thanks a lot am not the best when it comes most of this php stuff – Dude2019 Mar 29 '19 at 22:25
  • This has been marked as the correct answer and is now working amazing with the rest of my script demo http://deltadude.com/cards/api.php?card=countries or http://deltadude.com/cards/api.php?card=money an image is being output perfect everytime :D – Dude2019 Mar 31 '19 at 00:58
1

Following answer of @AbraCadaver, how about (sorry, my PHP is very rusty)

$src  = array_merge($r=range(1, 9), $r, $r); /* 123456789123456789123456789 */
$keys = array('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine');

shuffle($src);
$result = array_slice($src, 0, 9);

$result = array_combine($keys, $result);

all combinations would be allowed and equally distributed with max 3 of repeating numbers

UPDATE

Just tried on http://phptester.net version where initial array is a bit different, and outcome (after pressing test button for 50 or so times) is visible a bit different. Curios if quality of shuffle() implementation is any good...

$src = array_merge(range(1, 9), range(9, 1, -1), range(1, 9)); /* 123456789987654321123456789 */
print_r($src);
shuffle($src);
$result = array_slice($src, 0, 9);
print_r($result);
Severin Pappadeux
  • 18,636
  • 3
  • 38
  • 64
  • I like this better than mine, but I would do `$src = array_merge($r=range(1, 9), $r, $r);` – AbraCadaver Mar 29 '19 at 21:57
  • @AbraCadaver Yes, definitely better - only one call to range. Thank you, answer updated (my last PHP production code is more than 10years old...) – Severin Pappadeux Mar 29 '19 at 22:08
  • See this is weird as i have noticed using this code with your modification as mentioned above produces a lot of doubles such as 88 or 55 or 22 in a row so key one and two would be the same number or key 5 and 6 would be the same number where as your origenal after running it about 40+ times seems to happen not so often i have so far stuck to @AbraCadaver first code and i have ported it over to java and python for other ports of my app – Dude2019 Mar 29 '19 at 22:11
  • @Dude2019 interesting. I've added `print_r()` after initialization, shuffling and slice and run it via http://phptester.net/, looks ok to me (PHP 7). But if you're happy with @AbraCadaver code, so be it - but it will produce statistically different result from mine, I believe – Severin Pappadeux Mar 29 '19 at 22:40
  • @AbraCadaver just tried another variation of the idea, please check update – Severin Pappadeux Mar 29 '19 at 22:47
0

Create a base with 2 x [0-9] range.
Add one random number then shuffle them all.

Slice out the first nine digits from the array and join them to create the scratch card.

This means it's random if the scratch card is a winning card and it's random what number is three of.

$base = array_merge(range(0,9), range(0,9));
$winning_number = [mt_rand(0,9)];

$all_numbers = array_merge($base, $winning_number);
shuffle($all_numbers);

$scratch_card = array_slice($all_numbers, 0,9);

echo join($scratch_card);

https://3v4l.org/NjItR

Andreas
  • 23,610
  • 6
  • 30
  • 62
  • Tested this one around 30 times now and its not shown one winner yet i got a feeling users may get annoyed by the win rate so i ,may have to rethink this – Dude2019 Mar 29 '19 at 20:14
  • @Dude2019 you can replace winning_number with a random array. `$winning_number = range(mt_rand(0,9), mt_rand(0,9));`. Here is an example how many times to a winning card: https://3v4l.org/OdQP2 – Andreas Mar 29 '19 at 21:23