Bootstrap

【JavaScript——函数编写】猜硬币(蓝桥杯真题-2461)【合集】

目录😋

背景介绍

准备步骤

目标效果

要求规定

判分标准

通关代码✔️

代码解析📑

一、HTML 部分

二、CSS 部分

三、JavaScript 部分

四、工作流程▶️

测试结果👍


背景介绍

为了打发无聊的时间,小蓝开发了一款人机对战的猜硬币游戏,页面中一共有 9 个杯子,系统会随机挑选 3 个杯子在里面放入硬币,玩家通过输入含有杯子序号的字符串进行猜选,但是遇到了一些问题。

本题需要你帮助小蓝完成猜硬币游戏。


准备步骤

开始答题前,需要先打开本题的项目代码文件夹,目录结构如下:

├── css
├── effect.gif
├── images
├── index.html
└── js
    ├── findCoin.js
    └── index.js

其中:

  • css 是样式文件夹。
  • images 是图片文件夹。
  • index.html 是主页面。
  • js/index.js 是硬币渲染和动画逻辑。
  • js/findCoin.js 是需要补充代码的 js 文件。
  • effect.gif 是最终实现的效果图。

注意:打开环境后发现缺少项目代码,请手动键入下述命令进行下载:

cd /home/project
wget https://labfile.oss.aliyuncs.com/courses/9790/04.zip && unzip 04.zip && rm 04.zip

在浏览器中预览 index.html 页面效果如下:


目标效果

请在 js/findCoin.js 文件中补全 findNum 和 randomCoin 函数代码,最终实现猜硬币游戏。

具体需求如下:

  1. 页面加载后,系统会在 9 个杯子中随机挑选 3 个杯子生成硬币。
  2. 用户在文本框中输入任意字符串,点击确定按钮后,系统会找到字符串中含有 1-9 的数字,并根据数字打开对应的杯子。

完成后的效果见文件夹下面的 gif 图,图片名称为 effect.gif(提示:可以通过 VS Code 或者浏览器预览 gif 图片)。


要求规定

  • 请严格按照考试步骤操作,切勿修改考试默认提供项目中的文件名称、文件夹路径、class 名、id 名、图片名等,以免造成无法判题通过。

判分标准

  • 完成目标 1,得 5 分。
  • 完成目标 2,得 10 分。
  • 完成目标 3,得 5 分。

通关代码✔️

/**
 * @param {*} input_values input 框中输入的值
 * @returns Array  将输入的值中 1-9 组成一个数组
 */

// 将输入的值中 1-9 组成一个数组
function findNum(input_values) {
  // TODO:待补充代码
  return input_values.replace(/[^0-9]/g,'').split('').map(Number)
}

// 将 1-9 中三个不重复的随机数放入数组中,并返回这个数组
let randomCoin = () => {
  let randomNumArr = [];
  // TODO:待补充代码
  let set = new Set()
  while(set.size < 3){
    let ran = Math.ceil((Math.random()*9))
      set.add(ran)
  }
  randomNumArr = [...set]
  return randomNumArr;
};

// 请勿删除和修改下面代码
try {
  module.exports = { randomCoin, findNum };
} catch (e) {}

代码解析📑

一、HTML 部分

<!DOCTYPE html>
<html>
  <head>
    <title>猜硬币</title>
    <meta charset="utf-8" />
    <link href="./css/style.css" rel="stylesheet" type="text/css" />
  </head>

  <body>
    <div id="content">
      <p id="gameText"></p>
      <ul></ul>
      <div class="killout">
        <label for="killoutInput" style="color: #999">
          说明:填入序号,填入你猜测有硬币的杯子,可以输入任意值,只要输入的值中包含
          "1-9",就会根据对应的数字打开杯子<br />
          <input
            id="killoutInput"
            type="text"
            placeholder="填写你需要查找的位置序号"
          />
        </label>
      </div>

      <div class="btnbox">
        <button class="btn">确定</button>
      </div>
      <p id="result"></p>
    </div>
    <script src="./js/findCoin.js"></script>
    <script src="./js/index.js"></script>
  </body>
</html>
  1. 文档声明与头部
    • <!DOCTYPE html>:声明文档类型为 HTML5。
    • <title> 标签:设置页面标题为 “猜硬币”。
    • <meta charset="utf-8">:设置页面的字符编码为 UTF-8。
    • <link> 标签:引入外部的 CSS 文件 style.css,用于设置页面的样式。
  2. 主体内容
    • <div id="content">:页面的主要容器,包含了游戏的所有元素。
    • <p id="gameText">:用于显示游戏的提示信息或结果信息。
    • <ul>:用于显示杯子的列表。
    • <div class="killout">:包含了游戏的说明文本和输入框,用户可以在输入框中输入猜测有硬币的杯子序号。
    • <input id="killoutInput">:用户输入猜测的杯子序号的输入框。
    • <div class="btnbox">:包含了一个按钮,用于触发游戏的操作。
    • <button class="btn">:按钮,初始文本为 “确定”,点击后执行相应的游戏逻辑。
    • <p id="result">:可能用于显示游戏的结果(当前代码中未充分使用)。
  3. 脚本引入
    • <script src="./js/findCoin.js"></script> 和 <script src="./js/index.js"></script>:引入了两个外部的 JavaScript 文件,用于实现游戏的逻辑。

二、CSS 部分

html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
font,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend {
  margin: 0;
  padding: 0;
  font-size: 100%;
  border: 0;
  outline: 0;
  background: transparent;
}

ol,
ul {
  list-style: none;
}

:focus {
  outline: 0;
}

#content {
  padding-top: 40px;
}

#content ul {
  margin: 0 auto;
  width: 70%;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

.btnbox {
  width: 100%;
  margin: 0 auto;
  text-align: center;
}

#content ul li {
  margin: 20px;
  width: 8vw;
  height: 8vw;
}

#content ul li:last-child {
  margin-right: 0;
}

#content ul li a {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  perspective: 800px;
}

#content ul li a > div {
  position: absolute;
  left: 0;
  height: 0;
  width: 100%;
  height: 100%;
  color: #fff;
  overflow: hidden;
  transform-style: preserve-3d;
  transition: 0.8s ease-in-out;
  backface-visibility: hidden;
}

#content ul li a div:first-child {
  display: flex;
  justify-content: center;
  transform: rotateY(0);
  z-index: 2;
}

#content ul li a div:last-child {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  perspective: 800px;
}

#content ul li a > div {
  width: 100%;
  height: 100%;
  color: #fff;
  transition: 0.8s ease-in-out;
  backface-visibility: hidden;
}

#content ul li a div:first-child {
  display: flex;
  justify-content: center;
  z-index: 2;
}

#content ul li a div h1 {
  text-align: center;
  line-height: 90px;
  font-size: 12px;
}

#content ul li a div img {
  max-width: 100%;
}

.rotatey30 {
  transform: translate(0, -15px) rotate(-30deg) !important;
}

.btn,
.btn-all {
  margin-top: 60px;
  display: inline-block;
  color: #0099cc;
  background: #2e7eee;
  border-radius: 10px;
  text-decoration: none;
  text-transform: uppercase;
  border: none;
  color: white;
  padding: 8px 16px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  transition-duration: 0.4s;
  cursor: pointer;
}

.cardnum {
  position: absolute;
  font-size: 12px;
  left: 45%;
  top: 10px;
}

#gameText,
#result {
  text-align: center;
  padding-bottom: 20px;
}

.killout {
  text-align: center;
}

.killout input {
  display: inline-block;
}

.z {
  position: relative;
}

.z .cup,
.b .cup {
  transform: rotate(180deg);
  display: inline-block;
  transition: all 1s ease-in-out;
}

.coin {
  position: absolute;
  width: 30px;
  height: auto;
  left: 50%;
  bottom: 0;
  z-index: -1;
}

sup {
  text-align: center;
  line-height: 20px;
  width: 20px;
  height: 20px;
  position: absolute;
  font-size: 12px;
  z-index: 10000;
  color: #fff;
  left: 50%;
  top: 50%;
  margin-left: -5px;
  margin-top: -10px;
  border-radius: 50%;
}

#killoutInput {
  width: 200px;
  margin-top: 40px;
  box-sizing: border-box;
  font-variant: tabular-nums;
  list-style: none;
  position: relative;
  display: inline-block;
  padding: 4px 11px;
  color: #000000d9;
  font-size: 14px;
  line-height: 1.5715;
  background-color: #fff;
  background-image: none;
  border: 1px solid #d9d9d9;
  border-radius: 2px;
  transition: all 0.3s;
}
  1. 全局样式重置
    • 对常见的 HTML 元素进行样式重置,去除默认的边距、内边距、边框等,使页面布局更加统一。
  2. 页面容器与列表样式
    • #content:设置顶部内边距为 40px。
    • #content ul:设置列表的宽度为 70%,居中显示,使用弹性盒模型布局,使杯子列表可以自动换行并居中对齐。
    • #content ul li:设置每个杯子的外边距、宽度和高度,使用视口宽度单位 vw 来适应不同屏幕尺寸。
  3. 杯子与动画样式
    • #content ul li a:设置杯子的定位和透视效果,为 3D 动画做准备。
    • #content ul li a > div:设置杯子的内部元素的定位、颜色、溢出处理、3D 转换样式和过渡效果,以及背面不可见。
    • .rotatey30:定义了一个动画类,用于将杯子旋转一定角度,模拟打开杯子的效果。
  4. 按钮样式
    • .btn 和 .btn-all:设置按钮的样式,包括颜色、背景、边框、内边距、文本样式和过渡效果。
  5. 其他元素样式
    • #gameText 和 #result:设置文本的对齐方式和底部内边距。
    • .killout 和 .killout input:设置游戏说明和输入框的样式。
    • .z 和 .z .cup:设置杯子的定位和旋转样式。
    • .coin:设置硬币的定位和样式。
    • sup:设置杯子上序号的样式。
    • #killoutInput:设置输入框的样式,包括宽度、内边距、颜色、边框和过渡效果。

三、JavaScript 部分

index.js 部分

//index.js
// 初始化页面效果
let cardList;
let init = () => {
  cardList = [];
  // 根据随机数组生成硬币位置
  let gendercarlist = () => {
    let arr = randomCoin();
    for (let index = 0; index < 9; index++) {
      cardList.push({
        id: index + 1,
        category: `nomoney`,
        name: "空",
      });
    }
    for (let index = 0; index < arr.length; index++) {
      const item = arr[index];
      cardList[item - 1].category = "money";
      cardList[item - 1].name = "硬币";
    }
    return cardList;
  };
  let content = document.querySelector("#content ul");
  cardList = gendercarlist();
  content.innerHTML = "";
  for (let index = 0; index < cardList.length; index++) {
    let oneCard = cardList[index];
    content.innerHTML += `<li> 
                  <a href="javascript:void(0)">
                      <div class="z">
                         <img class='cup' src="./images/cup.svg">
                        
                          <sup>${index + 1}</sup>
                      </div>
                        ${
                          oneCard.category == "money"
                            ? `<img class='coin' src="./images/coin.svg">`
                            : ""
                        }
                  </a>
              </li>`;
  }
};

init();

let gameText = document.querySelector("#gameText");
let btnbox = document.querySelector(".btn");
let select_input = document.getElementById("killoutInput");
let ul = document.getElementsByTagName("ul")[0];
let flag = true;

// 点击确定按钮的逻辑
btnbox.addEventListener("click", function () {
  flag = !flag;
  if (flag) {
    this.innerHTML = "确定";
    select_input.value = "";
    gameText.innerHTML = ``;
    init();
  } else {
    this.innerHTML = "重置";
    let select_values = select_input.value;
    let res = findNum(select_values); // 找到输入值中 1-9 的数字
    let result = cardList.filter((item) => res.includes(item.id));
    let length = result.filter((item) => item.category == "money").length;
    if (length) {
      gameText.innerHTML = `恭喜你,找到了${length}个硬币`;
    } else {
      gameText.innerHTML = `很遗憾,没有找到硬币`;
    }
    // 打开杯子
    annimateCard(select_values);
  }
});
// 给选择的杯子添加动画
function annimateCard(select_values) {
  let domz = document.querySelectorAll(".z");
  let res = findNum(select_values);
  for (let index = 0; index < domz.length; index++) {
    if (res.includes(index + 1)) {
      domz[index].classList.add("rotatey30");
    }
  }
}
  1. 初始化函数 init
    • 初始化 cardList 数组,用于存储每个杯子的信息。
    • 调用 gendercarlist 函数生成硬币的随机位置。
    • 遍历 cardList,根据每个杯子是否有硬币,动态生成 HTML 结构并添加到页面的 <ul> 元素中。
  2. 获取页面元素
    • 获取页面中的 #gameText.btn#killoutInput 和 <ul> 元素,用于后续的操作和交互。
    • 定义 flag 变量,用于判断按钮的状态(确定或重置)。
  3. 按钮点击事件处理
    • 为按钮添加点击事件监听器。
    • 当按钮状态为 flag 为 true 时,将按钮文本设置为 “确定”,清空输入框和游戏提示信息,重新初始化游戏。
    • 当按钮状态为 flag 为 false 时,将按钮文本设置为 “重置”,获取输入框的值,调用 findNum 函数提取输入值中 1-9 的数字。
    • 根据提取的数字过滤 cardList,统计找到的硬币数量,并根据结果更新游戏提示信息。
    • 调用 annimateCard 函数,根据输入的数字为对应的杯子添加旋转动画,模拟打开杯子的效果。
  4. 动画函数 annimateCard
    • 获取所有杯子的 DOM 元素。
    • 调用 findNum 函数提取输入值中 1-9 的数字。
    • 遍历杯子的 DOM 元素,根据提取的数字为对应的杯子添加 rotatey30 类,触发旋转动画。

findCoin.js 部分

/**
 * @param {*} input_values input 框中输入的值
 * @returns Array  将输入的值中 1-9 组成一个数组
 */

// 将输入的值中 1-9 组成一个数组
function findNum(input_values) {
  // TODO:待补充代码
  return input_values.replace(/[^0-9]/g,'').split('').map(Number)
}

// 将 1-9 中三个不重复的随机数放入数组中,并返回这个数组
let randomCoin = () => {
  let randomNumArr = [];
  // TODO:待补充代码
  let set = new Set()
  while(set.size < 3){
    let ran = Math.ceil((Math.random()*9))
      set.add(ran)
  }
  randomNumArr = [...set]
  return randomNumArr;
};

// 请勿删除和修改下面代码
try {
  module.exports = { randomCoin, findNum };
} catch (e) {}
还有这段

findNum 函数

/**
 * @param {*} input_values input 框中输入的值
 * @returns Array  将输入的值中 1-9 组成一个数组
 */

// 将输入的值中 1-9 组成一个数组
function findNum(input_values) {
  // TODO:待补充代码
  return input_values.replace(/[^0-9]/g,'').split('').map(Number)
}
  1. 函数功能概述
    findNum 函数的作用是从用户在输入框中输入的值中提取出 1 到 9 的数字,并将这些数字组成一个数组返回。
  2. 代码解释
    • input_values.replace(/[^0-9]/g,''):使用正则表达式 /[^0-9]/g[^0-9] 表示匹配除了数字(0 到 9)之外的任意字符,g 是全局匹配标志。replace 方法将输入值中所有非数字字符替换为空字符串,这样就得到了只包含数字的字符串。
    • .split(''):将得到的只包含数字的字符串拆分成单个字符组成的数组,例如字符串 "123" 会被拆分成 ["1", "2", "3"]
    • .map(Number):使用 map 方法遍历数组中的每个元素,将每个元素(字符串形式的数字)转换为数字类型。例如 ["1", "2", "3"] 会被转换为 [1, 2, 3]
    • 最后返回处理后的数组。

randomCoin 函数

// 将 1-9 中三个不重复的随机数放入数组中,并返回这个数组
let randomCoin = () => {
  let randomNumArr = [];
  // TODO:待补充代码
  let set = new Set()
  while(set.size < 3){
    let ran = Math.ceil((Math.random()*9))
      set.add(ran)
  }
  randomNumArr = [...set]
  return randomNumArr;
};
  1. 函数功能概述
    randomCoin 函数的作用是从 1 到 9 的数字中随机选取三个不重复的数字,并将这三个数字组成一个数组返回,用于模拟硬币随机放置的位置。
  2. 代码解释
    • let set = new Set():创建一个 Set 对象,Set 是 JavaScript 中的一种数据结构,它的特点是存储的元素唯一,不会有重复值。
    • while(set.size < 3):当 Set 对象中的元素数量小于 3 时,进入循环。
    • let ran = Math.ceil((Math.random()*9)):生成一个 1 到 9 之间的随机整数。Math.random() 会返回一个大于等于 0 且小于 1 的随机小数,乘以 9 后得到一个大于等于 0 且小于 9 的随机小数,再使用 Math.ceil() 方法对这个小数向上取整,就得到了 1 到 9 之间的一个随机整数。
    • set.add(ran):将生成的随机整数添加到 Set 对象中。由于 Set 的元素唯一性,重复的数字不会被添加进去。
    • randomNumArr = [...set]:当 Set 对象中元素数量达到 3 个时,使用扩展运算符 ... 将 Set 对象转换为数组,并赋值给 randomNumArr
    • 最后返回 randomNumArr 数组。

模块导出部分

// 请勿删除和修改下面代码
try {
  module.exports = { randomCoin, findNum };
} catch (e) {}

这部分代码的作用是将 randomCoin 和 findNum 这两个函数导出,以便在其他模块中可以导入和使用这两个函数。module.exports 是 Node.js 中用于导出模块成员的方式,通过这种方式,其他文件可以使用 require 函数来引入这两个函数并调用。try-catch 块用于捕获可能出现的错误,即使在导出过程中出现异常,也不会导致程序崩溃。

四、工作流程▶️

  1. 页面加载
    • 浏览器加载 HTML 页面,解析并渲染页面结构。
    • 引入外部的 CSS 文件,应用页面样式。
    • 执行 JavaScript 代码,初始化游戏,生成杯子列表和随机放置硬币。
  2. 用户输入
    • 用户在输入框中输入猜测有硬币的杯子序号。
  3. 按钮点击
    • 用户点击 “确定” 按钮。
    • 按钮点击事件监听器判断按钮状态,如果是 “确定” 状态,重新初始化游戏;如果是 “重置” 状态,进行以下操作:
      • 获取输入框的值,提取其中 1-9 的数字。
      • 根据提取的数字过滤杯子列表,统计找到的硬币数量。
      • 根据统计结果更新游戏提示信息。
      • 为对应的杯子添加旋转动画,模拟打开杯子的效果。
  4. 游戏结果展示
    • 根据找到的硬币数量,在页面上显示相应的提示信息(恭喜找到硬币或很遗憾没有找到硬币)。
  5. 游戏重置
    • 用户再次点击 “重置” 按钮,游戏回到初始状态,用户可以重新输入猜测并进行下一轮游戏。

测试结果👍

在这里插入图片描述

;