前面几节已经把象棋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

本文为原创文章,转载请注明出处,欢迎访问作者网站(和而不同)

发表评论

error: Content is protected !!