换位表使用位板上玩家 0 和玩家 1 位置的键,并包括最后的玩家回合,我这样做是为了保证所有状态的唯一键。但这似乎很慢,因为 fmt.Sprintf。
我有两个函数用于存储和检索,在每个函数中我都会构建密钥并进行检查或存储。
类型TTFlag int64
const (
Exact TTFlag = 0
UpperBound TTFlag = 1
LowerBound TTFlag = 2
)
type TTEntry struct {
BestScore float64
BestMove int
Flag TTFlag
Depth int
IsValid bool
}
type Solver struct {
NodeVisitCounter int
TTMapHitCounter int
TTMap map[string]TTEntry
}
func NewSolver() *Solver {
return &Solver{
NodeVisitCounter: 0,
TTMapHitCounter: 0,
TTMap: make(map[string]TTEntry),
}
}
func (s *Solver) StoreEntry(p *Position, entry TTEntry) {
key := fmt.Sprintf("%d:%d:%d", p.Bitboard[0], p.Bitboard[1], p.PlayerTurn)
s.TTMap[key] = entry
}
func (s *Solver) RetrieveEntry(p *Position) TTEntry {
key := fmt.Sprintf("%d:%d:%d", p.Bitboard[0], p.Bitboard[1], p.PlayerTurn)
if entry, exists := s.TTMap[key]; exists {
s.TTMapHitCounter++
return entry
}
return TTEntry{}
}
我可以做些什么来进一步优化这个?如何在不使用 fmt.Sprintf 和字符串连接的情况下制作更好的密钥?
编辑:
Position 结构体用于跟踪游戏状态:
类型位置结构体{ 位板 [2]uint64 玩家回合 int HeightBB [7]int 移动次数 int }
HeightBB 是一个跟踪列高度的数组,因此我们知道将块放在位图中的位置。
如果您注意数据结构的设计,那么我认为没有任何必要
fmt.Sprintf
。
例如,
type TTKey struct {
Bitboard [2]uint64
PlayerTurn int
}
type TTFlag int64
type TTEntry struct {
BestScore float64
BestMove int
Flag TTFlag
Depth int
IsValid bool
}
type Solver struct {
NodeVisitCounter int
TTMapHitCounter int
TTMap map[TTKey]TTEntry
}
type Position struct {
Key TTKey
HeightBB [7]int
NumberOfMoves int
}
func (s *Solver) StoreEntry(p *Position, entry TTEntry) {
s.TTMap[p.Key] = entry
}
func (s *Solver) RetrieveEntry(p *Position) TTEntry {
if entry, exists := s.TTMap[p.Key]; exists {
s.TTMapHitCounter++
return entry
}
return TTEntry{}
}