text/scanner的应用

炸金花:
扫描输入的字符串, 如
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)
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值