123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- package cards
- import (
- cryptoRand "crypto/rand"
- "fmt"
- "math/big"
- )
- // новая колода из 36 карт. jokers - количество джокеров в колоде
- func NewDeck36(jokers int) *Deck {
- deck, _ := NewDeckOffset(Number(6), jokers)
- return deck
- }
- // новая колода из 54 карт. jokers - количество джокеров в колоде
- func NewDeck54(jokers int) *Deck {
- deck, _ := NewDeckOffset(Number(2), jokers)
- return deck
- }
- // новая колода. 4 масти, порядок начинается с offset (минимальный)
- func NewDeckOffset(offset Number, jockers int) (*Deck, error) {
- if !offset.IsValid() {
- return nil, fmt.Errorf("invalid offset: %d", offset)
- }
- cards := make([]*Card, 0, 52+jockers)
- for i := Hearts; i <= Spades; i++ {
- for j := Number(2); j <= Ace; j++ {
- cards = append(
- cards,
- &Card{
- N: j,
- S: i,
- },
- )
- }
- }
- for i := 0; i < jockers; i++ {
- cards = append(
- cards,
- &Card{
- N: Joker,
- S: Undefined,
- })
- }
- deck := &Deck{
- countJokers: jockers,
- cards: cards,
- }
- return deck, nil
- }
- // колода
- type Deck struct {
- countJokers int
- cards []*Card
- offsetLeft int
- offsetRight int
- }
- // количество джокеров в колоде
- func (s *Deck) CountJokers() int {
- return s.countJokers
- }
- // собираем колоду в исходное состояние (возвращаем вышедшие карты)
- func (s *Deck) ResetOffset() {
- s.offsetLeft = 0
- s.offsetRight = 0
- }
- // количество карт в колоде
- func (s *Deck) Count() int {
- return len(s.cards)
- }
- // количество карт без джокеров
- func (s *Deck) CountWithoutJokers() int {
- return len(s.cards) - s.countJokers
- }
- // количество оставшихся карт в колоде
- func (s *Deck) CountLeft() int {
- return len(s.cards) - s.offsetLeft - s.offsetRight
- }
- // переместить карту с позиции pos на позицию newPos
- // если pos или newPos выходят за рамки массива колоды, результат будет false
- func (s *Deck) MoveCard(pos, newPos int) bool {
- if (pos < 0 || pos >= len(s.cards)) || (newPos < 0 || newPos >= len(s.cards)) {
- return false
- }
- s.cards[pos], s.cards[newPos] = s.cards[newPos], s.cards[pos]
- return true
- }
- // перемешать колоду (стандартныйметод с использованием криптографически стойкого генератора)
- func (s *Deck) Shuffle() {
- n := len(s.cards)
- for i := range s.cards {
- // генерация случайного индекса с использованием криптографически стойкого генератора
- jBig, _ := cryptoRand.Int(cryptoRand.Reader, big.NewInt(int64(n-i)))
- j := int(jBig.Int64()) + i
- // меняем позицию
- s.cards[i], s.cards[j] = s.cards[j], s.cards[i]
- }
- }
- // взять карту снизу
- func (s *Deck) PopLeft() (*Card, bool) {
- if s.CountLeft() == 0 {
- return nil, false
- }
- card := s.cards[s.offsetLeft]
- s.offsetLeft += 1
- return card, true
- }
- // взять карту сверху
- func (s *Deck) PopRight() (*Card, bool) {
- if s.CountLeft() == 0 {
- return nil, false
- }
- card := s.cards[len(s.cards)-s.offsetRight-1]
- s.offsetRight += 1
- return card, true
- }
- // строка полной колоды (включая вышедшие карты)
- func (s *Deck) StringAll() string {
- return showCardSlice(s.cards)
- }
- // строка только оставшихся карт
- func (s *Deck) StringLeft() (res string) {
- left := s.cards[s.offsetLeft : len(s.cards)-s.offsetRight]
- return showCardSlice(left)
- }
- // строка только вышедших карт
- func (s *Deck) String() string {
- return "[ " + s.StringLeft() + " ]"
- }
|