脑虎科技之马踏棋盘

这是一个著名的问题。在 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";

// 渲染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;