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() + " ]" }