freeCodeCamp 每日编程挑战实战解析:Challenge 228 “Movie Night“ 电影票价计算

发布时间:2026/9/10 12:57:06
freeCodeCamp 每日编程挑战实战解析:Challenge 228 “Movie Night“ 电影票价计算 freeCodeCamp 每日编程挑战实战解析Challenge 228 Movie Night 电影票价计算【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp导读本文以 freeCodeCamp 开源仓库中的每日编程挑战Challenge 228: Movie Night为对象完整还原题目规则、7 组官方测试用例与参考实现并结合仓库源码剖析这道题在每日编程挑战体系中的发布、验证与运行链路。读完本文你将掌握 12 小时制时间解析、多规则定价优先级排序、toFixed(2)金额格式化等实战技巧同时理解 freeCodeCamp 每日编程挑战从课程文件到 API 服务的完整技术闭环。一、挑战背景这道题在 freeCodeCamp 里的位置Movie Night 是 freeCodeCamp 每日编程挑战Daily Coding ChallengeJavaScript 系列中的第 228 道题其 Markdown 源文件位于 curriculum/challenges/english/blocks/daily-coding-challenges-javascript/69a890af247de743333bd4d1.md。从块的元数据文件 curriculum/structure/blocks/daily-coding-challenges-javascript.json 可以看到该块共规划了 365 道 JavaScript 每日挑战isUpcomingChange标记为true表示这是一个仍在上线过程中的新模块题目从 Challenge 1: Vowel Balance 一直编排到第 365 题而 Challenge 228 就处于序列的中后段。该块还声明了helpCategory: JavaScript、usesMultifileEditor: true等属性说明这些题目在课程编辑器中使用多文件编辑环境运行。这道题的挑战类型为challengeType: 28与同一块内其他每日挑战保持一致区别于传统的 HTML/CSS 或算法题类型属于每日编程挑战这一独立题型体系。二、题目描述与函数签名题目要求实现一个函数getMovieNightCost它接收三个参数并返回该场次电影票的总价参数类型说明daystring星期几取值固定为Monday至Sunday七个英文单词之一showtimestring放映时间格式为H:MMam或H:MMpm例如10:00am、10:00pmnumberOfTicketsinteger购买的票数整数返回值必须严格格式化为$D.CC即美元符号加整数部分和两位小数例如$12.00。初始的种子代码只给出了函数骨架仅返回day占位function getMovieNightCost(day, showtime, numberOfTickets) { return day; }三、定价规则拆解四条规则与优先级题目给出了四条定价规则它们共同决定了最终单价周末票价周五、周六、周日Friday - Sunday每张票$12.00工作日票价周一至周四Monday - Thursday每张票$10.00日场折扣Matinee放映时间在下午 5:00 之前每张票减$2.00周二除外周二特价周二所有票一律$5.00每张。需要特别注意的是规则之间的优先级规则 4 是最强的特例一旦day是Tuesday直接以 $5.00 作为单价不再参与周末/工作日判断也不适用日场折扣这正对应规则 3 中except on Tuesdays的约束。换句话说周二的定价完全由规则 4 独立决定而规则 3 只作用于除周二以外的其余六天。从题目的英文表述看before 5:00pm 中的 5:00pm 是一个开区间边界恰好 5:00pm如5:40pm属于 5:00pm 之后不享受折扣而4:30pm等早于 5:00pm 的时间享受折扣。这一点在后面的官方测试用例中得到了明确印证。四、官方测试用例逐条验证原题附带了 7 组测试用例覆盖了所有规则分支与边界情况逐一分析如下调用预期结果规则解析getMovieNightCost(Saturday, 10:00pm, 1)$12.00周六属周末$12 × 1晚场无折扣getMovieNightCost(Sunday, 10:00am, 1)$10.00周日是周末应 $12但 10:00am 为日场减 $2得到 $10getMovieNightCost(Tuesday, 7:20pm, 2)$10.00周二特价 $5 × 2getMovieNightCost(Wednesday, 5:40pm, 3)$30.00周三工作日 $10 × 35:40pm 已过 5:00pm 不享受日场折扣getMovieNightCost(Monday, 11:50am, 4)$32.00周一工作日 $1011:50am 日场减 $2 得 $8$8 × 4getMovieNightCost(Friday, 4:30pm, 5)$50.00周五周末 $124:30pm 日场减 $2 得 $10$10 × 5getMovieNightCost(Tuesday, 11:30am, 1)$5.00周二特价 $5即使上午日场也不打折其中第二个用例非常有启发性周日虽然属于周末基准 $12但因为放映时间是上午场日场折扣 $2 依然生效最终单价为 $10。这说明规则 1周末定价与规则 3日场折扣是叠加关系而非互斥关系——只有在周二时折扣才被整体旁路。五、参考实现逐行拆解官方解决方案仓库在题目的# --solutions--部分给出了完整的参考实现其核心逻辑可以划分为五个步骤第一步判定周二特价短路其余规则let price; if (day Tuesday) { price 5; } else { // ... 其余定价逻辑 }周二分支直接赋值5并且整个日场折扣逻辑都放在else分支内从结构上保证了周二既不算周末价也不算日场价。第二步区分周末与工作日if ([Friday, Saturday, Sunday].includes(day)) { price 12; } else { price 10; }使用数组includes一次性判断三个周末日简洁且易扩展非周末周一至周四落入else分支得到 $10。注意此处else分支在逻辑上只会被周一至周四触发因为周二已在第一步被短路。第三步将 12 小时制时间解析为 24 小时制数值const hour parseInt(showtime.split(:)[0]); const period showtime.slice(-2); let hour24 hour; if (period pm hour ! 12) hour24 12; if (period am hour 12) hour24 0;这是整道题最核心、也最容易被忽略的边界处理showtime.split(:)[0]取出小时部分如10:00am→10再经parseInt转为数值showtime.slice(-2)取出末尾的am或pm后缀下午且非 12 点小时加 1210:00pm→ 22上午 12 点归零12:00am→ 0这是12:00am表示午夜的特殊情况中午 12 点12:00pm因hour ! 12条件不满足而保持 12恰好符合 24 小时制中 12 点即正午的语义。第四步应用日场折扣if (hour24 17) { price - 2; }将 24 小时制小时数与 17即 5:00pm比较严格小于 17 才减 2 美元。这精确实现了5:00pm 之前的边界语义——5:40pm的 24 小时制小时为 17不小于 17故不折扣与第三个测试用例吻合。第五步计算总额并格式化为美元金额const total price * numberOfTickets; return $${total.toFixed(2)};price * numberOfTickets得到总价toFixed(2)保证始终输出两位小数模板字符串前加$前缀最终产出如$50.00的标准格式。六、两种解题思路对比除官方参考实现外这道题还有另一种常见的字符串区间匹配思路直接对showtime做字典/正则匹配判断其是否位于 12:00am 至 4:59pm 区间。官方方案选择了先转 24 小时制再数值比较的路线其优势在于语义清晰把5:00pm 之前翻译成可读的hour24 17避免了维护大量字符串比较分支边界统一12 小时制中12:00am、12:00pm两个特殊时刻的转换规则集中处理不易遗漏可测试性强转换函数逻辑独立便于针对12:00am、12:00pm、11:59pm等边界单独验证。无论采用哪种实现都必须通过第一节中那 7 组覆盖了周末、工作日、周二特价、日场折扣、5:00pm 边界等全部分支的测试用例。七、从源码视角看挑战的验证机制在 freeCodeCamp 的挑战体系中每一道题的# --hints--部分定义了验证逻辑。本题的 7 个 hint 全部采用assert.equal(getMovieNightCost(...), ...)的形式即对函数进行黑盒断言运行函数、比较返回值。这类测试字符串在种子脚本入库后会被课程运行环境执行判定学习者提交的代码是否正确。从客户端一侧看每日挑战的展示与提交由独立的页面承载见 client/src/client-only-routes/show-daily-coding-challenge.tsx 与 client/src/components/daily-coding-challenge/widget.tsx。其中 widget 组件为用户提供前往今日挑战与浏览历史归档两个入口分别链接到/learn/daily-coding-challenge/MM-DD与/learn/daily-coding-challenge/archive。数据在到达前端之前还会经过一层结构校验客户端工具 client/src/utils/daily-coding-challenge-validator.ts 使用 Joi 定义了DailyCodingChallengeFromDb的结构要求每条挑战记录必须包含id、challengeNumber、title、date、description以及javascript、python两个语言维度的tests与challengeFiles字段——这说明每日挑战是**同一道题双语言JavaScript 与 Python**发布的Movie Night 的 JS 版本只是其中一半。八、延伸Movie Night 的完整技术链路从仓库源码结构看一道每日挑战从内容到用户可见要经过以下完整链路内容源挑战 Markdown含描述、hints、seed、solutions存放于 curriculum/challenges/english/blocks/daily-coding-challenges-javascript/块的顺序与数量由 curriculum/structure/blocks/daily-coding-challenges-javascript.json 控制入库种子脚本 tools/daily-challenges/seed-daily-challenges.ts 通过 GraphQL 从客户端课程数据中抓取全部 365 道题为每道题分配自 2025-08-11 起按天递增的日期写入 MongoDB 的DailyCodingChallenges集合对外服务API 层在 api/src/daily-coding-challenge/routes/daily-coding-challenge.ts 暴露 6 个 GET 端点/date/:date、/day/:day、/today、/month/:month、/all、/newest请求与响应结构由 api/src/daily-coding-challenge/schemas/daily-coding-challenge.ts 中的 TypeBox 模式约束时区与日期映射由于 365 道题只覆盖一年周期api/src/daily-coding-challenge/utils/helpers.ts 中的getSourceDate会把任意请求日期映射回 2025-08-11 ~ 2026-08-10 的源挑战区间例如 2026 年 8 月 11 日之后的请求会自动映射到该周期的对应日期同时将 2 月 29 日映射到 2 月 28 日。也就是说当你某天在 freeCodeCamp 上做到 Movie Night 时它其实是被getSourceDate从源周期映射到当天的第 228 号挑战而每道题的 JS/Python 双语言测试数据正是由上述种子脚本从课程仓库同步进数据库的。九、总结与延伸练习Challenge 228 Movie Night 是一道典型的多规则定价计算实战题核心考点集中在三个层面分支优先级周二特价短路其余规则、时间格式解析12 小时制转 24 小时制的边界处理、金额格式化toFixed(2)与美元前缀。读完本文后建议你对照 原题源文件 自行实现一遍并尝试以下延伸改造将定价规则抽成配置对象如{ weekend: 12, weekday: 10, matineeDiscount: 2, tuesday: 5 }增强可维护性增加对非法输入如未知星期、13:00pm之类非法时间的防御性处理参考同一块的相邻题目如 Challenge 215 Parking Fee Calculator、Challenge 47 Caught Speeding这些题目同样在练习多条件定价/罚款计算可以串联复习同一类解题模式。【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考