Poker Straight Flush Probability Simulation in Go
package main
import (
"fmt"
"math/rand"
"sort"
"time"
)
type Suit int
type Pip int
const (
club Suit = iota
diamond
heart
spade
)
type Card struct {
s Suit
pip Pip
}
func shuffle(d *[]Card) {
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(*d), func(i, j int) {
(*d)[i], (*d)[j] = (*d)[j], (*d)[i]
})
}
func isStraightFlush(h []Card) bool {
var ccount, dcount, hcount, scount int
var sameSuitCards []Card
for _, v := range h {
switch v.s {
case club:
ccount++
case diamond:
dcount++
case heart:
hcount++
case spade:
scount++
}
}
// Step 1 : Check if all cards are of the same suit
if ccount >= 5 || dcount >= 5 || hcount >= 5 || scount >= 5 {
// Collect all cards of the same suit
for _, v := range h {
if (ccount >= 5 && v.s == club) ||
(dcount >= 5 && v.s == diamond) ||
(hcount >= 5 && v.s == heart) ||
(scount >= 5 && v.s == spade) {
sameSuitCards = append(sameSuitCards, v)
}
}
// Step 2 : Sort the cards by pip value
sort.Slice(sameSuitCards, func(i, j int) bool {
return sameSuitCards[i].pip < sameSuitCards[j].pip
})
// Step 3 : Check if all cards are in sequence
consecutive := 1
for i := 1; i < len(sameSuitCards); i++ {
if sameSuitCards[i].pip == sameSuitCards[i-1].pip+1 {
consecutive++
if consecutive == 5 {
return true
}
} else if sameSuitCards[i].pip == sameSuitCards[i-1].pip {
consecutive = 1
}
}
}
return false
}
func main() {
deck := make([]Card, 52)
var sfcount int // number of straight flushes
var totcnt int // Number of trials
fmt.Print("Enter the number of trials: ")
_, err := fmt.Scanln(&totcnt)
if err != nil {
fmt.Println("Invalid input. Please enter a valid number.")
return
}
// Initialize the deck
for i := 0; i < 13; i++ {
deck[i] = Card{club, Pip(i + 1)}
deck[i+13] = Card{diamond, Pip(i + 1)}
deck[i+26] = Card{heart, Pip(i + 1)}
deck[i+39] = Card{spade, Pip(i + 1)}
}
// Run the trials
for i := 0; i < totcnt; i++ {
shuffle(&deck)
hand := deck[:7]
if isStraightFlush(hand) {
sfcount++
}
}
fmt.Printf("\nStraight flushes for %d trials: %d \n", totcnt, sfcount)
fmt.Printf("Probability of straight flush: %.8f\n", float64(sfcount)/float64(totcnt))
}
Key Concepts in Go
This example introduces:
-
Enumerated Types with
iota
:- Go uses the
iota
keyword to simplify the declaration of constants. It automatically increments for each line in theconst
block.
const ( club Suit = iota diamond heart spade )
- Here,
club
is assigned0
,diamond
is1
,heart
is2
, andspade
is3
.
- Go uses the
-
The
for _,
Loop:- Go uses the
for
loop for all iterations, replacingwhile
anddo-while
loops in C. - The
_
is a placeholder when you don’t need the index from the loop.
for _, v := range h { switch v.s { case club: ccount++ case diamond: dcount++ case heart: hcount++ case spade: scount++ } }
- Here, the loop iterates through the
h
slice, andv
holds each element of the slice.
- Go uses the
-
Slices and Sorting:
- Slices in Go allow dynamic resizing. The
sort.Slice
function sorts slices based on a custom comparison.
sort.Slice(sameSuitCards, func(i, j int) bool { return sameSuitCards[i].pip < sameSuitCards[j].pip })
- Slices in Go allow dynamic resizing. The
-
Randomization:
- The
rand.Shuffle
function shuffles the deck using a time-based seed for randomness.
- The
-
Probability Estimation:
- The program calculates the probability of a straight flush by dividing the number of straight flushes by the total number of trials.
Overview of the Program
This program simulates the probability of getting a straight flush in a 7-card hand from a shuffled deck. It involves:
- User Input:
- The user provides the number of trials to simulate.
- Deck Initialization:
- A standard 52-card deck is created, with each card represented by a
Suit
and aPip
(rank).
- A standard 52-card deck is created, with each card represented by a
- Shuffling and Hand Selection:
- The deck is shuffled, and the top 7 cards form the hand.
- Straight Flush Detection:
- The hand is analyzed to check if it contains a straight flush.
- Probability Calculation:
- The program calculates the percentage of hands containing a straight flush after all trials.
Real-World Applications
- Game Theory and Probability:
- This program demonstrates the mathematical principles behind poker probabilities.
- Monte Carlo Simulations:
- Randomized simulations like this are used in fields ranging from finance to physics to model complex systems.
- Card Game Algorithms:
- Understanding the odds of different hands helps in designing and balancing card games.
Code Explanation
The code can be broken down into key sections:
-
Deck Initialization:
for i := 0; i < 13; i++ { deck[i] = Card{club, Pip(i + 1)} deck[i+13] = Card{diamond, Pip(i + 1)} deck[i+26] = Card{heart, Pip(i + 1)} deck[i+39] = Card{spade, Pip(i + 1)} }
- Creates a 52-card deck with 13 ranks (
1-13
) for each suit.
- Creates a 52-card deck with 13 ranks (
-
Shuffling:
func shuffle(d *[]Card) { rand.Seed(time.Now().UnixNano()) rand.Shuffle(len(*d), func(i, j int) { (*d)[i], (*d)[j] = (*d)[j], (*d)[i] }) }
- Shuffles the deck in place using the
rand.Shuffle
function.
- Shuffles the deck in place using the
-
Straight Flush Detection:
- The
isStraightFlush
function checks if the hand contains a straight flush:- Counts cards of each suit.
- Collects cards of the same suit.
- Sorts the cards by rank (
pip
). - Checks if the sorted cards form a sequence of 5 consecutive ranks:
consecutive := 1 for i := 1; i < len(sameSuitCards); i++ { if sameSuitCards[i].pip == sameSuitCards[i-1].pip+1 { consecutive++ if consecutive == 5 { return true } } else if sameSuitCards[i].pip == sameSuitCards[i-1].pip { consecutive = 1 } }
- The
-
Main Function:
- Runs the simulation:
for i := 0; i < totcnt; i++ { shuffle(&deck) hand := deck[:7] if isStraightFlush(hand) { sfcount++ } }
- Calculates and prints the probability:
fmt.Printf("Probability of straight flush: %.8f\n", float64(sfcount)/float64(totcnt))
- Runs the simulation:
How to Run
- Enter the number of trials when prompted:
Enter the number of trials: 10000
- Example output:
Straight flushes for 10000 trials: 12 Probability of straight flush: 0.00120000
Extensions
- Additional Hands:
- Extend the program to detect and calculate probabilities for other poker hands (e.g., four of a kind, full house).
- Parallelization:
- Use goroutines to run multiple trials in parallel for faster simulations.
- Graphical Analysis:
- Visualize the probabilities of different hands using a library like
gonum/plot
.
- Visualize the probabilities of different hands using a library like
- Card Representation:
- Add a string representation for cards to display the hands more clearly.