这是一个著名的问题。在 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的棋盘再说
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| .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; } } } }
|
然后加上文本框和马
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| 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;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| .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);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| import "./App.scss"; import Icon from "./assets/horse.svg"; import { ChangeEvent, useState } from "react";
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;
|