炸金花:
扫描输入的字符串, 如
3AK Q1J 2103
三个玩家,每个人三张牌(或者N张牌). 如果不是三张牌, 则价值为无效;
10点在字符串中的表示就是“10”。
能用text/scanner完成吗?
答案是不行. 比如在扫描3AK的时候就会扫描成 3/AK
所以有必要手写一个scanner作为单手牌的扫描。
package main
import (
"fmt"
"io"
"math/rand"
"sort"
"strconv"
"strings"
// "text/scanner"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
func genC() string {
a := rand.Int()%13 + 2
switch a {
case 11:
return "J"
case 12:
return "Q"
case 13:
return "K"
case 14:
return "A"
default:
return fmt.Sprintf("%d", a)
}
}
func genPack() string {
var rv string
for i := 0; i < 3; i++ {
rv += genC()
}
return rv
}
func genRandPacks() string {
//n := rand.Intn(6) + 3
const n = 200
var rv string
for i := 0; i < n; i++ {
rv += fmt.Sprintf("%v ", genPack())
}
return rv
}
type Token struct {
point int
name string
}
func newToken(a string) Token {
var p int
switch a {
case "K":
p = 13
case "Q":
p = 12
case "J":
p = 11
case "A":
p = 14
default:
i, e := strconv.Atoi(a)
if e != nil {
panic(e)
}
p = i
}
return Token{
point: p,
name: a,
}
}
func (t Token) String() string {
return fmt.Sprintf("<%s>(%d)", t.name, t.point)
}
type Pack []Token
func (a Pack) Len() int {
return len(a)
}
func (a Pack) Less(i, j int) bool {
return a[i].point < a[j].point
}
func (a Pack) Swap(i, j int) {
t := a[i]
a[i] = a[j]
a[j] = t
}
func (a Pack) String() string {
var rv string
for _, v := range a {
rv += v.name
}
return rv
}
// pack stored in ascending order.
func (a Pack) Evaluate() (major, minor int) {
if len(a) != 3 {
major, minor = -1, -1
return
}
switch {
case a[0].point == a[1].point && a[1].point == a[2].point:
major = 100
minor = a[2].point
case 1+a[0].point == a[1].point && 1+a[1].point == a[2].point:
major = 90
minor = a[2].point
case a[2].point == a[1].point:
major = 80
minor = a[2].point
case a[0].point == a[1].point:
major = 80
minor = a[1].point
default:
major = 0
minor = a[2].point
}
return
}
func LessThan(lhs Pack, rhs Pack) bool {
lmajor, lminor := lhs.Evaluate()
rmajor, rminor := rhs.Evaluate()
if lmajor != rmajor {
return lmajor < rmajor
}
return lminor < rminor
}
type Scanner struct {
raw string
idx int
head rune
cash string
}
func newScanner(input string) *Scanner {
rv := &Scanner{
raw: input,
idx: 0,
head: -1,
}
if len(input) > 0 {
rv.head = rune(input[0])
}
return rv
}
func isNonTerminal(r rune) bool {
return '1' == r // for 10
}
// if there is a new token waiting for you.
func (s *Scanner) next() bool {
s.cash = ""
if s.head < 0 {
return false
}
var ns string
for s.head >= 0 && isNonTerminal(s.head) {
ns += string(s.head)
s.idx++
if s.idx < len(s.raw) {
s.head = rune(s.raw[s.idx])
} else {
s.head = -1
}
}
if s.head >= 0 {
ns += string(s.head)
s.idx++
if s.idx < len(s.raw) {
s.head = rune(s.raw[s.idx])
} else {
s.head = -1
}
}
s.cash = ns
return true
}
func (s *Scanner) Now() string {
return s.cash
}
func (s *Scanner) Next() (token Token, err error) {
if s.next() {
token = newToken(s.Now())
} else {
err = io.EOF
}
return
}
type Packs []Pack
func (p Packs) Len() int {
return len(p)
}
func (p Packs) Less(i, j int) bool {
return LessThan(p[i], p[j])
}
func (p Packs) Swap(i, j int) {
t := p[i]
p[i] = p[j]
p[j] = t
}
func main() {
var vs []string
//sr := new(scanner.Scanner).Init(strings.NewReader(" K102 A210 1023 "))
rawInput := genRandPacks()
// rawInput := "Q9K"
fmt.Printf("raw: %v\n", rawInput)
// sr := new(scanner.Scanner).Init(strings.NewReader(rawInput))
// for tok := sr.Scan(); tok != scanner.EOF; tok = sr.Scan() {
// vs = append(vs, sr.TokenText())
// }
vss := strings.Split(rawInput, " ")
for _, v := range vss {
if v != "" {
vs = append(vs, v)
}
}
//fmt.Printf("site A: %v\n", strings.Join(vs, ","))
var packs []Pack
for _, s := range vs {
var tks Pack
sToken := newScanner(s)
tk, over := sToken.Next()
for over != io.EOF {
tks = append(tks, tk)
tk, over = sToken.Next()
}
sort.Sort(tks)
packs = append(packs, tks)
}
fmt.Printf("playesr in %v\n", len(packs))
// for _, p := range packs {
// fmt.Printf("%v\n", p)
// }
// for i := 0; i < len(packs)-1; i++ {
// for j := i + 1; j < len(packs); j++ {
// fmt.Printf("%v smaller than %v ? %v\n", packs[i].String(), packs[j].String(),
// LessThan(packs[i], packs[j]),
// )
// }
// }
// fmt.Printf("*******************\n\n")
sort.Sort(Packs(packs))
for i, p := range packs {
fmt.Printf("[%d] %v\n", i, p)
}
}