go_games_collection/deck.go
2026-07-04 13:51:04 +03:00

65 lines
1.9 KiB
Go

package main
import (
"crypto/rand"
"math/big"
)
// Deck — стопка карт. Индекс 0 — верх колоды (карта, которая уходит первой).
type Deck struct {
cards []Card
}
// NewDeck создаёт полную неперетасованную колоду из 52 карт.
func NewDeck() *Deck {
d := &Deck{cards: make([]Card, 0, 52)}
for s := Clubs; s <= Spades; s++ {
for r := Ace; r <= King; r++ {
d.cards = append(d.cards, Card{Suit: s, Rank: r})
}
}
return d
}
// Shuffle перемешивает колоду криптографически стойким рандомом
// (алгоритм Фишера-Йейтса).
func (d *Deck) Shuffle() {
for i := len(d.cards) - 1; i > 0; i-- {
jBig, err := rand.Int(rand.Reader, big.NewInt(int64(i+1)))
if err != nil {
// crypto/rand не должен падать в обычных условиях;
// если это случилось — не имеет смысла продолжать игру.
panic(err)
}
j := int(jBig.Int64())
d.cards[i], d.cards[j] = d.cards[j], d.cards[i]
}
}
// Len возвращает количество карт, оставшихся в колоде.
func (d *Deck) Len() int {
return len(d.cards)
}
// Draw снимает верхнюю карту колоды. Второе значение — false,
// если колода пуста.
func (d *Deck) Draw() (Card, bool) {
if len(d.cards) == 0 {
return Card{}, false
}
c := d.cards[0]
d.cards = d.cards[1:]
return c, true
}
// DrawN снимает n верхних карт (используется при раздаче).
// Если в колоде меньше карт, чем запрошено, возвращает столько,
// сколько есть.
func (d *Deck) DrawN(n int) []Card {
if n > len(d.cards) {
n = len(d.cards)
}
out := d.cards[:n]
d.cards = d.cards[n:]
return out
}