ZBLOG

用golang写一个贪吃蛇小游戏

当然,下面是一个简单的贪吃蛇小游戏的示例代码(使用Go语言编写):

package main

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

const (
	width  = 20
	height = 15
)

type point struct {
	x, y int
}

type snake struct {
	body       []point
	direction  point
	grow       bool
	gameOver   bool
	score      int
	speedLevel time.Duration // 控制速度的级别,数值越小速度越快
}

var (
	snakeGame    snake // 游戏实例
	fruit        point // 水果位置
	inputKeyChan chan termbox.KeyEvent // 输入通道用于接收键盘事件输入
)

func main() {
	err := termbox.Init()
	if err != nil {
		fmt.Println("无法初始化 termbox:", err)
		return
	}
	defer termbox.Close()

	eventQueue := make(chan termbox.Event)
	go func() {
		for {
			eventQueue <- termbox.PollEvent()
		}
	}()

	initGame()
	render()

loop:
	for {
		select {
		case ev := <-eventQueue:
			switch ev.Type {
			case termbox.EventKey:
				switch ev.Key {
				case termbox.KeyArrowUp:
					snakeGame.direction = point{0, -1}
				case termbox.KeyArrowDown:
					snakeGame.direction = point{0, 1}
				case termbox.KeyArrowLeft:
					snakeGame.direction = point{-1, 0}
				case termbox.KeyArrowRight:
					snakeGame.direction = point{1, 0}
				case termbox.KeyEsc:
					break loop
				}
			case termbox.EventError:
				panic(ev.Err)
			}
		default:
			move()
			render()
			time.Sleep(snakeGame.speedLevel * time.Millisecond)
		}
	}

	fmt.Println("游戏结束!得分:", snakeGame.score)
}

// 初始化游戏
func initGame() {
	rand.Seed(time.Now().UnixNano())

	snakeGame = snake{
		body:       []point{{5, 5}},
		direction:  point{1, 0},
		grow:       false,
		gameOver:   false,
		score:      0,
		speedLevel: 200,
	}

	fruit = generateFruit()

	inputKeyChan = make(chan termbox.KeyEvent)
	go func() {
		for {
			event := <-inputKeyChan
			if event.Key == termbox.KeyEsc {
				os.Exit(0)
			}
		}
	}()
}

// 移动蛇
func move() {
	if snakeGame.gameOver {
        return
    }
    
	head := snakeGame.body[0]
	newHead := point{head.x + snakeGame.direction.x, head.y + snakeGame.direction.y}

	if !isValidPosition(newHead) || isColliding(newHead) {
        snakeGame.gameOver = true
        return
    }

	snakeGame.body = append([]point{newHead}, snakeGame.body...)
	if !snakeGame.grow { // 不需要增长,移除最后一个尾巴元素
        snakeGame.body = snakeGame.body[:len(snakeGame.body)-1]
    } else {
        fruit = generateFruit() // 吃到水果后生成新的水果位置
    }

	snakeGame.grow = false

	checkEatFruit(newHead)
}

// 渲染游戏界面
func render() {
	termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)

	for _, p := range snakeGame.body {
		drawCell(p.x, p.y, termbox.ColorGreen)
	}

	drawCell(fruit.x, fruit.y, termbox.ColorRed)

	termbox.Flush()
}

// 在指定位置绘制单元格
func drawCell(x, y int, color termbox.Attribute) {
	termbox.SetCell(x*2, y, ' ', termbox.ColorDefault, color)
	termbox.SetCell(x*2+1, y, ' ', termbox.ColorDefault, color)
}

// 检查是否吃到水果
func checkEatFruit(head point) {
	if head == fruit {
        snakeGame.score++
        snakeGame.grow = true
        
        if snakeGame.score % 5 == 0 { // 每吃到五个水果,速度提高一级别
            snakeGame.speedLevel -= 10
            if snakeGame.speedLevel < 50 { // 速度上限为50ms
                snakeGame.speedLevel = 50
            }
        }
    }
}

// 随机生成水果位置
func generateFruit() point {
	var p point

	for {
		p = point{rand.Intn(width), rand.Intn(height)}

		if !isColliding(p) {
			break
		}
	}

	return p
}

// 判断位置是否合法(在边界内)
func isValidPosition(p point) bool {
	return p.x >= 0 && p.x < width && p.y >= 0 && p.y < height
}

// 判断是否与蛇身碰撞
func isColliding(p point) bool {
	for _, b := range snakeGame.body {
		if b == p {
			return true
		}
	}

	return false
}

这只是一个简单的贪吃蛇小游戏示例,可能还有一些功能和优化可以增加进去。你可以根据自己的需求进行修改和扩展。希望对你有帮助!


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=8507

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?