Go + C 一款簡單的貪喫蛇

前言

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章