Question

I'm a beginner with PHP (and programming in general). To test what I've learned so far I wrote this code, which prints all the possibile combinations of a set number of dice with a certain number of faces. (you'll find the code at the end).

What I want to do is dynamically change the number of nested for loops according to the $dicenumber variable. Right now it can only process 3 dice, since the code is:

            for ($d1=1; $d1 <= $d1value ; $d1++) { 
                for ($d2=1; $d2 <= $d2value ; $d2++) { 
                for ($d3=1; $d3 <= $d3value ; $d3++) { 
                        array_push(${sum.($d1+$d2+$d3)}, "$d1"."$d2"."$d3");
                    }
                }
            }

But I want to change it so that, for example, if $dicenumber were 2, it would produce something like:

            for ($d1=1; $d1 <= $d1value ; $d1++) { 
                for ($d2=1; $d2 <= $d2value ; $d2++) { 
                        array_push(${sum.($d1+$d2)}, "$d1"."$d2");
                }
            }

I want the code to process for whatever number $dicenumber may be, without limits. Looking around, it seems like I have to add some kind of recursive code, but I don't know how to do that. Any tips? Also, any feedback on what I did wrong in general, would be extremely helpful! thanks!

            <?php
            //defines the number and type of dice
            $dicenumber = 3;
            $dtype = 6;
            //defines the maximum value of every die 
            for ($i=1; $i <=$dicenumber ; $i++) { 
                ${d.$i.value} = $dtype;
            }
            //defines and array for each possible sum resulting from the roll of the given number of dice. 
            for ($i=$dicenumber; $i <= ($dtype*$dicenumber) ; $i++) { 
            ${sum.$i} = array();
            }

            //the troublesome piece of code I want to change    

            for ($d1=1; $d1 <= $d1value ; $d1++) { 
                for ($d2=1; $d2 <= $d2value ; $d2++) { 
                for ($d3=1; $d3 <= $d3value ; $d3++) { 
                        array_push(${sum.($d1+$d2+$d3)}, "$d1"."$d2"."$d3");
                    }
                }
            }

            //prints all the possible roll combinations, each line lists combination that share the same sum
            for ($i=$dicenumber; $i <= ($dtype*$dicenumber); $i++) { 
        print join(" ", ${sum.$i})."<br />";
        }
        ?>
Était-ce utile?

La solution

Here we have a two-function process. The first function, buildArrays, creates arrays in the proper format to feed into the second function, allCombinations. So, for this example with 3 d6's in play, buildArrays will produce an array equivalent to this:

$data = array(
    array(1, 2, 3, 4, 5, 6),
    array(1, 2, 3, 4, 5, 6),
    array(1, 2, 3, 4, 5, 6));

I will warn you that as you increase the number of dice and the number of sides, the number of possible combinations increases exponentially! This means that you could place a very large demand on the server, and both timeout and max memory limits will quickly come into play. The arrays generated could be very, very large and quickly consume more than the max memory limit. That said, here we go:

function buildArrays($dicenumber, $dtype){

    for ($i = 0; $i<$dicenumber; $i++){
        $tmp = array();
        for ($j = 1; $j<=$dtype; $j++){
            $tmp[] = $j;
        }
        $data[$i] = $tmp;
    }
    return $data;
}



function allCombinations($data){

    $result = array(array()); //this is crucial, dark magic.

    foreach ($data as $key => $array) {
        $new_result = array();
        foreach ($result as $old_element){
            foreach ($array as $element){
                if ($key == 0){
                    $new_result[] = $element;
                } else {
                    $new_result[] = $old_element.$element;
                }
            }
        $result = $new_result;
        }
    }
    return $result;
}

//set variables
$dicenumber = 3;
$dtype = 6;

//set_time_limit(0); //You may need to uncomment this for large values.

//call functions
$data = buildArrays($dicenumber, $dtype);
$results = allCombinations($data);

//print out the results
foreach ($results as $result){
    echo $result."<br/>";   
}

N.B. This answer is a variant of the cartesian product code

Autres conseils

If you have learned functions, you can do a recursive call and keep track of what dicenumber you're on, then increment it each call to the function (and end the loop once you've hit your #). understanding basic recursion

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top