跳转到内容

脑虎科技之马踏棋盘

发布于:

这是一个著名的问题。在 8×8 的国际象棋棋盘上用一个马按照马步跳遍整个棋盘,要求每个格子都只跳到一次,最后回到出发点。

第一问

你的任务是实现一个网页来展示马踏棋盘的整个交互过程。需求描述如 下:

需求a.页面上有一个输入框 “start point”,用户可以输入马的起始位置。起始位置是用逗号隔开的 2 个整数。例如用户输入 4,4,下面右图的起始位置 1 就 是坐标(4,4)

需求b. 实现一个拖动条,用户拖动这个拖动条,可以看到马当前移动的路径。 例如用户拖动到 40,那么下面的图就要展示出从第 1 到第 40 步移动的路径。

需求c. 实现两个个按钮,“line”用于显示马移动的路径,“numbers”用于 显示移动的步数。我这里图片显示是 2 个棋盘,你实际实现的时候,用户只应该 看到一个棋盘,用户点击 line 和 numbers 按钮的时候,棋盘显示效果会发生切换。

第二问

马踏棋盘并不是只是在国际象棋棋盘上才成立,其他尺寸的棋盘也一样 具有这样的结论。传统的马踏棋盘需要马最终回到起点,第二和第三问这里可以 稍微弱化我们的要求,只要求走完整个棋盘的格子,不要求回到起点。 需求 d:在保留前面功能的前提下,增加一个输入框,名称叫”board size”, 用于输入棋盘的大小。起始位置是用逗号隔开的 2 个整数。例如输入 (3,10),得 到的结果是这样的

例如输入 (25,25),得到的结果是这样的

第三问

马踏棋盘并不是只是在矩形的棋盘上才成立,其他不规则图形也有可能 具有这样的结论。 需求 e:在保留需求 a,b,c 的前提下,增加一个用户自定义棋盘按钮”user defined board”,用户点击此按钮之后可以从自己的电脑上传一个自己定义的 棋盘文件,这个文件是用 json 或者 yaml 描述的。然后得到不规则图形的马踏 棋盘交互效果,如下图所示。你的代码注释里要讲清楚如何描述不规则棋盘

okok,一个个来

第一问

先实现一下8x8的棋盘再说

import "./App.scss";

function renderSquare() {
  const squares = [];
  for (let i = 0; i < 8; i++) {
    for (let j = 0; j < 8; j++) {
      const squareClass = (i + j) % 2 === 0 ? "square" : "square-black";
      squares.push(<button key={`${i}-${j}`} className={squareClass}></button>);
    }
  }
  return squares;
}

function App() {
  return <div className="container">{renderSquare()}</div>;
}

export default App;
.container {
  position: absolute;
  top: 0;
  left: 0;
  transform: translate(50%, 20%);
  height: 600px;
  width: 600px;
  border: 1px solid black;
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-template-rows: repeat(8, 1fr);

  .square {
    background-color: white;

    &:hover {
      background-color: #b8b4b4;
      cursor: pointer;
    }

    &-black {
      background-color: black;

      &:hover {
        background-color: #333;
        cursor: pointer;
      }
    }
  }
}

然后加上文本框和马

import "./App.scss";
import Icon from "./assets/horse.svg";
function renderSquare() {
  const squares = [];
  for (let i = 0; i < 8; i++) {
    for (let j = 0; j < 8; j++) {
      const squareClass = (i + j) % 2 === 0 ? "square" : "square-black";
      squares.push(<div key={`${i}-${j}`} className={squareClass}></div>);
    }
  }
  return squares;
}

function App() {
  return (
    <>
      <div className="container">{renderSquare()}</div>
      <img src={Icon} alt="horse" />
      <div className="searchbox">
        <input type="text" />
        <button>确定</button>
      </div>
    </>
  );
}

export default App;
.container {
  position: absolute;
  top: 0;
  left: 0;
  transform: translate(50%, 20%);
  height: 600px;
  width: 600px;
  border: 1px solid black;
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-template-rows: repeat(8, 1fr);

  .square {
    background-color: white;
    border: 1px solid black;
    &:hover {
      background-color: #b8b4b4;
      cursor: pointer;
    }
    &-black {
      background-color: black;
      &:hover {
        background-color: #333;
        cursor: pointer;
      }
    }
  }
}
.searchbox {
  position: absolute;
  top: 70%;
  left: 28%;

  input {
    width: 200px;
    height: 20px;
    font-size: 18px;
  }
  button {
    vertical-align: top;
    height: 26px;
  }
}

那么下一个问题:获取文本框的输入并区分逗号?

const values = inputValue.split(",").map(Number);

import "./App.scss";
import Icon from "./assets/horse.svg";
import { ChangeEvent, useState } from "react";

// 渲染8x8的棋盘
function renderSquare(startPosition: [number, number] | null) {
  const squares = [];
  for (let i = 0; i < 8; i++) {
    for (let j = 0; j < 8; j++) {
      const squareClass = (i + j) % 2 === 0 ? "square" : "square-black";
      squares.push(
        <div key={`${i}-${j}`} className={squareClass}>
          {startPosition && startPosition[0] === i && startPosition[1] === j && (
            <img src={Icon} alt="horse" style={{ position: "absolute" }} />
          )}
        </div>
      );
    }
  }
  return squares;
}

function App() {
  const [inputValue, setInputValue] = useState("");
  const [startPosition, setStartPosition] = useState<[number, number] | null>(null);

  const handleClick = () => {
    const values = inputValue.split(",").map(Number);

    if (values.length === 2 && values.every(n => !isNaN(n) && n >= 0 && n < 8)) {
      setStartPosition([values[0], values[1]]);
    } else {
      alert("请输入有效的起始位置,格式为:x,y,且 x 和 y 在 0 到 7 之间.");
    }
  };

  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
    setInputValue(event.target.value);
  };

  return (
    <>
      <div className="container">{renderSquare(startPosition)}</div>
      <div className="searchbox">
        <input type="text" value={inputValue} onChange={handleChange} />
        <button type="submit" onClick={handleClick}>
          确定
        </button>
      </div>
    </>
  );
}

export default App;