抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

相信大家都玩过 2048 这个游戏,这次我们将使用 Go 语言及调用相关包来完成一个简易版的 2048 游戏,快来一同尝试下吧!

执行代码

package main

import (
    "fmt"
    "github.com/shiyanlou/termbox-go"
    "math/rand"
    "time"
)

var Score int
var step int

func coverPrintStr(x, y int, str string, fg, bg termbox.Attribute) error {

    xx := x
    for n, c := range str {
        if c == '\n' {
            y++
            xx = x - n - 1
        }
        termbox.SetCell(xx+n, y, c, fg, bg)
    }
    termbox.Flush()
    return nil
}

type Status uint

const (
    Win Status = iota
    Lose
    Add
    Max = 2048
)

type G2048 [4][4]int

func (t *G2048) checkWinOrAdd() Status {
    for _, x := range t {
        for _, y := range x {
            if y >= Max {
                return Win
            }
        }
    }
    i := rand.Intn(len(t))
    j := rand.Intn(len(t))
    for x := 0; x < len(t); x++ {
        for y := 0; y < len(t); y++ {
            if t[i%len(t)][j%len(t)] == 0 {
                t[i%len(t)][j%len(t)] = 2 << (rand.Uint32() % 2)
                return Add
            }
            j++
        }
        i++
    }

    return Lose
}

func (t G2048) initialize(ox, oy int) error {
    fg := termbox.ColorYellow
    bg := termbox.ColorBlack
    termbox.Clear(fg, bg)
    str := "      SCORE: " + fmt.Sprint(Score)
    for n, c := range str {
        termbox.SetCell(ox+n, oy-1, c, fg, bg)
    }
    str = "ESC:exit " + "Enter:replay"
    for n, c := range str {
        termbox.SetCell(ox+n, oy-2, c, fg, bg)
    }
    str = " PLAY with ARROW KEY"
    for n, c := range str {
        termbox.SetCell(ox+n, oy-3, c, fg, bg)
    }
    fg = termbox.ColorBlack
    bg = termbox.ColorGreen
    for i := 0; i <= len(t); i++ {
        for x := 0; x < 5*len(t); x++ {
            termbox.SetCell(ox+x, oy+i*2, '-', fg, bg)
        }
        for x := 0; x <= 2*len(t); x++ {
            if x%2 == 0 {
                termbox.SetCell(ox+i*5, oy+x, '+', fg, bg)
            } else {
                termbox.SetCell(ox+i*5, oy+x, '|', fg, bg)
            }
        }
    }
    fg = termbox.ColorYellow
    bg = termbox.ColorBlack
    for i := range t {
        for j := range t[i] {
            if t[i][j] > 0 {
                str := fmt.Sprint(t[i][j])
                for n, char := range str {
                    termbox.SetCell(ox+j*5+1+n, oy+i*2+1, char, fg, bg)
                }
            }
        }
    }
    return termbox.Flush()
}

func (t *G2048) mirrorV() {
    tn := new(G2048)
    for i, line := range t {
        for j, num := range line {
            tn[len(t)-i-1][j] = num
        }
    }
    *t = *tn
}

func (t *G2048) right90() {
    tn := new(G2048)
    for i, line := range t {
        for j, num := range line {
            tn[j][len(t)-i-1] = num
        }
    }
    *t = *tn
}

func (t *G2048) left90() {
    tn := new(G2048)
    for i, line := range t {
        for j, num := range line {
            tn[len(line)-j-1][i] = num
        }
    }
    *t = *tn
}

func (t *G2048) right180() {
    tn := new(G2048)
    for i, line := range t {
        for j, num := range line {
            tn[len(line)-i-1][len(line)-j-1] = num
        }
    }
    *t = *tn
}

func (t *G2048) mergeUp() bool {
    tl := len(t)
    changed := false
    notfull := false
    for i := 0; i < tl; i++ {

        np := tl
        n := 0

        for x := 0; x < np; x++ {
            if t[x][i] != 0 {
                t[n][i] = t[x][i]
                if n != x {
                    changed = true
                }
                n++
            }
        }
        if n < tl {
            notfull = true
        }
        np = n
        for x := 0; x < np-1; x++ {
            if t[x][i] == t[x+1][i] {
                t[x][i] *= 2
                t[x+1][i] = 0
                Score += t[x][i] * step
                x++
                changed = true
            }
        }
        n = 0
        for x := 0; x < np; x++ {
            if t[x][i] != 0 {
                t[n][i] = t[x][i]
                n++
            }
        }
        for x := n; x < tl; x++ {
            t[x][i] = 0
        }
    }
    return changed || !notfull
}

func (t *G2048) mergeDwon() bool {
    //t.mirrorV()
    t.right180()
    changed := t.mergeUp()
    //t.mirrorV()
    t.right180()
    return changed
}

func (t *G2048) mergeLeft() bool {
    t.right90()
    changed := t.mergeUp()
    t.left90()
    return changed
}

func (t *G2048) mergeRight() bool {
    t.left90()
    changed := t.mergeUp()
    t.right90()
    return changed
}

func (t *G2048) mrgeAndReturnKey() termbox.Key {
    var changed bool
Lable:
    changed = false
    //ev := termbox.PollEvent()
    event_queue := make(chan termbox.Event)
    go func() {
        for {
            event_queue <- termbox.PollEvent()
        }
    }()

    ev := <-event_queue

    switch ev.Type {
    case termbox.EventKey:
        switch ev.Key {
        case termbox.KeyArrowUp:
            changed = t.mergeUp()
        case termbox.KeyArrowDown:
            changed = t.mergeDwon()
        case termbox.KeyArrowLeft:
            changed = t.mergeLeft()
        case termbox.KeyArrowRight:
            changed = t.mergeRight()
        case termbox.KeyEsc, termbox.KeyEnter:
            changed = true
        default:
            changed = false
        }

        if !changed {
            goto Lable
        }

    case termbox.EventResize:
        x, y := termbox.Size()
        t.initialize(x/2-10, y/2-4)
        goto Lable
    case termbox.EventError:
        panic(ev.Err)
    }
    step++
    return ev.Key
}

func (b *G2048) clear() {
    next := new(G2048)
    Score = 0
    step = 0
    *b = *next

}

func (b *G2048) Run() {
    err := termbox.Init()
    if err != nil {
        panic(err)
    }
    defer termbox.Close()

    rand.Seed(time.Now().UnixNano())

A:

    b.clear()
    for {
        st := b.checkWinOrAdd()
        x, y := termbox.Size()
        b.initialize(x/2-10, y/2-4)
        switch st {
        case Win:
            str := "Win!!"
            strl := len(str)
            coverPrintStr(x/2-strl/2, y/2, str, termbox.ColorMagenta, termbox.ColorYellow)
        case Lose:
            str := "Lose!!"
            strl := len(str)
            coverPrintStr(x/2-strl/2, y/2, str, termbox.ColorBlack, termbox.ColorRed)
        case Add:
        default:
            fmt.Print("Err")
        }
        key := b.mrgeAndReturnKey()
        if key == termbox.KeyEsc {
            return
        }
        if key == termbox.KeyEnter {
            goto A
        }
    }
}

func main() {
    var game G2048
    game.Run()
}

注意:创建源文件 2048.go,输入以上内容。

执行效果

运行代码 go run 2048.go 可启动游戏:

评论