用Go写一个中国象棋(十四)| 象棋AI进阶
前面几节已经把象棋AI进行了优化,下面我们把优化后的算法运用到象棋程序中。
aiMove
打开game.go,增加重复局面的处理:
//aiMove AI移动
func (g *Game) aiMove(screen *ebiten.Image) {
//AI走一步棋
g.singlePosition.searchMain()
g.singlePosition.makeMove(g.singlePosition.search.mvResult)
//把AI走的棋标记出来
g.mvLast = g.singlePosition.search.mvResult
//检查重复局面
vlRep := g.singlePosition.repStatus(3)
if g.singlePosition.isMate() {
//如果分出胜负,那么播放胜负的声音
g.playAudio(MusicGameWin)
g.showValue = "Your Lose!"
g.bGameOver = true
} else if vlRep > 0 {
vlRep = g.singlePosition.repValue(vlRep)
//vlRep是对玩家来说的分值
if vlRep < -WinValue {
g.playAudio(MusicGameLose)
g.showValue = "Your Lose!"
} else {
if vlRep > WinValue {
g.playAudio(MusicGameWin)
g.showValue = "Your Lose!"
} else {
g.playAudio(MusicGameWin)
g.showValue = "Your Draw!"
}
}
g.bGameOver = true
} else if g.singlePosition.nMoveNum > 100 {
g.playAudio(MusicGameWin)
g.showValue = "Your Draw!"
g.bGameOver = true
} else {
//如果没有分出胜负,那么播放将军、吃子或一般走子的声音
if g.singlePosition.inCheck() {
g.playAudio(MusicJiang)
} else {
if g.singlePosition.captured() {
g.playAudio(MusicEat)
} else {
g.playAudio(MusicPut)
}
}
if g.singlePosition.captured() {
g.singlePosition.setIrrev()
}
}
}
clickSquare
//clickSquare 点击格子处理
func (g *Game) clickSquare(screen *ebiten.Image, sq int) {
pc := 0
if g.bFlipped {
pc = g.singlePosition.ucpcSquares[squareFlip(sq)]
} else {
pc = g.singlePosition.ucpcSquares[sq]
}
if (pc & sideTag(g.singlePosition.sdPlayer)) != 0 {
//如果点击自己的棋子,那么直接选中
g.sqSelected = sq
g.playAudio(MusicSelect)
} else if g.sqSelected != 0 && !g.bGameOver {
//如果点击的不是自己的棋子,但有棋子选中了(一定是自己的棋子),那么走这个棋子
mv := move(g.sqSelected, sq)
if g.singlePosition.legalMove(mv) {
if g.singlePosition.makeMove(mv) {
g.mvLast = mv
g.sqSelected = 0
// 检查重复局面
vlRep := g.singlePosition.repStatus(3)
if g.singlePosition.isMate() {
// 如果分出胜负,那么播放胜负的声音,并且弹出不带声音的提示框
g.playAudio(MusicGameWin)
g.showValue = "Your Win!"
g.bGameOver = true
} else if vlRep > 0 {
vlRep = g.singlePosition.repValue(vlRep)
if vlRep > WinValue {
g.playAudio(MusicGameLose)
g.showValue = "Your Lose!"
} else {
if vlRep < -WinValue {
g.playAudio(MusicGameWin)
g.showValue = "Your Win!"
} else {
g.playAudio(MusicGameWin)
g.showValue = "Your Draw!"
}
}
g.bGameOver = true
} else if g.singlePosition.nMoveNum > 100 {
g.playAudio(MusicGameWin)
g.showValue = "Your Draw!"
g.bGameOver = true
} else {
if g.singlePosition.checked() {
g.playAudio(MusicJiang)
} else {
if g.singlePosition.captured() {
g.playAudio(MusicEat)
g.singlePosition.setIrrev()
} else {
g.playAudio(MusicPut)
}
}
g.aiMove(screen)
}
} else {
g.playAudio(MusicJiang) // 播放被将军的声音
}
}
//如果根本就不符合走法(例如马不走日字),那么不做任何处理
}
}
Update
//Update 更新状态,1秒60帧
func (g *Game) Update(screen *ebiten.Image) error {
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
if g.bGameOver {
g.bGameOver = false
g.showValue = ""
g.sqSelected = 0
g.mvLast = 0
g.singlePosition.startup()
} else {
x, y := ebiten.CursorPosition()
x = Left + (x-BoardEdge)/SquareSize
y = Top + (y-BoardEdge)/SquareSize
g.clickSquare(screen, squareXY(x, y))
}
}
g.drawBoard(screen)
if g.bGameOver {
g.messageBox(screen)
}
return nil
}
运行程序,再与AI对弈的时候,会发现AI已经变聪明了许多,也不会出现长将的局面。
如果小伙伴们想学习更多这方面的知识,可以访问http://www.xqbase.com/computer/stepbystep4.htm
在下一节中,我们将学习如何使用转换表?
0