You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React中仅通过键盘实现棋子的选择与移动?

纯键盘操作国际象棋的实现方案

基于你提供的React Chessboard组件,要实现纯键盘的棋子选择与移动,可按以下步骤改造:

1. 新增状态管理

在Chessboard组件中添加状态,跟踪当前选中的格子坐标、是否处于选中棋子的状态,以及可修改的棋子位置数据:

import { useState, useEffect } from 'react';

export const Chessboard: React.FC = () => {
  // 跟踪当前选中的格子坐标
  const [selectedPos, setSelectedPos] = useState<{x: number, y: number} | null>(null);
  // 标记是否处于选中棋子待移动的状态
  const [isSelecting, setIsSelecting] = useState(false);
  // 将棋子数据转为状态变量,方便修改
  const [figures, setFigures] = useState(initialFigures);

  // 原有的棋盘生成逻辑...
};

2. 监听键盘事件

用useEffect全局监听键盘按键,处理方向键、Enter、Esc的核心逻辑:

useEffect(() => {
  const handleKeyDown = (e: KeyboardEvent) => {
    // 初始状态下,默认定位到棋盘左上角格子(可根据需求调整)
    if (!selectedPos) {
      setSelectedPos({x: 0, y: horisontalAxis.length - 1});
      return;
    }

    const {x, y} = selectedPos;
    const maxX = verticalAxis.length - 1;
    const maxY = horisontalAxis.length - 1;

    switch(e.key) {
      // 方向键移动选中框
      case 'ArrowUp':
        e.preventDefault();
        if (y < maxY) setSelectedPos({x, y: y + 1});
        break;
      case 'ArrowDown':
        e.preventDefault();
        if (y > 0) setSelectedPos({x, y: y - 1});
        break;
      case 'ArrowLeft':
        e.preventDefault();
        if (x > 0) setSelectedPos({x: x - 1, y});
        break;
      case 'ArrowRight':
        e.preventDefault();
        if (x < maxX) setSelectedPos({x: x + 1, y});
        break;
      // Enter键切换状态:选中棋子/执行移动
      case 'Enter':
        e.preventDefault();
        if (!isSelecting) {
          // 检查当前格子是否有棋子,有则进入选中状态
          const hasFigure = figures.some(f => f.x === x && f.y === y);
          if (hasFigure) setIsSelecting(true);
        } else {
          // 将选中的棋子移动到当前格子
          const updatedFigures = figures.map(f => {
            if (f.x === selectedPos.x && f.y === selectedPos.y) {
              return {...f, x, y};
            }
            return f;
          });
          setFigures(updatedFigures);
          setIsSelecting(false); // 结束选中状态
        }
        break;
      // Esc键取消选中状态
      case 'Escape':
        setIsSelecting(false);
        break;
    }
  };

  window.addEventListener('keydown', handleKeyDown);
  return () => window.removeEventListener('keydown', handleKeyDown);
}, [selectedPos, isSelecting, figures]);

3. 改造Cell组件,添加状态样式

修改Cell组件的渲染逻辑,接收选中状态的props,添加对应的样式类:

// 在Chessboard生成Cell时传递状态
board.push(
  <Cell 
    key={`${i}, ${j}`} 
    image={image} 
    num={num}
    isSelected={isSelecting && selectedPos?.x === i && selectedPos?.y === j}
    isTarget={!isSelecting && selectedPos?.x === i && selectedPos?.y === j}
  />
);

// Cell组件示例
export const Cell: React.FC<{
  image: string;
  num: number;
  isSelected?: boolean;
  isTarget?: boolean;
}> = ({image, num, isSelected, isTarget}) => {
  return (
    <div 
      className={`cell ${isSelected ? 'selected-piece' : ''} ${isTarget ? 'target-pos' : ''}`}
    >
      {image && <img src={image} alt="chess piece" />}
    </div>
  );
};

4. 定义状态样式

在CSS中添加选中棋子和目标位置的样式,让用户直观感知当前操作状态:

.cell {
  width: 60px;
  height: 60px;
  border: 1px solid #000;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 选中棋子的格子样式 */
.cell.selected-piece {
  background-color: #ffd700;
  outline: 3px solid #ff8c00;
}

/* 目标移动位置的格子样式 */
.cell.target-pos {
  background-color: #90ee90;
  outline: 2px solid #228b22;
}

额外优化建议

  • 移动合法性校验:在执行移动前,根据国际象棋规则判断该棋子是否能移动到目标位置(比如兵只能前进1格、车走直线等)。
  • 初始定位优化:组件挂载时自动将选中框定位到有棋子的格子(比如白方的兵行)。
  • 快捷键提示:在界面角落添加简单的快捷键说明(比如「方向键移动 · Enter选中/移动 · Esc取消」)。

内容的提问来源于stack exchange,提问作者Tykhon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 08:54:20