我正在用Go编写一个简单的程序,作为学习语言的练习。该程序是一个游戏玩家:它exec.Command
是一个基于文本的游戏,然后通过StdinPipe
/StdoutPipe
与它通信。经过一段时间的闲逛和阅读了大量的在线文档,我设法使框架工作起来——相当于Hello World,在那里我建立了双向通信,可以处理程序终止等错误。
现在我正在尝试编写实际的游戏AI代码。由于我的目的是学习这门语言,我试着在风格上非常小心——我不只是想在Go中写C(或其他语言)。
程序中明显的分工(一旦完成所有设置)分为两部分。首先,程序查看当前状态,并决定应该向游戏发出什么命令。其次,程序查看返回的数据并相应地更新状态。(是的,这是一个简单的游戏——它等待输入,然后做出响应,不存在时间问题。)
我不确定这些州信息应该放在哪里。将其全部转储到全局范围感觉是错误的,而制作一个大型的单例对象似乎更糟糕(Go并不是特别OO)。在任何情况下,我都不希望函数传递并返回20多个变量。
一般的建议是可以的,但我最感兴趣的是什么是围棋的惯用语。根据请求,我可以共享代码,但我认为这不会有帮助。
我喜欢为此使用包。
琐碎的例子:
package foo
func Incr() {
f.incr()
}
func Count() int {
return f.count()
}
type foo struct {
sync.RWMutex
count int
}
func (f *foo) incr() {
f.Lock()
f.count++
f.Unlock()
}
func (f *foo) count() int {
f.RLock()
defer f.RUnlock()
return f.count
}
var f = &foo{}
此程序包可以导入到任何其他程序包并保持状态。我添加了同步。RWMutex,以防止任何比赛条件。这使您能够完全控制如何访问foo的状态,并很好地包含该状态。
为游戏状态创建一个结构类型。在程序中传递一个指向该类型值的指针,或者将指针存储在包级别的变量中(如果这类事情不困扰您的话)。根据需要在此类型上实现方法。考虑将它放在自己的包中,以便进行更大的封装。