2008 Winter Scripting Games Event 10
If you aren't already in the know, these ten problems are from the 2008 Winter Scripting games.
For each problem, I'm going to quickly sum up the interesting (interesting TO ME) bits of each problem, then I'm going to post the full source.
Event 10: Blackjack!
Here we are asked to simulate a text-based Blackjack game. Mine works, I'm certainly not proud of the graphics, not proud of the colors, not even necessarily proud of the structure of my solution.
Please do not look at any of the following code and think "that's how I'm supposed to use objects in PowerShell!" Please don't. It's NOT ideal, I made several design mistakes; I don't even think most of my objects are necessary. Or, thinking from the other side--maybe I didn't go far enough.
Source
#PROBLEM #10
$cardValues = @{
"Ace" = 11;
"King" = 10;
"Queen" = 10;
"Jack" = 10;
"Ten" = 10;
"Nine" = 9;
"Eight" = 8;
"Seven" = 7;
"Six" = 6;
"Five" = 5;
"Four" = 4;
"Three" = 3;
"Two" = 2;
}
$suits = @("Spades", "Hearts", "Diamonds", "Clubs")
#bad random number generator
$rnd = new-object Random
function Create-DeckObject
{
$o = new-object PSObject
$cards = @()
foreach ($suit in $suits)
{
foreach ($cardValue in $cardValues.Keys)
{
$cards += Create-CardObject -value $cardValue -suit $suit
}
}
$sortedDeck = $cards | sort PositionInDeck
Add-Member -inputObject $o -memberType NoteProperty -name "Cards" -value $sortedDeck
Add-Member -inputObject $o -memberType ScriptProperty -name "Deal" -value { $nextCard = $this.Cards | select -first 1; $this.Cards = $this.Cards | select -last ($this.Cards.Count - 1); $nextCard }
$o
}
function Create-CardObject ($value, $suit)
{
$o = new-object PSObject
Add-Member -inputObject $o -memberType NoteProperty -name "Card" -value ("$value of $suit")
Add-Member -inputObject $o -memberType NoteProperty -name "BlackjackValue" -value $cardValues[$value]
Add-Member -inputObject $o -memberType NoteProperty -name "PositionInDeck" -value $rnd.NextDouble()
$o
}
function Create-HandObject ([switch]$isdealer)
{
$o = new-object PSObject
$emptyHand = @()
Add-Member -inputObject $o -memberType NoteProperty -name "Cards" -value $emptyHand
Add-Member -inputObject $o -memberType NoteProperty -name "IsDealerHand" -value $isdealer
#this value will change for the dealer hand as the game progresses.
Add-Member -inputObject $o -memberType NoteProperty -name "AreAllCardsRevealed" -value (-not $isdealer)
Add-Member -inputObject $o -memberType ScriptProperty -name "BlackjackValue" -value { $total = 0; $this.Cards | % {$total += $_.BlackjackValue}; $total }
$o
}
function Print-VisibleCards ($cards,$allcardsvisible,[switch]$isdealer)
{
$output = @()
if ($allcardsvisible -eq $TRUE)
{
foreach ($card in $cards)
{
$output += $card.Card
}
#POSTSCRIPT-OOPS! Looks like I'm calculating the "total value of hand", when
#I expose that value as a script property! This function would have been
#IDEAL as a ScriptMethod attached to the Hand object.
$total = 0; $cards | % { $total += $_.BlackjackValue }
if (-not $isdealer)
{
$output += "You have $($total).`n"
}
else
{
$output += "Dealer has $($total).`n"
}
}
else
{
#if the dealer's hand is invisible, we don't know their total, so
#don't display it; also we can only see the second card.
$output += $cards[1].Card
}
$output | out-string
}
function Show-Status ($my, $dealer)
{
Write-Host "Your cards:"
Write-Host (Print-VisibleCards -cards $my.Cards -allcardsvisible $TRUE) -foregroundColor Green
Write-Host "Dealer's cards:"
Write-Host (Print-VisibleCards -cards $dealer.Cards -isdealer -allcardsvisible $dealer.AreAllCardsRevealed ) -foregroundColor Red
}
function Show-Action ($text)
{
Write-Host $text -foregroundColor Yellow
Start-Sleep -seconds 1
}
function Solve-Problem10
{
$deck = Create-DeckObject
$myHand = Create-HandObject
$dealerHand = Create-HandObject -isdealer
Show-Action "Dealing starting hands..."
$myHand.Cards += $deck.Deal
$dealerHand.Cards += $deck.Deal
$myHand.Cards += $deck.Deal
$dealerHand.Cards += $deck.Deal
#show starting hands
Show-Status -my $myHand -dealer $dealerHand
#give the player the option to hit
while ($myHand.BlackjackValue -lt 21)
{
Write-Host -noNewLine "Stay (s) or Hit (h) ? "
if ((Read-Host) -match "h")
{
Show-Action "You have chosen to Hit."
$myHand.Cards += $deck.Deal
Show-Status -my $myHand -dealer $dealerHand
}
else
{
Show-Action "You have chosen to Stay."
break
}
}
#did we bust? If so, quit.
if ($myHand.BlackjackValue -gt 21)
{
Show-Action "YOU LOSE! You busted!"
return
}
#dealer reveals their cards
$dealerHand.AreAllCardsRevealed = $TRUE
Show-Action "Dealer has revealed their cards."
Show-Status -my $myHand -dealer $dealerHand
#extra delay so that we can process what is in the dealer's hand.
Start-Sleep -seconds 3
#give the dealer the option to hit
while ($dealerHand.BlackjackValue -lt $myHand.BlackjackValue)
{
Show-Action "Dealer takes a card."
$dealerHand.Cards += $deck.Deal
Show-Status -my $myHand -dealer $dealerHand
}
#did dealer bust? If so, VICTORY!
if ($dealerHand.BlackjackValue -gt 21)
{
Show-Action "YOU WIN! VICTORY! Dealer busts!"
}
else
{
Show-Action "YOU LOSE! Dealer has $($dealerHand.BlackjackValue), you have $($myHand.BlackjackValue)."
}
}
Solve-Problem10
$cardValues = @{
"Ace" = 11;
"King" = 10;
"Queen" = 10;
"Jack" = 10;
"Ten" = 10;
"Nine" = 9;
"Eight" = 8;
"Seven" = 7;
"Six" = 6;
"Five" = 5;
"Four" = 4;
"Three" = 3;
"Two" = 2;
}
$suits = @("Spades", "Hearts", "Diamonds", "Clubs")
#bad random number generator
$rnd = new-object Random
function Create-DeckObject
{
$o = new-object PSObject
$cards = @()
foreach ($suit in $suits)
{
foreach ($cardValue in $cardValues.Keys)
{
$cards += Create-CardObject -value $cardValue -suit $suit
}
}
$sortedDeck = $cards | sort PositionInDeck
Add-Member -inputObject $o -memberType NoteProperty -name "Cards" -value $sortedDeck
Add-Member -inputObject $o -memberType ScriptProperty -name "Deal" -value { $nextCard = $this.Cards | select -first 1; $this.Cards = $this.Cards | select -last ($this.Cards.Count - 1); $nextCard }
$o
}
function Create-CardObject ($value, $suit)
{
$o = new-object PSObject
Add-Member -inputObject $o -memberType NoteProperty -name "Card" -value ("$value of $suit")
Add-Member -inputObject $o -memberType NoteProperty -name "BlackjackValue" -value $cardValues[$value]
Add-Member -inputObject $o -memberType NoteProperty -name "PositionInDeck" -value $rnd.NextDouble()
$o
}
function Create-HandObject ([switch]$isdealer)
{
$o = new-object PSObject
$emptyHand = @()
Add-Member -inputObject $o -memberType NoteProperty -name "Cards" -value $emptyHand
Add-Member -inputObject $o -memberType NoteProperty -name "IsDealerHand" -value $isdealer
#this value will change for the dealer hand as the game progresses.
Add-Member -inputObject $o -memberType NoteProperty -name "AreAllCardsRevealed" -value (-not $isdealer)
Add-Member -inputObject $o -memberType ScriptProperty -name "BlackjackValue" -value { $total = 0; $this.Cards | % {$total += $_.BlackjackValue}; $total }
$o
}
function Print-VisibleCards ($cards,$allcardsvisible,[switch]$isdealer)
{
$output = @()
if ($allcardsvisible -eq $TRUE)
{
foreach ($card in $cards)
{
$output += $card.Card
}
#POSTSCRIPT-OOPS! Looks like I'm calculating the "total value of hand", when
#I expose that value as a script property! This function would have been
#IDEAL as a ScriptMethod attached to the Hand object.
$total = 0; $cards | % { $total += $_.BlackjackValue }
if (-not $isdealer)
{
$output += "You have $($total).`n"
}
else
{
$output += "Dealer has $($total).`n"
}
}
else
{
#if the dealer's hand is invisible, we don't know their total, so
#don't display it; also we can only see the second card.
$output += $cards[1].Card
}
$output | out-string
}
function Show-Status ($my, $dealer)
{
Write-Host "Your cards:"
Write-Host (Print-VisibleCards -cards $my.Cards -allcardsvisible $TRUE) -foregroundColor Green
Write-Host "Dealer's cards:"
Write-Host (Print-VisibleCards -cards $dealer.Cards -isdealer -allcardsvisible $dealer.AreAllCardsRevealed ) -foregroundColor Red
}
function Show-Action ($text)
{
Write-Host $text -foregroundColor Yellow
Start-Sleep -seconds 1
}
function Solve-Problem10
{
$deck = Create-DeckObject
$myHand = Create-HandObject
$dealerHand = Create-HandObject -isdealer
Show-Action "Dealing starting hands..."
$myHand.Cards += $deck.Deal
$dealerHand.Cards += $deck.Deal
$myHand.Cards += $deck.Deal
$dealerHand.Cards += $deck.Deal
#show starting hands
Show-Status -my $myHand -dealer $dealerHand
#give the player the option to hit
while ($myHand.BlackjackValue -lt 21)
{
Write-Host -noNewLine "Stay (s) or Hit (h) ? "
if ((Read-Host) -match "h")
{
Show-Action "You have chosen to Hit."
$myHand.Cards += $deck.Deal
Show-Status -my $myHand -dealer $dealerHand
}
else
{
Show-Action "You have chosen to Stay."
break
}
}
#did we bust? If so, quit.
if ($myHand.BlackjackValue -gt 21)
{
Show-Action "YOU LOSE! You busted!"
return
}
#dealer reveals their cards
$dealerHand.AreAllCardsRevealed = $TRUE
Show-Action "Dealer has revealed their cards."
Show-Status -my $myHand -dealer $dealerHand
#extra delay so that we can process what is in the dealer's hand.
Start-Sleep -seconds 3
#give the dealer the option to hit
while ($dealerHand.BlackjackValue -lt $myHand.BlackjackValue)
{
Show-Action "Dealer takes a card."
$dealerHand.Cards += $deck.Deal
Show-Status -my $myHand -dealer $dealerHand
}
#did dealer bust? If so, VICTORY!
if ($dealerHand.BlackjackValue -gt 21)
{
Show-Action "YOU WIN! VICTORY! Dealer busts!"
}
else
{
Show-Action "YOU LOSE! Dealer has $($dealerHand.BlackjackValue), you have $($myHand.BlackjackValue)."
}
}
Solve-Problem10
2008 Winter Scripting Game Events: Index
- Introduction: TOTAL DOMINATION!
- Event 1: Could I Get Your Phone Number?
- Event 2: Skating on Thin Ice
- Event 3: Instant (Runoff) Winner
- Event 4: Image is Everything
- Event 5: You Call That a Password?
- Event 6: Prime Time
- Event 7: Play Ball!
- Event 8: Making Beautiful Music
- Event 9: You're Twisting My Words
- Event 10: Blackjack!
- Recap