// Package xiangqi 实现中国象棋的完整规则:走子合法性、将军/将死判定与极大极小搜索 AI package xiangqi // 棋盘约定:10 行 x 9 列,row 0 为黑方底线(上方),row 9 为红方底线(下方) // 棋子编码 int8:正数=红方,负数=黑方,绝对值代表兵种: // 1=帅/将 2=仕/士 3=相/象 4=马 5=车 6=炮 7=兵/卒 const ( King = 1 // 帅/将 Advisor = 2 // 仕/士 Bishop = 3 // 相/象 Knight = 4 // 马 Rook = 5 // 车 Cannon = 6 // 炮 Pawn = 7 // 兵/卒 ) // 红黑双方标识 const ( Red = 1 // 红方(下方,先手) Black = -1 // 黑方(上方) ) // Board 棋盘:[行][列],0 表示空位 type Board [10][9]int8 // pieceNames 棋子中文名:[兵种][0]=红名 [1]=黑名 var pieceNames = map[int][2]string{ King: {"帅", "将"}, Advisor: {"仕", "士"}, Bishop: {"相", "象"}, Knight: {"马", "马"}, Rook: {"车", "车"}, Cannon: {"炮", "炮"}, Pawn: {"兵", "卒"}, } // PieceName 棋子中文名(按红黑区分) func PieceName(p int8) string { if p == 0 { return "" } kind := int(p) idx := 0 if p < 0 { kind = -kind idx = 1 } return pieceNames[kind][idx] } // Initial 初始棋盘布局(红下黑上) func Initial() Board { var b Board // 黑方(上方,负数) back := []int8{Rook, Knight, Bishop, Advisor, King, Advisor, Bishop, Knight, Rook} for c, p := range back { b[0][c] = -p } b[2][1], b[2][7] = -Cannon, -Cannon for c := 0; c < 9; c += 2 { b[3][c] = -Pawn } // 红方(下方,正数) for c, p := range back { b[9][c] = p } b[7][1], b[7][7] = Cannon, Cannon for c := 0; c < 9; c += 2 { b[6][c] = Pawn } return b } // Move 一步着法:从 (FromR,FromC) 到 (ToR,ToC) type Move struct { FromR int `json:"from_r"` // 起点行 FromC int `json:"from_c"` // 起点列 ToR int `json:"to_r"` // 终点行 ToC int `json:"to_c"` // 终点列 } // side 返回棋子所属方(1红 -1黑 0空) func side(p int8) int { if p > 0 { return Red } if p < 0 { return Black } return 0 } // Apply 执行着法并返回被吃的棋子(调用方需自行保证合法性) func (b *Board) Apply(m Move) int8 { captured := b[m.ToR][m.ToC] b[m.ToR][m.ToC] = b[m.FromR][m.FromC] b[m.FromR][m.FromC] = 0 return captured } // Undo 撤销着法(配合 Apply 的返回值恢复现场,搜索用) func (b *Board) Undo(m Move, captured int8) { b[m.FromR][m.FromC] = b[m.ToR][m.ToC] b[m.ToR][m.ToC] = captured } // findKing 找到指定方的帅/将位置 func (b *Board) findKing(s int) (int, int) { for r := 0; r < 10; r++ { for c := 3; c <= 5; c++ { if int(b[r][c])*s > 0 && abs8(b[r][c]) == King { return r, c } } } return -1, -1 } // abs8 int8 绝对值 func abs8(v int8) int8 { if v < 0 { return -v } return v } // inBoard 坐标是否在棋盘内 func inBoard(r, c int) bool { return r >= 0 && r < 10 && c >= 0 && c < 9 } // inPalace 坐标是否在指定方的九宫内 func inPalace(r, c, s int) bool { if c < 3 || c > 5 { return false } if s == Red { return r >= 7 && r <= 9 } return r >= 0 && r <= 2 } // crossedRiver 兵卒是否已过河 func crossedRiver(r, s int) bool { if s == Red { return r <= 4 } return r >= 5 } // MoveDesc 着法的中文描述(如 "红车 (9,0)→(5,0)",用于聊天与记录展示) func (b *Board) MoveDesc(m Move) string { p := b[m.FromR][m.FromC] color := "红" if p < 0 { color = "黑" } return color + PieceName(p) }