分享一个golang数据结构相关的文字迷宫小游戏

文字游戏效果图

分享一个golang数据结构相关的文字迷宫小游戏_第1张图片

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

type choices struct {
     
	cmd         string
	description string
	nextNode    *storyNode
	nextChoice  *choices
}

type storyNode struct {
     
	text    string
	choices *choices
}

func (node *storyNode) addChoice(cmd string, description string, nextNode *storyNode) {
     
	choice := &choices{
     cmd, description, nextNode, nil}
	if node.choices == nil {
     
		node.choices = choice
	} else {
     
		currentChoice := node.choices

		for currentChoice.nextChoice != nil {
     
			currentChoice = currentChoice.nextChoice
		}
		currentChoice.nextChoice = choice
	}
}

func (node *storyNode) render() {
     
	fmt.Println(node.text)

	currentChoice := node.choices

	for currentChoice != nil {
     
		fmt.Println(currentChoice.cmd, ":", currentChoice.description)
		currentChoice = currentChoice.nextChoice
	}
}

func (node *storyNode) executeCmd(cmd string) *storyNode {
     
	currentChoice := node.choices

	for currentChoice != nil {
     
		if strings.ToLower(currentChoice.cmd) == strings.ToLower(cmd) {
     
			return currentChoice.nextNode
		}

		currentChoice = currentChoice.nextChoice
	}
	fmt.Println("Sorry I didn't understand that.")

	return node
}

var scanner *bufio.Scanner

func (node *storyNode) play() {
     
	node.render()

	if node.choices != nil {
     
		scanner.Scan()
		node.executeCmd(scanner.Text()).play()
	}
}
func main() {
     
	scanner = bufio.NewScanner(os.Stdin)

	start := storyNode{
     text: `You are in large chamber,deep underground.You see three passages leading out.A north passage 
	into darkness.To the south,a passage appears to head upward.The easter appears flat and well traveled.`}
	darkRoom := storyNode{
     text: `It is pitch black.You cannot see a thing.`}
	darkRoomLit := storyNode{
     text: `The dark passage is now lit by your lantern. You can continue north or head back south.`}
	grue := storyNode{
     text: `while stumbling around in the darkness, you are eaten by a grue`}
	trap := storyNode{
     text: `You head down the well traveled path when suddenly a trap door opens and yo u fall into a pit`}
	treasure := storyNode{
     text: `You arrive at a small chamber,filled with treasure!`}

	start.addChoice("N", "go north", &darkRoom)
	start.addChoice("S", "go south", &darkRoom)
	start.addChoice("E", "go east", &trap)

	darkRoom.addChoice("S", "Try to go back south", &grue)
	darkRoom.addChoice("O", "Turn on lantern", &darkRoomLit)

	darkRoomLit.addChoice("N","Go North",&treasure)
	darkRoomLit.addChoice("S","Go South",&start)

	start.play()

	fmt.Println()
	fmt.Println("The End.")
}

storyNode是一堆离散的故事节点,choice是一组行为链表,
每一个离散的故事节点会在尾部衔接一堆choice行为,每个choice又会通过输入连接到不同的故事节点。很适合理解go关于图的数据结构。

视频原连接 go游戏编程系列 油管上找到的。

https://www.youtube.com/watch?v=u87bfwSGtrg&list=PLDZujg-VgQlZUy1iCqBbe5faZLMkA3g2x&index=6


画了上面这张图来解释一下,这是一个关于图的文字游戏,方块是故事节点,圈是行为链表。然后他们的关系就是图中画的那样,理解代码最重要,我写的英文和字以及图很丑不重要,学习到东西才是重点。

下面贴出数组实现的代码,很简单就是把行为链表换成数组就行了。

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

type choices struct {
     
	cmd         string
	description string
	nextNode    *storyNode
}

type storyNode struct {
     
	text    string
	choices []*choices
}

func (node *storyNode) addChoice(cmd string, description string, nextNode *storyNode) {
     
	choice:=&choices{
     cmd,description,nextNode}
	node.choices=append(node.choices,choice)
}

func (node *storyNode) render() {
     
	fmt.Println(node.text)

	if node.choices!=nil{
     
		for _,choice:=range  node.choices{
     
			fmt.Println(choice.cmd,choice.description)
		}
	}
}

func (node *storyNode) executeCmd(cmd string) *storyNode {
     
	for _,choice:=range node.choices{
     
		if strings.ToLower(choice.cmd)==strings.ToLower(cmd){
     
			return choice.nextNode
		}
	}

	fmt.Println("sorry ,i didn't understand that.")

	return node
}

var scanner *bufio.Scanner

func (node *storyNode) play() {
     
	node.render()

	if node.choices != nil {
     
		scanner.Scan()
		node.executeCmd(scanner.Text()).play()
	}
}
func main() {
     
	scanner = bufio.NewScanner(os.Stdin)

	start := storyNode{
     text: `You are in large chamber,deep underground.You see three passages leading out.A north passage 
	into darkness.To the south,a passage appears to head upward.The easter appears flat and well traveled.`}
	darkRoom := storyNode{
     text: `It is pitch black.You cannot see a thing.`}
	darkRoomLit := storyNode{
     text: `The dark passage is now lit by your lantern. You can continue north or head back south.`}
	grue := storyNode{
     text: `while stumbling around in the darkness, you are eaten by a grue`}
	trap := storyNode{
     text: `You head down the well traveled path when suddenly a trap door opens and yo u fall into a pit`}
	treasure := storyNode{
     text: `You arrive at a small chamber,filled with treasure!`}

	start.addChoice("N", "go north", &darkRoom)
	start.addChoice("S", "go south", &darkRoom)
	start.addChoice("E", "go east", &trap)

	darkRoom.addChoice("S", "Try to go back south", &grue)
	darkRoom.addChoice("O", "Turn on lantern", &darkRoomLit)

	darkRoomLit.addChoice("N", "Go North", &treasure)
	darkRoomLit.addChoice("S", "Go South", &start)

	start.play()

	fmt.Println()
	fmt.Println("The End.")
}

下图是优化后的版本

方块依旧是故事节点,数组是行为列表,当输入遍历的角色来到没有行为列表的故事节点后游戏终止。

其实如果有精力的话,下面是油管博主的额外建议可拓展
//homework
//add npc non player characters talk to them,fight
//npc move around the graph
//items can picked up or placed down
//accept natural language as input

//verb noun
//north south east west

//build you own with this
//big state machine

可以添加故事节点支持玩家对话,npc对话,以及npc移动,包括可以打怪。
也可以做自然语言输入来进行交互,当然如果有足够精力的话可以搞一些当输入对话中含有某些动词,名词时候触发新的行为,故事,boss等。

加油学习,GO万岁

你可能感兴趣的:(学习随笔)