ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

freeCodeCamp 每日编程挑战解析:用 JavaScript 实现象棋兵的合法走法(Valid Pawn Moves)

freeCodeCamp 每日编程挑战解析:用 JavaScript 实现象棋兵的合法走法(Valid Pawn Moves) freeCodeCamp 每日编程挑战解析用 JavaScript 实现象棋兵的合法走法Valid Pawn Moves【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp本文以 freeCodeCamp 开源仓库中的每日编程挑战Daily Coding Challenge第 173 题「Valid Pawn Moves」为蓝本完整还原题面、棋盘规则、测试用例与官方参考解法并结合仓库中的板块配置、种子脚本与 API 实现从一道题延伸到这套每日挑战系统如何运转的源码级解析。读完本文你将掌握 8×8 棋盘坐标建模、按规则枚举合法走法、边界条件处理等实战能力也能独立在本地运行并验证这套每日挑战的完整数据链路。挑战背景Daily Coding Challenge 与第 173 题freeCodeCamp 仓库中有一个名为daily-coding-challenges-javascript的课程板块其中按编号存放了超过 240 道短小精悍的算法题截至当前仓库challengeOrder已排到 Challenge 240第 173 题正是其中之一源文件位于 challenge-173 源文件。从板块配置文件 daily-coding-challenges-javascript.json 可以看出这套题目的设计特点helpCategory: JavaScript按 JavaScript 语言组织分类usesMultifileEditor: true使用多文件编辑器承载代码disableLoopProtectTests: true禁用循环保护测试允许自由编写循环逻辑isUpcomingChange: true标记为即将发布的新内容题目以Challenge N: 标题的形式顺序排列例如 Challenge 171Flatten the Array、Challenge 172Letters-Numbers、Challenge 173Valid Pawn Moves、Challenge 174Zodiac Finder。这套挑战还有一个重要特性同一道题同时存在 JavaScript 与 Python 两个版本仓库中的daily-coding-challenges-javascript与daily-coding-challenges-python两个板块成对出现因此本篇文章的解法同样可以作为两种语言解题思路的参考起点。题目描述给定兵的位置返回所有合法走法棋盘坐标系统题面给出的前提是标准国际象棋棋盘8×8列从左到右标记为A到H行从下到上标记为1到8完整坐标如下|A8|B8|C8|D8|E8|F8|G8|H8| | - | - | - | - | - | - | - | - | |A7|B7|C7|D7|E7|F7|G7|H7| |A6|B6|C6|D6|E6|F6|G6|H6| |A5|B5|C5|D5|E5|F5|G5|H5| |A4|B4|C4|D4|E4|F4|G4|H4| |A3|B3|C3|D3|E3|F3|G3|H3| |A2|B2|C2|D2|E2|F2|G2|H2| |A1|B1|C1|D1|E1|F1|G1|H1|注意这里的坐标约定是字母在前、数字在后例如D4表示第 D 列第 4 行。这是整个题目的核心数据结构一个坐标由列字母A–H 行数字1–8两个分量拼接而成。走法规则本挑战对兵的移动做了简化设定只需遵守三条规则你是棋盘底部的玩家即兵只能向上方移动行号递增方向兵通常每次只能向上移动一格例外情况如果兵位于起始行第 2 行它可以向上移动一格或两格。换句话说合法的目标格集合是第 8 行没有合法走法已到棋盘顶端无法再向上第 2 行起始行{上一行, 上两行}例如B2→[B3, B4]其余行第 1 行外的 3–7 行只有{上一行}例如D4→[D5]。说明本挑战刻意省略了兵吃子走斜线过路兵en passant兵升变等真实国际象棋规则聚焦于直线前进 起始行两格特权这一最小规则集因此返回的目标格之间没有棋子阻挡的判定。函数签名与示例要求实现函数findPawnMoves(position)输入一个坐标字符串返回一个按升序排列的合法目标格数组。题面给出的两个示例| 输入 | 输出 | 原因 | | - | - | - | |D4|[D5]| 普通行只能前进一格 | |B2|[B3, B4]| 起始行可前进一格或两格升序排列 |测试用例hints全览源文件中的--hints--部分是这道题的全部验收标准本质上是五组断言。它们在本地校验和后续种子入库时都会被原样执行| 断言 | 期望结果 | | - | - | |findPawnMoves(D4)|[D5]| |findPawnMoves(B2)|[B3, B4]| |findPawnMoves(A7)|[A8]| |findPawnMoves(G2)|[G3, G4]| |findPawnMoves(E3)|[E4]|这五组用例刻意覆盖了关键分支普通行D4、E3、起始行两格特权B2、G2、以及最顶端行边界A7只能走到A8验证了行号上限为 8 的边界约束。种子代码与官方参考解法种子代码起点源文件的--seed-contents--部分给出了解题起点函数体默认直接返回传入的position等待补充实现function findPawnMoves(position) { return position; }官方参考解法--solutions--源文件同时提供了完整的参考实现这也是本挑战最简洁直观的解法function findPawnMoves(position) { const column position[0].toUpperCase(); const row parseInt(position[1]); const moves []; if (row 8) return moves; moves.push(${column}${row 1}); if (row 2) moves.push(${column}${row 2}); return moves; }逐行拆解这段解法解析坐标position[0]取列字母并用toUpperCase()兼容小写输入parseInt(position[1])把行字符解析为数字初始化结果数组moves []边界处理if (row 8) return moves;处理第 8 行含越界输入此时兵已在棋盘顶端直接返回空数组前进一格把${column}${row 1}拼进结果起始行特权if (row 2)时再前进一格得到${column}${row 2}返回结果由于实现顺序天然是先row 1后row 2输出自然满足题面要求的升序排列。边界情况与正确性分析把官方解法放到全输入空间审视可以确认以下边界全部被覆盖row 8第 8 行无合法走法返回[]例如输入H8得到空数组row 2起始行返回两个目标格例如G2→[G3, G4]列字母大小写toUpperCase()使得b2与B2得到相同结果增强了对输入格式的鲁棒性数字字符解析parseInt(2)得到数字 2字符串模板${row 1}会把它拼回目标格字符串。从时间复杂度看该解法是严格O(1)的无论输入是什么都只执行常数次字符串操作没有任何循环或递归这是此类规则枚举型题目的最优形态。相比需要遍历棋盘或构建映射表的方案直接基于行号做分支判断既简单又不易出错。解法变体正则与字符码理解了解析逻辑后可以自然衍生出等价的变体写法供对比学习// 变体一正则提取字母与数字 function findPawnMoves(position) { const match position.match(/^([A-Ha-h])([1-8])$/); if (!match) return []; const column match[1].toUpperCase(); const row Number(match[2]); const moves row 8 ? [${column}${row 1}] : []; if (row 2) moves.push(${column}${row 2}); return moves; } // 变体二字符码转换列号 function findPawnMoves(position) { const colCode position.charCodeAt(0) - 65; // 0 ~ 7 const row position[1]; const column String.fromCharCode(65 colCode); const moves []; if (row 8) moves.push(${column}${row 1}); if (row 2) moves.push(${column}${row 2}); return moves; }变体一额外增加了输入格式校验非法坐标返回空数组变体二则展示了字符码与 ASCII 之间的换算技巧——这类字母 ↔ 数字的双向转换在第 172 题Letters-Numbers等相邻挑战中同样适用。从一道题到一套系统挑战文件的完整数据链路这道题的 Markdown 源文件不仅仅是一个静态文档它处于 freeCodeCamp 每日挑战系统的源头位置。理解这条链路能让你真正看懂挑战题面 → 数据库 → 线上接口的运转方式。第一步Curriculum 源文件 → 种子脚本tools/daily-challenges 目录 下的 seed-daily-challenges.ts 会把dev-playground超级板块下daily-coding-challenges-javascript与daily-coding-challenges-python两个板块的挑战批量导入 MongoDB 的DailyCodingChallenges集合。其中几个关键事实均来自源码数量校验脚本硬编码EXPECTED_CHALLENGE_COUNT 365两个语言的挑战数量必须一致否则直接抛错按天排期从START_DATE 2025-08-11起每天一道new Date(START_DATE.getTime() i * ONE_DAY_IN_MS)数据合并helpers.ts 中的combineChallenges会把同一道题的 JavaScript 与 Python 两个版本的tests、challengeFiles合并成一个文档同时校验两个版本的标题、描述、测试数量完全一致题面清洗removeSection会剥掉解析器添加的section iddescription包裹标签只保留纯题面文档主键直接复用挑战的id如本道的69738771fb5a7b8b24cca29f作为 MongoDB_id该 ID 同时用于记录用户已完成挑战的completedDailyCodingChallenges[]数组。第二步数据库 → API 接口api/src/daily-coding-challenge 目录 下的 README.md 明确说明该模块提供获取每日编程挑战信息的接口而提交评测逻辑仍留在 API 主模块中。路由与校验分别位于 routes/daily-coding-challenge.ts 与 schemas/daily-coding-challenge.ts。日期处理工具 utils/helpers.ts 体现了这套系统的几个设计细节getNowUsCentral()按美国中部时区America/Chicago计算今天——每日挑战以美中时间切日dateStringToUtcMidnight()与monthDayStringToUtcDate()分别把YYYY-MM-DD与MM-DD格式的日期字符串解析为 UTC 午夜且做了正则格式校验和非法日期回卷防御getSourceDate()由于只生成了 2025-08-11 至 2026-08-10 一年的题库该函数会把任意请求日期映射回原始题库日期含 2 月 29 日落到 2 月 28 日的特殊处理实现题库循环复用。第三步API → 前端组件前端在 client/src/components/daily-coding-challenge 目录下有对应的 widget.tsx、calendar.tsx 等组件用于在页面上展示每日一题同时 e2e/daily-coding-challenge.spec.ts 提供了端到端测试覆盖。整个链路可以概括为curriculum 挑战 Markdown含 --hints-- / --seed-contents-- / --solutions-- │ seed-daily-challenges.tstools/daily-challenges ▼ MongoDB DailyCodingChallenges 集合365 条JSPython 双语合并 │ api/src/daily-coding-challenge路由 时区/日期处理 ▼ 前端 widget / calendar 组件client/src/components/daily-coding-challenge学习要点总结坐标建模把字母 数字的棋盘坐标拆成独立的列分量与行分量处理是这类题目的通用第一步规则最小化题面明确省略了吃子、升变等复杂规则解题时应严格按题面规则实现不自行扩展边界先行第 8 行无走法与第 2 行起始行特权两个分支是本体的全部逻辑row 8的提前返回让代码更清晰结果有序性按row 1→row 2的构造顺序天然满足升序要求无需额外排序可测试性五组 hints 断言就是验收标准把每个分支都映射到至少一个用例是编写高质量挑战题以及编写任何函数的良好示范。如果你想在本地完整跑通这套系统可以按 tools/daily-challenges/README.md 的指引操作复制sample.env为.env、安装依赖、以显示即将发布内容的方式启动主客户端使 GraphQL 端点可用、进入tools/daily-challenges目录后执行pnpm seed-daily-challenges即可把题库灌入本地的freecodecamp数据库。而在此之前不妨先在浏览器控制台或 Node REPL 中运行本文的参考解法用五组测试用例验证findPawnMoves的全部分支——这本身就是对输入 → 规则 → 输出这一编程思维的最小练习。【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表