如何修改Chessboard.js代码实现PGN加载与方向键复盘功能?
实现PGN加载与方向键浏览对局的代码修改方案
核心修改内容
- 新增全局变量存储对局每一步的FEN序列、当前浏览位置
- 新增PGN加载函数,传入PGN字符串即可自动解析生成步数序列
- 绑定键盘方向键事件,实现对局步进退控制
- 兼容原有状态更新逻辑,无需修改原有核心走棋代码
完整修改后JS代码
var board = null var game = new Chess() var $status = $('#status') var $fen = $('#fen') var $pgn = $('#pgn') // 新增对局浏览相关变量 var fenHistory = [] var currentMoveIndex = 0 function onDragStart (source, piece, position, orientation) { // 对局结束后禁止拾取棋子 if (game.game_over()) return false // 仅允许当前走棋方拾取己方棋子 if ((game.turn() === 'w' && piece.search(/^b/) !== -1) || (game.turn() === 'b' && piece.search(/^w/) !== -1)) { return false } } function onDrop (source, target) { // 校验走法合法性 var move = game.move({ from: source, to: target, promotion: 'q' // 示例默认升变为后,可根据需求调整 }) // 非法走法自动回弹棋子 if (move === null) return 'snapback' updateStatus() } // 棋子落子后更新棋盘位置,兼容王车易位、吃过路兵、升变场景 function onSnapEnd () { board.position(game.fen()) } function takeBack () { board.position(game.undo()) } // 新增:加载PGN函数 function loadPgn(pgnStr) { // 重置所有状态 game.reset() fenHistory = [] currentMoveIndex = 0 // 解析PGN const loadSuccess = game.load_pgn(pgnStr) if (!loadSuccess) { alert('PGN格式错误,加载失败') return } // 生成每一步对应的FEN序列 const allMoves = game.history() game.reset() fenHistory.push(game.fen()) // 存储初始位置FEN allMoves.forEach(move => { game.move(move) fenHistory.push(game.fen()) }) // 初始化到对局起始位置 currentMoveIndex = 0 board.position(fenHistory[currentMoveIndex]) updateStatus() } // 新增:绑定方向键事件 $(document).keydown(function(e) { if (fenHistory.length === 0) return // 左箭头:后退一步 if (e.key === 'ArrowLeft' || e.keyCode === 37) { if (currentMoveIndex > 0) { currentMoveIndex-- game.load(fenHistory[currentMoveIndex]) board.position(fenHistory[currentMoveIndex]) updateStatus() } } // 右箭头:前进一步 if (e.key === 'ArrowRight' || e.keyCode === 39) { if (currentMoveIndex < fenHistory.length - 1) { currentMoveIndex++ game.load(fenHistory[currentMoveIndex]) board.position(fenHistory[currentMoveIndex]) updateStatus() } } }) function updateStatus () { var status = '' var moveColor = '白方' if (game.turn() === 'b') { moveColor = '黑方' } // 判定将死 if (game.in_checkmate()) { status = '对局结束,' + moveColor + '被将死' } // 判定和棋 else if (game.in_draw()) { status = '对局结束,和棋' } // 对局进行中 else { status = moveColor + '行棋' // 判定将军 if (game.in_check()) { status += ',' + moveColor + '被将军' } } // 新增:显示当前浏览进度 if (fenHistory.length > 0) { status += ` | 第 ${currentMoveIndex} 步 / 共 ${fenHistory.length - 1} 步` } $status.html(status) $fen.html(game.fen()) $pgn.html(game.pgn()) } var config = { draggable: true, // 如果仅做对局浏览,可改为false禁用拖拽走棋 position: 'start', onDragStart: onDragStart, onDrop: onDrop, onSnapEnd: onSnapEnd } board = Chessboard('legalBoard', config) updateStatus() // 对接sqlite使用示例:读取到PGN内容后直接调用loadPgn即可 /* const pgnFromSqlite = '从sqlite中读取到的PGN文本内容' loadPgn(pgnFromSqlite) */
HTML可选补充(测试用)
如果需要手动触发加载PGN,可以在原有HTML中新增加载按钮:
<button id="loadPgnBtn">加载PGN对局</button> <div id="legalBoard" style="width: 400px"></div> <span>对局状态</span> <div id="status"></div> <span>PGN</span> <div id="pgn"></div> <span>FEN</span> <div id="fen"></div>
对接sqlite说明
你只需要从sqlite中读取到.pgn文件对应的文本内容后,调用loadPgn(pgn文本)函数即可完成对局加载,加载完成后直接按键盘左右方向键即可浏览对局进程。
内容的提问来源于stack exchange,提问作者lukitamodric
相关产品推荐
相关产品推荐

