init
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Suit خال کارت.
|
||||
type Suit uint8
|
||||
|
||||
const (
|
||||
Spades Suit = iota
|
||||
Hearts
|
||||
Diamonds
|
||||
Clubs
|
||||
)
|
||||
|
||||
var suitChar = [4]byte{'S', 'H', 'D', 'C'}
|
||||
var suitName = [4]string{"spades", "hearts", "diamonds", "clubs"}
|
||||
|
||||
func (s Suit) String() string { return suitName[s] }
|
||||
|
||||
// ParseSuit نام انگلیسی خال را به Suit تبدیل میکند.
|
||||
func ParseSuit(name string) (Suit, error) {
|
||||
switch strings.ToLower(name) {
|
||||
case "spades", "s":
|
||||
return Spades, nil
|
||||
case "hearts", "h":
|
||||
return Hearts, nil
|
||||
case "diamonds", "d":
|
||||
return Diamonds, nil
|
||||
case "clubs", "c":
|
||||
return Clubs, nil
|
||||
}
|
||||
return 0, fmt.Errorf("invalid suit: %q", name)
|
||||
}
|
||||
|
||||
// Rank ارزش کارت؛ 2..10 معمولی، 11=J 12=Q 13=K 14=A.
|
||||
type Rank uint8
|
||||
|
||||
const (
|
||||
Jack Rank = 11
|
||||
Queen Rank = 12
|
||||
King Rank = 13
|
||||
Ace Rank = 14
|
||||
)
|
||||
|
||||
// Card یک کارت بازی.
|
||||
type Card struct {
|
||||
Suit Suit
|
||||
Rank Rank
|
||||
}
|
||||
|
||||
// String کد کوتاه کارت مثل "AS", "10H", "2C".
|
||||
func (c Card) String() string {
|
||||
var r string
|
||||
switch c.Rank {
|
||||
case Ace:
|
||||
r = "A"
|
||||
case King:
|
||||
r = "K"
|
||||
case Queen:
|
||||
r = "Q"
|
||||
case Jack:
|
||||
r = "J"
|
||||
default:
|
||||
r = fmt.Sprintf("%d", c.Rank)
|
||||
}
|
||||
return r + string(suitChar[c.Suit])
|
||||
}
|
||||
|
||||
// ParseCard کد کوتاه کارت را پارس میکند (مثلاً "10H", "AS").
|
||||
func ParseCard(code string) (Card, error) {
|
||||
code = strings.ToUpper(strings.TrimSpace(code))
|
||||
if len(code) < 2 {
|
||||
return Card{}, fmt.Errorf("invalid card: %q", code)
|
||||
}
|
||||
rankStr := code[:len(code)-1]
|
||||
suitStr := code[len(code)-1:]
|
||||
|
||||
s, err := ParseSuit(suitStr)
|
||||
if err != nil {
|
||||
return Card{}, fmt.Errorf("invalid card %q: %w", code, err)
|
||||
}
|
||||
|
||||
var r Rank
|
||||
switch rankStr {
|
||||
case "A":
|
||||
r = Ace
|
||||
case "K":
|
||||
r = King
|
||||
case "Q":
|
||||
r = Queen
|
||||
case "J":
|
||||
r = Jack
|
||||
default:
|
||||
var n int
|
||||
if _, err := fmt.Sscanf(rankStr, "%d", &n); err != nil || n < 2 || n > 10 {
|
||||
return Card{}, fmt.Errorf("invalid rank in card %q", code)
|
||||
}
|
||||
r = Rank(n)
|
||||
}
|
||||
return Card{Suit: s, Rank: r}, nil
|
||||
}
|
||||
|
||||
// NewDeck یک دسته ۵۲ کارتی مرتب میسازد.
|
||||
func NewDeck() []Card {
|
||||
deck := make([]Card, 0, 52)
|
||||
for s := Suit(0); s < 4; s++ {
|
||||
for r := Rank(2); r <= Ace; r++ {
|
||||
deck = append(deck, Card{Suit: s, Rank: r})
|
||||
}
|
||||
}
|
||||
return deck
|
||||
}
|
||||
|
||||
// Shuffle دسته را با crypto/rand بهصورت Fisher-Yates بُر میزند.
|
||||
func Shuffle(deck []Card) {
|
||||
for i := len(deck) - 1; i > 0; i-- {
|
||||
jBig, err := rand.Int(rand.Reader, big.NewInt(int64(i+1)))
|
||||
if err != nil {
|
||||
continue // عملاً رخ نمیدهد
|
||||
}
|
||||
j := int(jBig.Int64())
|
||||
deck[i], deck[j] = deck[j], deck[i]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user