Question

I'm writing a game in PHP. There are 52 elements in an array 0 to 51. The goal is to create a random list each time that is unique from the previous list. So that there is no sequence pattern from the first list in the next one. For example, if the first list has a pattern contained as 7654, we don't want a pattern of 7654 to appear immediately in the next list.

The rule is that the first element of the list and the last element can't be the start and end elements from the previous list. For example if the first list starts and ends with:

0
...
51

Don't want the next list to start with 51 and end with 0.

I'm been thinking about how to approach this. I'm aware of the shuffle function in PHP, but each time it generates a random list it has no knowledge of the previous list. Again, the lists need to be unique directly from it's previous list, not from any other list it generates for the player.

The overall goal is that each list has no relationship or common pattern to it's previous list.

I don't know if there is a name for these kind of random lists.

How could this be done in PHP? Thanks!

Might this be done by using a random method which uses a different "seed" number each time it randomizes the list?

The pattern sequence is 4. So if 7654 appeared in the previous list, then the new list can't have 7654 in it.

Was it helpful?

Solution

I think I've got a solution that should work to meet these constraints.

function nextList($last) {
    $index = rand(1,50); // don't select first or last elements
    $out = array();
    do {
        list($value) = array_splice($last, $index, 1);
        $out[] = $value;
        $maxLoop = count($last);
        do {
            $newIndex = array_rand($last);
        } while ($newIndex == $index && --$maxLoop);
        $index = $newIndex;
    } while (count($last) > 1);
    $out[] = $last[0];

    return $out;
}

Used as follows:

$first = range(0, 51);
shuffle($first);
$second = nextList($first);
$third = nextList($second);
// etc.

This works on the basis that, for each element it adds to the new array, it is not proceeded by the same element that proceeds it in the last array.

For example, if the last array had, somewhere, the values 43,12,13..., and we add the element 43 to the new array, then we ensure that the next element is any element EXCEPT 12. With this logic, it should be impossible to get the same repeated sequences.

It also ensures that the first element is neither the first nor last element of the last array, however, making this constraint work also for the last element of the array would be a lot more difficult.

EDIT

I was actually able to use the check function given in Hendriq's answer to check whether this solution works, and it seems to always return a valid new list which does not contain a sequence from the last array =]

OTHER TIPS

Well there are is a small problem with the assumptions you have

Rule 1

The overall goal is that each list has no relationship or common pattern to it's previous list.

Rule 2

The rule is that the first element of the list and the last element can't be the start and end elements from the previous list.

Those two contradict each other. First there may be no relationship, so random. So as you said shuffle (did not look at is I take your word). But the second one needs to know about the previous one. What contradicts with your previous rule.

But what you could do is have the first and last element of the previous draw (the previous 52). Then you shuffle the current draw. If the first and/or last element are the same, draw again until no match is found.

Also I think the word for this is semi-random.

Look at the do{ }while(); for the trick.


After the comment of not having the same 4 elements after each other the next part came.

What you need is way to identify the elements, so lets assume every "item" has an id (for the purpose of the example I only use 5 elements)

Lets use the following

array(
  0 => array('id' => 1,),
  1 => array('id' => 2,),
  2 => array('id' => 3,),
  3 => array('id' => 4,),
  4 => array('id' => 5,),
)

The next draw is exaclty the same (just for the purpose of the exaple). What we do is we make an array of the ids that are drawn:

array(
  0 => 1,
  1 => 2,
  2 => 3,
  3 => 4,
  4 => 5,
)

Then use this array in the following function (not checked but should give you a right start)

function check(array $prev, array $draw, $the_same = 4) {
  $to_check = count($prev) - $the_same;
  for($i = 0; $i < $to_check; $i++) {
    if ($array_slice($prev, $i, $the_same) === array_slice($draw, $i, $the_same)) {
       return false;
    }
  }
  return true;
}

What is does, you give it the old array and the one you drew, and you give the number with it with how many occurence may be after eachother that maybe the same. Then it just start looping and array slicing to check if they are equal.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top