前言
这是一款运行在window上简单贪吃蛇,需要电脑上gcc编译C语言代码,可以参考win10下安装gcc/g++
代码【下载】
package main
import (
"fmt"
"math/rand"
"os"
"snake/Clib"
"strconv"
"time"
)
// 全局常量
const (
WIDTH = 40 // 地图宽度
HEIGHT = 20 // 地图高度
LENGTH = 2 // 蛇长度
DIRECTION = 'R' // 方向
)
// 全局变量
var (
food Food // 食物
delay time.Duration = time.Second / 2 // 速度
score int = 0 // 分数
)
// 初始化父类坐标
type Position struct {
X int
Y int
}
// 初始化蛇子类
type Snake struct {
len int // 长度
dir int // 方向
pos [WIDTH * HEIGHT]Position // 定义数组,存储每一节蛇的坐标
}
// 初始化食物子类
type Food struct {
Position
}
// 初始化游戏地图
func MapInit() {
fmt.Fprintln(os.Stderr, `
贪吃蛇
#----------------------------------------#
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
#----------------------------------------#
`)
}
// 初始化蛇信息
func (s *Snake) SnakeInit() {
s.len = LENGTH // 蛇长度
s.dir = DIRECTION // 蛇方向
// 蛇位置
s.pos[0].X = WIDTH / 2
s.pos[0].Y = HEIGHT / 2
s.pos[1].X = WIDTH/2 - 1
s.pos[1].Y = HEIGHT / 2
s.snake() // 绘制蛇
s.getInput() // 接受键盘输入
}
// 绘制蛇
func (s *Snake) snake() {
for i := 0; i < s.len; i++ {
var ch byte
// 区分蛇头和身体
if i == 0 {
ch = '@'
} else {
ch = '*'
}
Show(s.pos[i].X, s.pos[i].Y, ch)
}
}
// 接受指定键盘按键输入
func (s *Snake) getInput() {
go func() {
for {
switch Clib.Direction() {
case 80, 68, 100:
if s.dir != 'U' {
s.dir = 'D'
}
case 72, 85, 117:
if s.dir != 'D' {
s.dir = 'U'
}
case 77, 82, 114:
if s.dir != 'L' {
s.dir = 'R'
}
case 75, 76, 108:
if s.dir != 'R' {
s.dir = 'L'
}
case 32:
s.dir = 'P'
}
}
}()
}
// 蛇运动
func (s *Snake) Play() {
// 游戏流程控制
for {
FLAG:
time.Sleep(delay) // 延迟调用
if s.dir == 'P' {
goto FLAG
}
if s.check() == false { // 生命检测
break
}
s.eating() // 享受美食
s.changeSpeed() // 改变速度
s.updatePos() // 更新蛇位置
s.snake() // 绘制蛇的UI
}
}
// 生命检测
func (s *Snake) check() bool {
// 蛇和墙碰撞
if s.pos[0].X <= 2 || s.pos[0].X >= WIDTH+3 || s.pos[0].Y <= 2 || s.pos[0].Y >= HEIGHT+3 {
return false
}
// 蛇头和身体碰撞
for i := 1; i < s.len; i++ {
if s.pos[0].X == s.pos[i].X && s.pos[0].Y == s.pos[i].Y {
return false
}
}
return true
}
// 更新位置
func (s *Snake) updatePos() {
Show(s.pos[s.len-1].X, s.pos[s.len-1].Y, ' ') // 将末尾置空
// 更新蛇身体坐标
for i := s.len - 1; i > 0; i-- {
s.pos[i].X = s.pos[i-1].X
s.pos[i].Y = s.pos[i-1].Y
Show(s.pos[i].X, s.pos[i].Y, '*')
}
// 根据方向改变蛇头位置
switch s.dir {
case 'U':
s.pos[0].Y += -1
case 'D':
s.pos[0].Y += 1
case 'L':
s.pos[0].X += -1
case 'R':
s.pos[0].X += 1
}
Show(s.pos[0].X, s.pos[0].Y, '@') // 绘制蛇头
}
// 享受美食
func (s *Snake) eating() {
if s.pos[0].X == food.X && s.pos[0].Y == food.Y {
s.len++ // 身体增加
s.randomFood() // 创建随机食物
score ++
s.showScore() // 显示等分
}
}
// 根据得分改变速度
func (s *Snake) changeSpeed() {
delay = time.Second / (time.Duration(score/20) + 3)
}
// 随机食物
func (s *Snake) randomFood() {
// 随机食物
for i := 1; i < s.len; i++ {
food.X = RandInt(3, WIDTH+3)
food.Y = RandInt(3, HEIGHT+3)
if food.X == s.pos[i].X && food.Y == s.pos[i].Y {
continue
}
}
Show(food.X, food.Y, '$') // 显示食物
}
// 显示信息
func Show(X int, Y int, ch byte) {
Clib.GotoPosition(X, Y) // 调用C语言代码设置控制光标位置
fmt.Fprintf(os.Stderr, "%c", ch) // 将字符绘制在界面中
}
// 两者之间随机数 左闭右开
func RandInt(min, max int) int {
if min >= max || min == 0 || max == 0 {
return max
}
return rand.Intn(max-min) + min
}
// 显示等分
func (s *Snake) showScore() {
Clib.GotoPosition(2, 24)
fmt.Fprintf(os.Stderr, "%s", "分数:"+strconv.Itoa(score))
}
// 游戏结束
func (s *Snake) gameOver() {
// 擦除食物
Clib.GotoPosition(food.X, food.Y)
fmt.Fprintf(os.Stderr, "%s", " ")
// 显示Game Over
Clib.GotoPosition(18, 10)
fmt.Fprintf(os.Stderr, "%s", "Game Over")
// 显示等分
Clib.GotoPosition(22, 12)
fmt.Fprintf(os.Stderr, "%s", strconv.Itoa(score))
// 暂停关闭
time.Sleep(time.Second * 10)
}
func main() {
rand.Seed(time.Now().UnixNano()) // 创建随机数种子
Clib.HideCursor() // 隐藏控制台光标
MapInit() // 初始化地图
var s Snake // 创建蛇对象
s.SnakeInit() // 初始化蛇信息
s.randomFood() // 随机食物
s.Play() // 开始游戏
s.gameOver() // 游戏结束
}
package Clib
/*
#include<windows.h>
#include<conio.h>
//使用WInAPI来移动控制台光标
void gotoxy(int x,int y){
COORD c;
c.X=x,c.Y=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);
}
//从键盘获取一次按键但不显示在控制台
int direct(){
return _getch();
}
//去控制台光标
void hideCursor(){
CONSOLE_CURSOR_INFO cci;
cci.bVisible=FALSE;
cci.dwSize=sizeof(cci);
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cci);
}
*/
import "C" // go可以嵌入C语言的函数
// 设置控制台光标位置
func GotoPosition(X int, Y int) {
C.gotoxy(C.int(X), C.int(Y))
}
// 无显示键盘输入字符
func Direction() (key int) {
key = int(C.direct())
return
}
// 隐藏鼠标
func HideCursor() {
C.hideCursor()
}
备注:代码学习参考黑马《go语言与区块链精品入门课程视频》视频课程