English | 中文
本项目是一个基于 JavaScript 实现的中国象棋游戏,包含与AI对战的功能。支持音效、背景音乐、难度调整和悔棋操作。
index.html: 游戏的主页面,包含棋盘、控制按钮和模态框。style.css: 游戏界面的样式,包含棋盘、棋子和UI组件的样式。main.js: 项目的入口JavaScript文件,负责导入其他脚本和样式。xiangqi_script.js: 游戏的核心逻辑,包括棋盘管理、棋子移动规则、胜负判断、用户交互和背景音乐控制等。ai-worker.js: AI的逻辑实现,运行在 Web Worker 中,使用极小极大算法 (Minimax) 结合 Alpha-Beta 剪枝来决定AI的移动。audio/: 包含游戏音效和背景音乐的目录。click.wav: 棋子移动时的点击音效。1.mp3,2.mp3,3.mp3,4.mp3: 背景音乐文件,游戏中会随机播放。
public/: 公共资源目录。favicon.ico: 网站图标。
package.json,package-lock.json: Node.js 项目依赖管理文件。tailwind-input.css: Tailwind CSS 的输入文件。tailwind.config.js,postcss.config.js: Tailwind CSS 和 PostCSS 配置文件。vite.config.js: Vite 开发工具配置文件。copy-audio.js: 在构建过程中复制音频文件的脚本。.cursor/rules/: Cursor IDE的规则文件,帮助AI理解项目结构。
- 支持难度选择: 提供简单、中等和困难三个难度级别,对应AI搜索深度为2、3和4。
- 悔棋功能: 支持撤销最近的一步棋,方便调整策略。
- 背景音乐: 内置4首背景音乐,支持随机播放,可随时切换播放/暂停。
- 音效反馈: 棋子移动时有音效反馈,增强游戏体验。
- 认输选项: 当局面不利时可以选择认输。
- 历史记录: 记录每一步移动,支持悔棋操作。
- 高级AI算法: 使用极小极大算法与Alpha-Beta剪枝,并结合局面评估函数实现智能对弈。
- 自动新局: 一方获胜后,系统会自动开始新的一局,胜方先行,同时保留累计得分。
- 积分系统: 记录红黑双方的得分,可以通过"重新开始"按钮清零。
-
开始游戏:
- 游戏启动时,会显示难度选择对话框。
- 选择适合的难度(易、中、难)后点击"开始游戏"。
- 背景音乐会自动开始随机播放。
-
进行对局:
- 红方由玩家控制,黑方由AI控制。
- 点击棋子可以看到有效移动位置(绿色标记)。
- 当一方获胜后,会自动开始新的一局,胜方先行。
-
游戏控制:
- 重新开始: 完全重置游戏,显示难度选择对话框,清零积分。
- 认输: 当前局认输,黑方得1分,自动开始新局。
- 悔棋: 撤销最近一步(人机各一步),返回之前的局面。
- 音乐控制: 暂停/播放背景音乐。
- 功能: 项目的主入口。
- 主要职责:
- 导入
style.css应用样式。 - 导入
xiangqi_script.js以启动游戏逻辑。
- 导入
该文件包含了中国象棋游戏的主要逻辑。
ROWS,COLS: 定义棋盘的行数 (10) 和列数 (9)。boardElement,resetButton,resignButton,undoButton,redScoreElement,blackScoreElement: HTML中的关键DOM元素。difficultyModal,startGameButton,modalDifficultyRadios: 难度选择相关元素。popupMessageElement: 消息显示元素。initialBoardSetup: 定义棋盘的初始布局。pieceChineseNames: 棋子ID到中文名称的映射。pieceValues: 定义不同类型棋子的基础价值,用于AI评估。boardState: 二维数组,表示当前棋盘上各个位置的棋子状态。currentPlayer: 字符串 ('R' 或 'B'),表示当前轮到哪一方行动(红方或黑方)。selectedPiece: 对象,存储当前选中的棋子信息(棋子ID、行、列)。gameOver: 布尔值,标记游戏是否结束。moveHistory: 数组,记录每一步棋,支持悔棋功能。currentAIDepth: 数值,定义AI搜索深度,默认为2(简单难度)。bgMusicElements,currentMusicIndex,isMusicPlaying,userPausedMusic: 背景音乐相关变量。
-
initializeBoardAndGame(resetScores = false)- 功能: 初始化或重置游戏棋盘和状态。
- 参数:
resetScores(布尔型, 可选, 默认false): 是否重置双方得分。
- 用法: 在游戏开始或点击"重新开始"时调用。
-
showTemporaryMessage(message, duration = 3000, isError = false)- 功能: 在楚河汉界中显示临时消息。
- 参数:
message(字符串): 要显示的消息。duration(数字, 可选, 默认 3000): 消息显示的持续时间(毫秒)。isError(布尔型, 可选, 默认false): 是否为错误消息。
-
createPieceElement(pieceId, row, col)- 功能: 在棋盘上创建并显示一个棋子的DOM元素。
- 参数:
pieceId(字符串): 棋子的唯一标识符 (如 'RK', 'BH1')。row(数字): 棋子所在的行。col(数字): 棋子所在的列。
-
drawPalaceLines()- 功能: 在棋盘上绘制红黑双方九宫格的斜线。
-
onSquareClick(row, col)- 功能: 处理用户点击棋盘格子的事件。根据当前游戏状态决定是选中棋子、移动棋子还是取消选择。
- 参数:
row(数字):被点击格子的行号。col(数字): 被点击格子的列号。
-
selectPiece(row, col, pieceId)- 功能: 选中位于
(row, col)的棋子pieceId,并高亮显示,同时计算并显示其所有合法走法。 - 参数:
row(数字): 棋子所在的行。col(数字): 棋子所在的列。pieceId(字符串): 要选中的棋子ID。
- 功能: 选中位于
-
movePiece(fromRow, fromCol, toRow, toCol)- 功能: 将棋子从
(fromRow, fromCol)移动到(toRow, toCol)。 - 职责:
- 更新
boardState。 - 更新UI界面上的棋子位置。
- 处理吃子逻辑。
- 检查是否吃掉对方将/帅,若吃掉则结束游戏。
- 检查移动后是否造成将死或困毙。
- 切换玩家 (
switchPlayer())。 - 播放落子音效。
- 如果背景音乐未播放且未被用户暂停,则开始播放音乐。
- 更新
- 功能: 将棋子从
-
endGame(winner, reason)- 功能: 结束当前游戏。
- 参数:
winner(字符串): 胜方 ('R' 或 'B')。reason(字符串): 游戏结束的原因 (如 "黑方【将】被吃", "红方被将死")。
- 职责:
- 更新游戏结束状态。
- 累加胜方分数。
- 显示胜负信息。
- 根据胜方自动重置棋盘并开始新局,胜方先行。
-
switchPlayer()- 功能: 切换当前行棋方。如果轮到AI (黑方),则触发AI进行思考并移动 (
makeAIMove())。
- 功能: 切换当前行棋方。如果轮到AI (黑方),则触发AI进行思考并移动 (
-
背景音乐函数:
initBackgroundMusic(): 初始化背景音乐系统。playBackgroundMusic(): 播放当前选择的背景音乐。pauseBackgroundMusic(): 暂停当前播放的背景音乐。playRandomTrack(): 随机播放一首背景音乐。getRandomMusicIndex(): 获取一个随机的音乐索引。toggleBackgroundMusic(): 切换背景音乐的播放/暂停状态。
-
其他核心功能:
isMoveLegal,isValidBaseMove: 判断棋子移动的合法性。isKingInCheck,isCheckmate,isStalemate: 判断将军、将死和困毙情况。handleResign,handleUndoMove: 处理认输和悔棋操作。drawAIMoveIndicator: 显示AI移动的箭头指示器。
该文件运行在独立的Web Worker线程中,负责计算AI的走法,以避免阻塞浏览器主线程。
- 接收主线程发送的当前棋盘状态 (
boardState) 和搜索深度 (depth)。 - 使用极小极大算法 (
minimax) 配合Alpha-Beta剪枝来搜索最佳走法。 - 使用静态评估函数对局面进行评估。
- 还包含棋子位置价值表(PST)以提高AI评估的质量。
- 将计算得到的最佳走法发送回主线程。
-
findBestMove(boardState, depth = 3)- 功能: AI决策的核心函数。遍历AI方 (黑方 'B') 所有可能的合法移动,并对每一步棋之后形成的局面使用
minimax算法进行评估。 - 参数:
boardState(二维数组): 当前棋盘状态。depth(数字, 可选, 默认 3):minimax算法的搜索深度。
- 返回: 一个对象,表示最佳移动,格式为
{ fromRow, fromCol, toRow, toCol, pieceId }。
- 功能: AI决策的核心函数。遍历AI方 (黑方 'B') 所有可能的合法移动,并对每一步棋之后形成的局面使用
-
minimax(boardState, depth, alpha, beta, isMaximizingPlayer)- 功能: 实现了带Alpha-Beta剪枝的极小极大搜索算法。
- 参数:
boardState(二维数组): 当前评估的棋盘状态。depth(数字): 剩余搜索深度。alpha(数字): Alpha剪枝值。beta(数字): Beta剪枝值。isMaximizingPlayer(布尔型): 指示当前节点是最大化节点 (AI的回合) 还是最小化节点 (对手的回合)。
- 返回: 当前局面的评估分数。
-
quiescenceSearch(boardState, alpha, beta, isMaximizingPlayer, depth)- 功能: 静态搜索算法,用于减少水平效应。
- 参数: 与
minimax类似。 - 返回: 一个更稳定的评估分数。
-
evaluateBoard(boardState)- 功能: 评估给定棋盘状态的分数。AI (黑方) 尝试最大化此分数 (黑方物质价值 - 红方物质价值)。
- 参数:
boardState(二维数组)。 - 返回: 数字,表示评估分数。
- 游戏加载后自动开始播放随机选择的背景音乐。
- 音乐会循环播放并在一首结束后随机切换到下一首。
- 用户可以通过音乐控制按钮暂停/恢复播放。
- 系统会记住用户的暂停选择,不会在AI走棋时自动恢复被用户暂停的音乐。
- 任意一方获胜后,系统会自动开始新的一局,胜方先行。
- 积分会累计,反映每位玩家的胜场数。
- 只有点击"重新开始"按钮才会重置积分并重新选择难度。
- "认输"按钮会立即结束当前局,黑方得1分,并自动开始新局(黑方先行)。
- 消息提示在棋盘楚河汉界中央显示,更加醒目。
- AI移动时会显示箭头指示器,帮助玩家理解AI的走法。
- 当前难度显示在界面下方,方便用户查看。
- 确保你的浏览器支持 JavaScript 和 Web Workers。
- 直接用浏览器打开
index.html文件即可开始游戏。
- 确保已安装Node.js环境。
- 运行以下命令安装依赖:
npm install - 启动开发服务器:
npm run dev - 在浏览器中访问显示的本地URL(通常是
http://localhost:5173/)。
- 选择难度并开始游戏。
- 红方(下方)由玩家控制,黑方(上方)由AI控制。
- 点击己方棋子进行选中,然后点击有效位置(绿色标记)移动。
- 吃掉对方的将/帅,或将对方将死/困毙即可获胜。
- 如果局面不利,可以点击"认输"按钮。
- 如果想撤销上一步,可以点击"悔棋"按钮。
- 背景音乐可以通过音乐按钮控制开关。
- Web Worker技术: AI计算在独立线程中进行,不会阻塞UI交互。
- 先进的AI算法: 结合极小极大搜索、Alpha-Beta剪枝、静态搜索和局面评估。
- 棋子位置价值表(PST): 使AI能更好地理解不同棋子在不同位置的战略价值。
- 响应式设计: 适应不同屏幕大小的布局。
- 音频管理系统: 随机播放背景音乐,记住用户的播放偏好。
- 流畅的游戏流程: 自动开始新局,胜方先行,提高游戏体验。
本项目基于 Apache License 2.0 协议开源。查看 LICENSE 文件了解更多信息。