Add a general shuffler and deck shuffling.
This commit is contained in:
parent
20561c574c
commit
b8c0e5603a
@ -23,7 +23,7 @@ const (
|
|||||||
// The Deck stores cards yet-to-be-dealt.
|
// The Deck stores cards yet-to-be-dealt.
|
||||||
type Deck[C StatsCollection] struct {
|
type Deck[C StatsCollection] struct {
|
||||||
cards []Card[C]
|
cards []Card[C]
|
||||||
rand rand.Rand
|
rand *rand.Rand
|
||||||
}
|
}
|
||||||
|
|
||||||
// Len returns the number of cards in the Deck.
|
// Len returns the number of cards in the Deck.
|
||||||
@ -196,3 +196,45 @@ func (d *Deck[C]) InsertRandomRange(loFrac, hiFrac float64, card Card[C]) error
|
|||||||
errs.Add(d.Insert(slot, card))
|
errs.Add(d.Insert(slot, card))
|
||||||
return errs.Emit()
|
return errs.Emit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shuffle completely shuffles the deck. If the deck has one or fewer cards,
|
||||||
|
// this returns WarningTooFewCards since nothing can be shuffled.
|
||||||
|
func (d *Deck[C]) Shuffle() error {
|
||||||
|
if len(d.cards) < 2 {
|
||||||
|
return WarningTooFewCards
|
||||||
|
}
|
||||||
|
ShuffleAll(d.cards, d.rand)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShufflePart shuffles the `n` cards of the deck starting at `loc`.
|
||||||
|
// If the provided range doesn't fit in the deck, this returns
|
||||||
|
// WarningTopClamped and/or WarningBottomClamped. If the eventual range
|
||||||
|
// of cards to be shuffled (after any off-the-end issues are corrected)
|
||||||
|
// is one or less, this returns WarningTooFewCards since nothing can
|
||||||
|
// be shuffled.
|
||||||
|
func (d *Deck[C]) ShufflePart(loc, n int) error {
|
||||||
|
if n < 2 {
|
||||||
|
// Nothing to do.
|
||||||
|
return WarningTooFewCards
|
||||||
|
}
|
||||||
|
|
||||||
|
var errs ErrorCollector
|
||||||
|
if loc < 0 {
|
||||||
|
errs.Add(Warningf("%w: loc was %d", WarningTopClamped, loc))
|
||||||
|
loc = 0
|
||||||
|
}
|
||||||
|
if loc+n > d.Len() {
|
||||||
|
errs.Add(Warningf("%w: deck size %d does not have %d cards at and after location %d",
|
||||||
|
WarningBottomClamped, len(d.cards), n, loc))
|
||||||
|
n = d.Len() - loc
|
||||||
|
// Now is there anything to do?
|
||||||
|
if n < 2 {
|
||||||
|
errs.Add(WarningTooFewCards)
|
||||||
|
return errs.Emit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShufflePart(d.cards, d.rand, loc, n)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@ package cardsim
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InsertInto inserts one or more items into a slice at an arbitrary index.
|
// InsertInto inserts one or more items into a slice at an arbitrary index.
|
||||||
@ -98,3 +99,30 @@ func DeleteNFrom[T any](slice []T, loc, n int) []T {
|
|||||||
copy(slice[loc:], slice[loc+n:])
|
copy(slice[loc:], slice[loc+n:])
|
||||||
return slice[:len(slice)-n]
|
return slice[:len(slice)-n]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShuffleAll shuffles everything in slice, using the provided rand.Rand.
|
||||||
|
// If no rand.Rand is provided, this uses the default source.
|
||||||
|
func ShuffleAll[T any](slice []T, r *rand.Rand) {
|
||||||
|
shuffle := rand.Shuffle
|
||||||
|
if r != nil {
|
||||||
|
shuffle = r.Shuffle
|
||||||
|
}
|
||||||
|
shuffle(len(slice), func(i, j int) {
|
||||||
|
slice[i], slice[j] = slice[j], slice[i]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ShufflePart shuffles the `n` elements of `slice` starting at `loc`
|
||||||
|
// in-place, using the provided rand.Rand. If the range of items to
|
||||||
|
// shuffle is not entirely within `slice`, this panics.
|
||||||
|
//
|
||||||
|
// If no rand.Rand is provided, this uses the default source.
|
||||||
|
func ShufflePart[T any](slice []T, r *rand.Rand, loc, n int) {
|
||||||
|
if loc < 0 || loc+n > len(slice) {
|
||||||
|
panic(fmt.Sprintf("can't shuffle %d elements from a %d-element slice at location %d", n, len(slice), loc))
|
||||||
|
}
|
||||||
|
if n < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ShuffleAll(slice[loc:loc+n], r)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user