Powershell D&;D骰子模拟器

Powershell D&;D骰子模拟器,powershell,random,Powershell,Random,我想出了一个滚动策略,你滚动4d6,然后再滚动任何重复的。这导致数字介于10和18之间。这导致14是最常见的,10和18是最不常见的。若要指定,请保留其中一个副本,然后重新滚动其他副本。我在任何掷骰子应用程序/在线上都找不到这种方法。我正在PowerShell中尝试运行: $A = Get-Random -Maximum 6 -Minimum 1 $B = Get-Random -Maximum 6 -Minimum 1 $C = Get-Random -Maximum 6 -Minimum 1

我想出了一个滚动策略,你滚动4d6,然后再滚动任何重复的。这导致数字介于10和18之间。这导致14是最常见的,10和18是最不常见的。若要指定,请保留其中一个副本,然后重新滚动其他副本。我在任何掷骰子应用程序/在线上都找不到这种方法。我正在PowerShell中尝试运行:

$A = Get-Random -Maximum 6 -Minimum 1
$B = Get-Random -Maximum 6 -Minimum 1
$C = Get-Random -Maximum 6 -Minimum 1
$D = Get-Random -Maximum 6 -Minimum 1

While ($A = $B) {
$B = Get-Random -Maximum 6 -Minimum 1
}
... 
...

$Stat = $A+$B+$C+$D

但是$A和$B总是一样的,$C和$D总是一样的。谁能解释一下Get Random是如何工作的,并提出一个解决方案来解释为什么我的循环是无限的?

这里有一个解决方案,用于任意数量的骰子,重新滚动直到唯一并返回一个数组

function RollDice {
    param (
        [ValidateRange(1,[int]::MaxValue)][parameter(Position = 0, Mandatory = $true)][int]$Amount,
        [ValidateRange(1,[int]::MaxValue)][Alias('d')][int]$Sides
    )
    if ($Amount -gt $Sides) {
        throw "Invalid parameter - The number of sides ($Sides) must be greater than the number of dice thrown ($Amount)"
    }

    [System.Collections.Generic.List[int]]$Results = @()

    for ($DiceNum = 1; $DiceNum -le $Amount; $DiceNum++) {
        while (!([int]$Roll) -or $Roll -in $Results) {
            $Roll = Get-Random -Minimum 1 -Maximum ($Sides + 1)  #Maximum pulls a number less than, not equal. See https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-random
        }
        $Results += $Roll
    }
    
    Return $Results
}

RollDice 4 -d 6

如果您将其视为一系列单独的骰子滚动,重复直到您看到4个不同的值(这正是它的含义),您可以将其建模为:

function Roll-4d6 {
    # Use hashtable to keep track of face values
    $uniqueRolls = @{}

    # Keep rolling until we've seen 4 distinct faces
    while($uniqueRolls.Count -lt 4){
        # Roll the dice, make note of unique face value
        $roll = 1..6 |Get-Random
        $uniqueRolls[$roll] = $roll
    }

    # Calculate and return sum
    return $uniqueRolls.Values |Measure-Object -Sum |Select-Object -ExpandProperty Sum
}
执行10K次将揭示在副本上重新滚动4d6的真实分布(与您预期的不完全相同):

一个简单的解释是,只有一种轧辊组合可以生产10(
1,2,3,4
),11(
1,2,3,5
),17(
2,4,5,6
)和18(
3,4,5,6

要通过单个采样模拟相同的分布,您可以执行以下操作:

$roll = 10, 11, 12, 12, 13, 13, 14, 14, 14, 15, 15, 16, 16, 17, 18 |Get-Random

关于
-最大值的注释

请注意,
Get Random
-Maximum
参数是一个排除项,因此对于6面骰子,您需要
Get Random-最小1-最大7
以下是另一种使用列表且不需要重新滚动重复项的方法:

Function Roll {

    # Die face values
    $roll = [System.Collections.Generic.List[int]]@(1..6)
    # Perform the required number of rolls
    $values = 1..4 | Foreach-Object { 
        # Random roll
        $r = Get-Random -InputObject $roll
        # Remove rolled value from list to prevent duplicates
        [void]$roll.Remove($r)
        # return roll
        $r
    }
    # Sum rolls
    ($values | Measure-Object -Sum).Sum
}

# Execute the rolls
Roll

# Output
16

=
用于赋值
-eq
用于相等比较。因此,
10、11、11、12、12、12、13、13、13、13、14、14、14、14、14、15、15、15、16、16、16、17、17、18 | Get Random
对于我想做的事情更为准确,如果不是出于它的精神……不,那是不准确的,我在答案中添加了一个示例,说明如何在一个语句中实现这一点
Function Roll {

    # Die face values
    $roll = [System.Collections.Generic.List[int]]@(1..6)
    # Perform the required number of rolls
    $values = 1..4 | Foreach-Object { 
        # Random roll
        $r = Get-Random -InputObject $roll
        # Remove rolled value from list to prevent duplicates
        [void]$roll.Remove($r)
        # return roll
        $r
    }
    # Sum rolls
    ($values | Measure-Object -Sum).Sum
}

# Execute the rolls
Roll

# Output
16