前言
這是一款運行在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語言與區塊鏈精品入門課程視頻》視頻課程