main函数
package main
import (
"fmt"
"math/rand"
"os"
"os/exec"
"time"
)
//1.1 设置常量来保存地图的大小
const (
MaxRow = 7
MaxCol = 12
)
//2.1 创建一个结构体保存食物的位置
type Position struct {
x int // 表示第几行
y int // 表示第几列
}
//2.2 创建一个结构体保存蛇的位置
type Snake struct {
pos []Position // 用于保存蛇的所有位置 用切片保存
length int // 用于保存蛇的长度
// 6.1.2 蛇的运动方向结合移动函数move获得
direction string
}
// 2.5 创建一个结构体保存食物的位置
type Food struct {
Position
}
//5.1 定义结构体保存偏移位置
type Offset struct {
offX int
offY int
}
func main() {
//1. 设置贪吃蛇地图
snakeMap := [MaxRow][MaxCol]byte{
{'#','#','#','#','#','#','#','#','#','#','#','#'},
{'#',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','#'},
{'#',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','#'},
{'#',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','#'},
{'#',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','#'},
{'#',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','#'},
{'#','#','#','#','#','#','#','#','#','#','#','#'},
}//map end
// 2 创建蛇和食物的位置
snake := Snake{} // 创建一个蛇
snake.length = 2
snake.pos = make([]Position,2) // 初始化Snake里的代表位置的切片
snake.pos[0].x = MaxCol / 2 // 设置蛇头的列的位置
snake.pos[0].y = MaxRow / 2 // 设置蛇头的行位置
// 2.3 设置蛇身体的位置
snake.pos[1].x = MaxCol / 2 - 1
snake.pos[1].y = MaxRow / 2
// 2.4 将蛇放进地图里
snakeMap[snake.pos[0].y][snake.pos[0].x] = '@'
snakeMap[snake.pos[1].y][snake.pos[1].x] = '*'
//2.5 创建食物
fd := Food{}
//2.6 设置随机值让食物的位置随机改变
rand.Seed(time.Now().UnixNano()) // 随机种子
fd.x = rand.Intn(MaxCol-2)+1
fd.y = rand.Intn(MaxRow-2)+1
//2.7 将食物放入地图中
snakeMap[fd.y][fd.x] = 'O'
// 3 . 打印地图
printMap(snakeMap)
for{
//4 接受用户的输入
ch := getCommand()
//5 让蛇移动
move(&snakeMap,snake,ch)
//6 游戏规则判断(是否碰到墙壁,是否碰到自己身体,吃到食物)
res := control(&snakeMap,&snake,&fd)
//重新打印地图
printMap(snakeMap)
// 判断是否触碰到墙壁结束游戏
if res {
break
}
}
fmt.Println("Game Over")
}
//6.1 游戏判断的函数
func control(m *[MaxRow][MaxCol]byte,sk *Snake,fd *Food)bool{
//6.2.1获取蛇头的位置
headPos := sk.pos[0]
if headPos.x<=0 || headPos.x>=MaxCol-1 || headPos.y<=0 || headPos.y>=MaxRow-1 {
return true
}
//6.2.2 判断是否吃到食物
if headPos.x == fd.x && headPos.y== fd.y {
//6.2.3创建新蛇身 并获得最后一节蛇身的位置
lastPos := sk.pos[sk.length-1]
newPos := Position{}
// 6.2.4根据方向判断增加舍身的方向
switch sk.direction {
case "w":
newPos.x = lastPos.x // 往上走 列不变
newPos.y = lastPos.y+1 // 行+1
case "s":
newPos.x = lastPos.x // 往下走 列不变
newPos.y = lastPos.y-1 // 行-1
case "a":
newPos.x = lastPos.x+1 // 列+1
newPos.y = lastPos.y // 往左走 行不变
case "d":
newPos.x = lastPos.x-1 // 列-1
newPos.y = lastPos.y // 往右走 行不变
}
//6.2.5将新创建的身体加入到切片中
sk.pos = append(sk.pos,newPos)
// 让蛇身体+1
sk.length +=1
// 将新的蛇身添加到地图中
m[newPos.y][newPos.y] = '*'
// 重新设定食物
fd.x = rand.Intn(MaxCol-2)+1
fd.y = rand.Intn(MaxRow-2)+1
//重新绘画食物
m[fd.y][fd.x] = 'O'
return false
}
//6.3 判断是否碰到身体
for i:=1;i<sk.length;i++{
if sk.pos[0].x == sk.pos[i].x && sk.pos[0].y == sk.pos[i].y { // 判断蛇头任意等于蛇身的任意点
return true
}
}
return false
}
/**
5.1 蛇移动的函数
*/
func move(sm *[MaxRow][MaxCol]byte,sk Snake,ch string){
// 创建偏移位
offset := Offset{0,0}
// 根据方向判断偏移
switch ch {
case "w","W":
offset.offX = 0
offset.offY = -1
sk.direction = "w"
case "s","S":
offset.offX = 0
offset.offY = 1
sk.direction = "s"
case "a","A":
offset.offX = -1
offset.offY = 0
sk.direction = "a"
case "d","D":
offset.offX = 1
offset.offY = 0
sk.direction = "d"
}
//5.2 去除最后的蛇尾
lastPos := sk.pos[sk.length-1]
sm[lastPos.y][lastPos.x] = ' '
//5.3修改蛇身在地图中的位置
/**
循环会从蛇头往后变成蛇身*[length-1] == pos[蛇头下标]
*/
for i:=sk.length-1;i>0;i--{
sk.pos[i] = sk.pos[i-1]
sm[sk.pos[i].y][sk.pos[i].x] = '*'
}
//5.4 修改蛇头在地图中的位置
sk.pos[0].x += offset.offX
sk.pos[0].y += offset.offY
sm[sk.pos[0].y][sk.pos[0].x] = '@'
}
//4.1 接受用户的函数
func getCommand()(com string){
fmt.Println("请输入w/a/s/d 来控制蛇的方向")
fmt.Scanln(&com)
return
}
/**
3.1打印地图的函数
利用for index,value := range 循环
*/
func printMap(m [MaxRow][MaxCol]byte){
//清空控制台
cmd := exec.Command("cmd","/c","cls")
cmd.Stdout = os.Stdout
cmd.Run()
for _,value1 := range m{
for _,value2 := range value1{
fmt.Printf("%c",value2)
}
fmt.Println()
}
}
网友评论