Я хочу смоделировать бросок двух шестигранных кубиков X количество раз, используя PHP, чтобы увидеть, как часто происходит каждая возможная комбинация (2, 3, 4, 5, 6, 7, 8, 9, 10, 11 или 12). Что было бы хорошей отправной точкой?
Вот полный PHP-скрипт, который будет симулировать бросок двух кубиков столько раз, сколько вы захотите, а затем отобразить промежуточные итоги результатов каждого броска:
<?php
/**
* If your machine is low on memory, try uncommenting the following line:
*/
//ini_set('memory_limit', '512M');
/**
* If you still don't have enough memory, reduce the value of $number_of_rolls
* Note: with memory_limit at 512M, the max number of times I can roll at a time
* is about 325000
*/
$number_of_rolls = 20000;
print dice_roll_output($number_of_rolls);
/**
* Array of 6 sides in a single die
*/
function die_render() {
$die = array(1 => 1, 2, 3, 4, 5, 6);
return $die;
}
/**
* Roll a single die
*/
function die_roll($die_sides) {
// First function (less random)
//$number_rolled = array_rand($die_sides);
// Second function (more random)
$number_rolled = mt_rand(1, count($die_sides));
return $number_rolled;
}
/**
* Roll both dice
*/
function dice_roll() {
// Create the first die
$die1 = die_render();
// Create the second die
$die2 = die_render();
// Roll the first die
$die_roll_1 = die_roll($die1);
// Roll the second die
$die_roll_2 = die_roll($die2);
// Add the two rolls up to get the total
$total = $die_roll_1 + $die_roll_2;
// Return the first die, second die, and the total of the two
return array($die_roll_1, $die_roll_2, $total);
}
/**
* Much of this function is not necessary unless the
* area toward the bottom is un-commented out.
*/
function dice_roll_output($numrolls) {
$numrolls = (int) $numrolls;
// Abort if $numrolls is less than 1
if ($numrolls < 1) {
return 'Number of rolls must be greater than zero';
}
$rolled_arr = array();
$die1 = array();
$die2 = array();
$dice_sum = array();
for ($i = 0; $i < $numrolls; $i++) {
$dice_roll[$i] = dice_roll();
$die1[$i] = $dice_roll[$i][0];
$die2[$i] = $dice_roll[$i][1];
$dice_sum[$i] = $dice_roll[$i][2];
$rolled_arr[$i] = array($die1[$i], $die2[$i], $dice_sum[$i]);
}
// How many times each total (somewhere between 2 and 12) was rolled
$frequencies = array_count_values($dice_sum);
// Sort the displayed output from high to low
arsort($frequencies);
// For later use with calculating percentages
$rolled_tot = array_sum($frequencies);
// Begin actual display -- line 1
$out = "<pre><b>Rolled\t\tFrequency\tPercent</b>\n";
// Double-checking to make sure all percentages add up to 100%
$freqency_total = 0;
foreach ($frequencies as $dice_roll => $frequency) {
// Don't round the numbers using number_format until after they've been used
// for double-checking
$percent_raw = ($frequency / $rolled_tot) * 100;
// Add to the running total of the double-checked percentage
$freqency_total += $percent_raw;
// Now we can round the numbers up to two decimal places
$percent_display = number_format($percent_raw, 2);
// More display -- should be 11 lines maximum (lines 2 through 12)
$out .= "{$dice_roll}\t\t{$frequency}\t\t{$percent_display}\n";
}
// Format the running total of the double-checked percentage (optional)
$freqency_total = number_format($freqency_total, 2);
// Aesthetic purposes only
$out .= "\t\t\t\t-----\n";
// Line 13 of the display
$out .= "\t\t\t\t{$freqency_total}%\n";
// The following is the above-referenced "area toward the bottom"// NB: displaying this part could cause a LOT of output to be displayed
/*
if (!empty($rolled_arr)) {
// Uncomment the next line if you want to sort the output
//array_multisort($dice_sum, SORT_DESC, $rolled_arr);
// Aesthetic purposes only
$out .= "---------------------------------------\n";
// Line 14 of the display
$out .= "<b>Die #1\t\tDie #2\t\tTotal</b>\n";
foreach ($rolled_arr as $key => $arr) {
// Lines 15 and up of the display -- quantity determined by $numrolls
$out .= "{$arr[0]}\t\t{$arr[1]}\t\t{$arr[2]}\n";
}
}
*/
// End actual display
$out .= "</pre>";
return $out;
}
Вот короткий сценарий с простыми комментариями о том, что делает что.
<?php
// this will be our final result
$combinations = array();
// for as many times as we want to run the experiment (1000 here)
for ($i = 0; $i < 1000; $i++) {
// mt_rand returns random whole number in the specified range
$die1roll = mt_rand(1, 6);
$die2roll = mt_rand(1, 6);
// add the sum of two dice
$sum = $die1roll + $die2roll;
// if this sum hasn't happened yet, mark it so - it's happened zero times
if (!isset($combinations[$sum])) $combinations[$sum] = 0;
// increase number of times this sum has happened
$combinations[$sum] += 1;
}
// order the results array by keys (sums) ascending
ksort($combinations);
// print it out
print_r($combinations);