Last week I showed you my PowerShell Bingo game. While the game itself might be a fun way to pass the time, the real goal was to teach you some PowerShell techniques and concepts without you realizing it. This week, I thought I’d keep with the gaming theme and take up chance. Specifically let’s roll some dice and flip some coins. These aren’t especially complicated tasks in PowerShell, and it is hard to say what problem they might solve, but let’s have some fun anyway.

First up, flipping coins.

Flipping a coin is essentially a True/False game. Or another way to look at is Even/Odd. My favorite way is to use the modulo operator.

1 2 3 4 |
PS C:\> 5%2 1 PS C:\> 6%2 0 |

Those values can be represented as Booleans.

1 2 3 4 |
PS C:\> 5%2 -as [boolean] True PS C:\> 6%2 -as [boolean] False |

So all I need is a random number and perform a modulo operation. Here’s the function I created.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
Function Invoke-CoinToss { [cmdletbinding(DefaultParameterSetName="_AllParameterSets")] Param( [Parameter(ParameterSetName="Boolean")] [switch]$AsBoolean, [Parameter(ParameterSetName="EvenOdd")] [switch]$EvenOdd ) Write-Verbose "Using parameter set $($PSCmdlet.ParameterSetName)" #get a random number between 1 and 100 to test $i = Get-Random -Minimum 1 -Maximum 100 Write-Verbose "Random result = $i" #use the modulo operator if ($i%2) { Write-Verbose "Odd/Heads/True" Switch ($PSCmdlet.ParameterSetName) { "Boolean" { $True} "EvenOdd" {"Odd" } Default {"Heads"} } #switch } #if else { Write-Verbose "Even/Tails/False" Switch ($PSCmdlet.ParameterSetName) { "Boolean" { $False} "EvenOdd" {"Even" } Default {"Tails"} } #switch } #else } #end Invoke-CoinToss |

I used a valid verb but will also define a more user-friendly alias.

1 |
Set-Alias -Name Flip-Coin -Value Invoke-CoinToss |

Because you may want several different types of output, not necessarily the best idea for a function but this might be an exception. And remember this is supposed to be educational not necessarily practical. My function uses parameter sets and depending on the set, decides what type of result to write to the pipeline.

And it seems to work pretty well.

Next, let’s roll some dice. Again I’ll use Get-Random . A single dice roll is as simple as this:

1 |
get-random -Minimum 1 -Maximum 7 |

To roll multiple dice, you could do this:

1 2 3 4 |
$Dice = 4 1..$Dice | foreach { Get-Random -Minimum 1 -Maximum 7 } |

Naturally I wrote a function with a few more bells and whistles because I like shiny toys.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
Function Invoke-Dice { [cmdletbinding()] Param( [ValidateRange(1,10)] [int]$Dice = 2, [ValidateRange(6,12)] [int]$Sides = 6, [Alias("Total")] [switch]$Sum ) Write-Verbose "Rolling $dice $sides-sided dice" #generate a list of all possible numbers then select all random numbers at once $result = (1..$Sides)*$Dice | Get-Random -Count $Dice if ($sum) { write-Verbose "Totaling the result" Write-Verbose $($result -join ",") ($result | Measure-Object -sum).Sum } else { $result } } #end roll-dice Set-Alias -name Roll-Dice -value Invoke-Dice |

This function lets you choose the number of dice to roll. Notice I use a ValidateRange attribute to limit the number of dice. And in case you are rolling for a game of Dungeons and Dragons which has some extra-sided dice, I gave you that option as well.

In some games, you need the total so I added that as well. One thing that I changed was my rolling technique. In this version I am pre-generating an array of all possible values and then get the specified number of random values.

1 |
$result = (1..$Sides)*$Dice | Get-Random -Count $Dice |

Not that it is super critical, but this technique is faster.

1 2 3 4 5 6 7 8 9 10 11 |
$dice = 8 $sides = 7 Measure-Command { 1..$Dice | foreach { Get-Random -Minimum 1 -Maximum ($sides+1) } } Measure-Command { (1..$Sides)*$Dice | Get-Random -Count $Dice } |

Here’s the result

If you are debating between different techniques in a script or function, use Measure-Command to see how they perform.

Now you have some tools to build your own PowerShell games and maybe learn something new in the process. If you do, I hope you’ll share. Enjoy!