相信大家都玩过 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
可启动游戏:
条评论