iSpring 前端面试题「Пятнашки」:React Hooks + TypeScript 实现可解 15 拼图实战指南
教程【免费下载链接】ru-test-assignmentsТестовые задания для самостоятельного выполнения от разных it компаний项目地址https://gitcode.com/gh_mirrors/ru/ru-test-assignments点击查看免费下载导读本文围绕 iSpringispringtech/coding-interview前端面试题中的「Пятнашки」15 Puzzle / 数字华容道任务完整解读原题的四项功能要求与五项技术约束并结合经典 15 拼图的算法原理给出可复现的 React Hooks TypeScript 实现方案包括可解性判定、洗牌算法、点击移动与胜利检测。读完本文你将能独立完成这道前端测试题并理解它背后考察的 React 状态管理、不可变更新与组合数学知识点。原题出自 frontend.md 所列测试任务清单完整题目位于 15.md。一、原题要求逐条解读1.1 功能需求Задание原文档要求开发经典版本的“Пятнашки”游戏具体功能点如下「Начать заново」重新开始按钮将数字 115 以随机顺序打乱排列生成的组合必须是可解的решаема不能随便生成任意乱序否则可能无解方块通过点击移动Квадратики должны перемещаться по клику点击某个方块若其与空格相邻则滑动到位正确排列时向用户祝贺胜利поздравлен с победой当 115 按序排好且空格归位时触发胜利提示。1.2 技术约束Требования原题对实现方式有明确限制这是面试官考察的重点约束项具体内容语言TypeScript或 Vanilla JS 组件类型检查样式/结构纯手写 CSS 与 HTML禁止预处理器Sass/Less与模板引擎UI 框架必须使用 React且采用函数式风格 Hooks第三方依赖除 React 外不得引入任何第三方库加分项使用 state manager状态管理器自选如 Zustand/Redux Toolkit这些约束意味着打乱算法、可解性判断、移动逻辑、胜利判定都必须由你自己实现不能借助 lodash 之类工具库也不能用现成的拼图组件。二、核心算法为什么随机打乱可能导致无解2.1 可解性判定的数学原理15 拼图4×4 棋盘含一个空格并不是所有排列都可还原。一个排列可解的充要条件如下空格从初始位置右下角到目标位置的曼哈顿距离为偶数在 4×4 棋盘中空格的目标位置为第 4 行第 4 列初始与目标相同距离恒为 0为偶数逆序对inversions数量为偶数。逆序对的定义从左到右、从上到下读取棋盘跳过空格得到长度为 15 的序列若其中某一对数字i j但位置上前者大于后者则计一个逆序对。当逆序对数量为偶数时排列可解为奇数时不可解。由于本题中空格最终仍回到右下角奇偶性一致判定规则可简化为逆序对数为偶数即可解。2.2 为什么必须显式保证可解性如果只是简单地对1..15做Math.random()洗牌约有 50% 的概率生成不可解排列。用户在不可解的棋盘上无论怎么移动都无法完成游戏就“卡死”了。因此原题特别强调“生成的组合必须可解”这是本题最重要的算法考察点。2.3 两种可靠的洗牌策略策略一对合法移动序列洗牌正向构造从已还原的目标棋盘出发随机执行 N 次合法移动只能移动与空格相邻的方块。由于每一步都从可解状态出发最终状态必然可解for (let i 0; i 200; i) { const moves getLegalMoves(board, emptyIndex); // 空格上下左右可交换的方块 const pick moves[Math.floor(Math.random() * moves.length)]; swap(board, emptyIndex, pick); }策略二随机排列 逆序对校验逆向修正先生成随机排列计算逆序对数若为奇数交换任意两个非空格方块如前两个数字将逆序对奇偶性翻转从而保证可解function isSolvable(flat: number[]): boolean { const tiles flat.filter((v) v ! EMPTY); let inversions 0; for (let i 0; i tiles.length; i) { for (let j i 1; j tiles.length; j) { if (tiles[i] tiles[j]) inversions; } } return inversions % 2 0; }两种策略任选其一即可建议优先采用策略一因为它的正确性不依赖对奇偶规则的推导且更容易用测试验证。三、React Hooks 架构设计3.1 状态模型在函数式 React 中用 Hooks 管理游戏状态的核心思路是把棋盘建模为一维数组空格用0表示索引位置即棋盘格子编号type Board number[]; // 长度 16值为 0..150 表示空格const [board, setBoard] useStateBoard(SOLVED_BOARD); const [moves, setMoves] useState(0); const [won, setWon] useState(false);其中SOLVED_BOARD [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0]目标状态空格在末尾。3.2 移动逻辑点击与相邻性判定“方块按点击移动”的本质是点击的方块索引必须与空格索引相邻上下左右二者才交换。用useCallback封装const moveTile useCallback( (index: number) { if (won) return; const emptyIndex board.indexOf(0); const row Math.floor(index / 4); const col index % 4; const eRow Math.floor(emptyIndex / 4); const eCol emptyIndex % 4; const isAdjacent Math.abs(row - eRow) Math.abs(col - eCol) 1; if (!isAdjacent) return; // 不相邻忽略点击 const next [...board]; [next[index], next[emptyIndex]] [next[emptyIndex], next[index]]; setBoard(next); setMoves((m) m 1); }, [board, won] );这里用Math.abs(dRow) Math.abs(dCol) 1判断曼哈顿距离为 1 即相邻简洁且无边界问题。注意setBoard(next)传入的是新数组满足 React 不可变更新的要求保证重渲染正确。3.3 胜利检测每次setBoard后用useEffect监听棋盘是否达到目标状态useEffect(() { if (board.every((v, i) v SOLVED_BOARD[i])) { setWon(true); } }, [board]);也可以把判断内联进moveTile在交换后立即比对目标数组命中则setWon(true)并渲染祝贺消息如「Поздравляем! Вы собрали головоломку за N ходов」。3.4 重新开始按钮「Начать заново」按钮将棋盘重置为洗牌后的新随机可解状态并复位步数与胜利标记const shuffle useCallback(() { const shuffled randomSolvableBoard(); // 见 2.3 节两种策略之一 setBoard(shuffled); setMoves(0); setWon(false); }, []);建议在首次挂载useEffect[]依赖时也执行一次洗牌让用户进入页面即可开始游戏。四、渲染与样式实现要点4.1 纯 CSS 网格布局原题要求纯手写 CSS无预处理器、无 UI 库4×4 棋盘用 CSS Grid 即可优雅实现.board { display: grid; grid-template-columns: repeat(4, 80px); grid-template-rows: repeat(4, 80px); gap: 4px; } .tile { display: flex; align-items: center; justify-content: center; font-size: 24px; border-radius: 6px; background: #4a90d9; color: #fff; cursor: pointer; user-select: none; } .tile--empty { background: transparent; cursor: default; }渲染时div classNameboard {board.map((value, index) ( button key{index} className{tile ${value 0 ? tile--empty : }} onClick{() moveTile(index)} disabled{value 0} {value 0 ? : value} /button ))} /div用button而非div可以免费获得键盘可达性这是加分细节。空格格子渲染为空且禁用点击。4.2 组件拆分建议App持有游戏状态与事件处理洗牌、移动、胜利标志Board纯展示组件接收board与onTileClickTile单个方块负责自身样式与点击回调。这样的拆分让状态集中在顶层符合函数式 Hooks 的推荐写法也便于后续引入 state manager。五、加分项接入状态管理器State Manager原题明确写出“使用 state manager 是加分项”。在仅允许 React 一个依赖的前提下可以选择轻量的 Zustandzustand包或 React 内置的useReducer Context。以useReducer为例零额外依赖最符合“不引入第三方库”约束type Action | { type: MOVE; index: number } | { type: SHUFFLE } | { type: RESET }; function reducer(state: GameState, action: Action): GameState { switch (action.type) { case MOVE: { // 相邻判定 交换 胜利检测返回新 state return movedState(state, action.index); } case SHUFFLE: { return { board: randomSolvableBoard(), moves: 0, won: false }; } default: return state; } }Reducer 是纯函数把“移动、洗牌、重置”三类状态转换集中在一处天然可测试。若面试官偏好外部状态库也可用 Zustand 的create定义 store效果等价。六、可测试性与代码组织建议纯函数优先把isSolvable、randomSolvableBoard、isAdjacent、move都写成不依赖 React 的纯函数便于单测用例覆盖至少验证三类用例——可解判定对错例的区分、从任意可解状态移动一步后仍可解、胜利检测在目标状态触发运行方式项目可用 Create React App 或 Vite 初始化二者均以 TypeScript 模板开箱支持 JSX 与类型检查执行npm install与npm start或npm run dev即可本地运行npm test运行测试。注意实现游戏逻辑本身无需任何额外库第三方依赖仅限 React 及脚手架工具。七、面试考察点总结这道题在 iSpring 的 frontend.md 中与「Пианино (Junior)」、「Пианино (Middle)」、「Drag to area」、「Видеоплеер」并列属于面向 Frontend 开发者的经典测试任务主要考察算法功底15 拼图可解性判定逆序对奇偶性与洗牌策略React 函数式写法HooksuseState/useEffect/useCallback与不可变状态更新代码组织纯函数与组件拆分、state manager 的使用工程约束意识在“零第三方库”限制下完成全部功能这对测试候选人区分度较高。完整题目原文见 15.md同系列其他任务可对照 frontend.md 任务清单查阅。赞分享教程【免费下载链接】ru-test-assignmentsТестовые задания для самостоятельного выполнения от разных it компаний项目地址https://gitcode.com/gh_mirrors/ru/ru-test-assignments点击查看免费下载相关推荐Sendsay 前端面试题实战用 React TypeScript 从零实现拖拽式计算器构造器Calculator ConstructorSendsay 前端面试题实战用 React TypeScript 从零实现拖拽式计算器构造器Calculator Constructor 本篇技术指教程KODE 前端实习生测试任务实战指南React TypeScript 实现员工目录应用KODE 前端实习生测试任务实战指南React TypeScript 实现员工目录应用 导读 本文以开源仓库 ru test assignments ht教程Highcharts React高级技巧自定义组件集成与性能优化实战Highcharts React高级技巧自定义组件集成与性能优化实战 Highcharts React是官方支持的React图表组件库它允许开发者轻松地在R上一篇中文AI绘画终极指南5分钟掌握ComfyUI工作流配置秘籍下一篇开发者必看Llama-3.2-1B-Instruct API接口调用与参数配置详解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

AlgoNote 算法通关手册:LeetCode 0955「删列造序 II」贪心题解与逐列状态标记法详解

AlgoNote 算法通关手册:LeetCode 0955「删列造序 II」贪心题解与逐列状态标记法详解

教程文档知识库 【免费下载链接】AlgoNote ⛽️「算法通关手册」:从零开始的「算法与数据结构」学习教程,200 道「算法面试热门题目」,1000 道「LeetCode 题目解析」,持续更新中! 项目地址: https://gitcod…

2026/10/10 8:24:53 阅读更多 →
Matplotlib绘图核心方法与常见报错实战指南

Matplotlib绘图核心方法与常见报错实战指南

有阵子没写Matplotlib了,后台收到不少朋友私信,问得最多的还是那几件事:图表做出来不好看、中文字体乱码、图例和刻度调不明白,还有一堆奇奇怪怪的报错。趁着整理项目的机会,我把Matplotlib图表绘制的核心方法和踩过的…

2026/10/10 8:24:53 阅读更多 →
NYU-DLSP20 第七周技术全解:能量基模型、自监督学习与自编码器的 PyTorch 实战

NYU-DLSP20 第七周技术全解:能量基模型、自监督学习与自编码器的 PyTorch 实战

示例工程 【免费下载链接】NYU-DLSP20 NYU Deep Learning Spring 2020 项目地址: https://gitcode.com/gh_mirrors/pyt/pytorch-Deep-Learning 点击查看 免费下载 本篇技术指南围绕本仓库(NYU Deep Learning Spring 2020 课程,即 pytorch-De…

2026/10/10 8:24:53 阅读更多 →

最新新闻

小模型干大事路线图:从 GLiNER v2 60M 到 340M Decide,轻量 NER 路线的三招可复制打法

小模型干大事路线图:从 GLiNER v2 60M 到 340M Decide,轻量 NER 路线的三招可复制打法

小模型干大事路线图:从 GLiNER v2 60M 到 340M Decide,轻量 NER 路线的三招可复制打法 【免费下载链接】GLiNER2.5-Decide 项目地址: https://ai.gitcode.com/hf_mirrors/fastino/GLiNER2.5-Decide 过去两年,中文技术社区讨论"小…

2026/10/10 12:06:42 阅读更多 →
南京大学ICS PA实验:NEMU+nanos-lite全栈系统实践指南

南京大学ICS PA实验:NEMU+nanos-lite全栈系统实践指南

简介:本资源是南京大学ICS课程PA实验的完整教学实践包,面向计算机系统、操作系统与编译原理方向的本科生及自学者,聚焦底层系统开发能力培养。压缩包含487个文件,主体为188个C源码、145个头文件(h)、48个Ma…

2026/10/10 12:06:42 阅读更多 →
跳跃游戏高频题详解:贪心算法如何判断数组能否到达终点

跳跃游戏高频题详解:贪心算法如何判断数组能否到达终点

一直被“到达不了终点”折磨的人,看完这篇应该能少走很多弯路。力扣 Hot 100 的第 55 题“跳跃游戏”,是所有刷题人都绕不过去的一道经典题。它的题干很短:给你一个非负整数数组,初始位置在下标 0,每个元素代表你在该位…

2026/10/10 12:06:42 阅读更多 →
从x²=2到伽罗瓦群:域扩张、极小多项式与正规扩张完全梳理

从x²=2到伽罗瓦群:域扩张、极小多项式与正规扩张完全梳理

如果你正在学抽象代数,或者备战考研,一定绕不开一个问题:方程 x2 在有理数世界里无解。教材上会写“引入 Q(√2)”,但很少有人把这一步背后的逻辑讲透。有理数域上的扩域,就是把 Q 不包含的数,通过某种受控…

2026/10/10 12:06:42 阅读更多 →
readmap地图转换工具详解:千年服务端MAP文件解析与编译实战

readmap地图转换工具详解:千年服务端MAP文件解析与编译实战

简介:资源为千年游戏服务端地图转换工具readmap的完整工程包,面向游戏服务端开发、私服运维及经典游戏地图数据研究者。工具主要实现千年map文件的解析与格式转换,便于调整地形、怪物与NPC等地图要素;标题关联msp430f149微控制器&…

2026/10/10 12:06:42 阅读更多 →
YOLOv8智慧校园人脸识别与公路车辆检测实战指南

YOLOv8智慧校园人脸识别与公路车辆检测实战指南

简介:基于YOLOv8的智慧校园人脸识别与公路汽车检测项目,面向AI入门及进阶学习者,可直接用作毕设、课程设计或工程实训。项目实现校园门口进出人员识别,通过yolov8l-face模型检测人脸、track技术持续跟踪,再由dlib的res…

2026/10/10 12:05:41 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:25 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →