前端搭建打字通游戏(内附源码)

news2024/12/22 20:06:05

The sand accumulates to form a pagoda

  • ✨ 写在前面
  • ✨ 打字通功能介绍
  • ✨ 页面搭建
  • ✨ 样式代码
  • ✨ 功能实现


✨ 写在前面

上周我们实通过前端基础实现了名言生成器,当然很多伙伴再评论区提出了想法,后续我们会考虑实现的,今天还是继续按照我们原定的节奏来带领大家完成一个打字通的小游戏,功能也比较简单简单,也是想借助这样一个简单的功能,然后来帮助大家了解我们JavaScript在前端中的作用, 在前面的文章当中我们也提及到我们在本系列的专栏是循序渐进从简单到复杂的过程,后续会带领大家用前端实现猜数字、翻卡片、扫雷、贪吃蛇等有趣的小游戏,纯前端语言实现,都会陆续带给大家。欢迎大家订阅我们这份前端小游戏的专栏。


✨ 打字通功能介绍

在这里插入图片描述

我们中间白色区域就是我们文本域,用户可以在里面输入内容,我们点击开始按钮后我们下面的倒计时就会启动,这里我们是以60秒倒计时,与此同时上面的你准备好了吗?将变成我们的文案内容,我们需要照着文案内容再文本域中进行输入,倒计时结束后我们的我们上面将变成最终的得分,然后用户可以重新点击开始,又是同样的倒计时,当然我们可以自己规定规则,大家可以自己修改变成更棒的小游戏!下面我们就按照前面的思路先来实现一下吧!


✨ 页面搭建

创建文件

首先呢我们创建我们的HTML文件,这里我就直接命名为 打字通.html 了,大家可以随意命名, 文件创建生成后我们通过编辑器打开,这里我用的是VScode, 然后初始化我们的代码结构,那在这里告诉大家一个快捷键,就是我们敲上我们英文的一个 ! 我们敲击回车直接就会给我们生成基础版本的前端代码结构。

在这里插入图片描述

搭建DOM结构

我们现在就可以再body中对着我们的效果图开始搭建我们的DOM结构了,首先的话,我们可以看到我们肯定是有一个大的盒子,我们就先来定义这个盒子我们设置类名就为bigBox,然后我们上面的你准备好了吗?我们也放一个盒子我们设置类名为container,盒子的下面是一个文本域,这个文本域我们前端可以使用 textarea 标签,标签中有一些属性,在下面我们可以看到我们用到了几个属性,首先placeholder的作用是提示文字,我们可以看没有输入内容的时候看到开始输入…字样,我们style是设置样式这里我是通过resize:none来禁止我们文本域的拖拽,大家可以先不设置这个属性然后感受一下我们文本域的右下角是有一个三角是可以对文本域进行拖拽的,这里呢我们禁止拖拽,为了保护我们后续的布局,这是我们的文本域,再往下面就是我们的按钮跟倒计时的内容,这里我们的首先添加一个盒子类名叫做operate,然后盒子里面我们添加一个按钮跟一个类名叫做timer的div,就是下面这些代码,我们可以保存代码然后看一下页面。

<div class="bigBox">
  <div class="container">
    你准备好了吗?
  </div>
  <textarea name="" placeholder="开始输入..."
   id="" style="resize:none" cols="30" 
   rows="10"></textarea>
  <div class="operate">

    <button>开始</button>
    <div id="timer">60</div>
  </div>
</div>

在这里插入图片描述


✨ 样式代码

大盒子样式

上面的框架我们已经搭建出来了,其实在我们的开发过程中我们是肯定搭建一个DOM元素然后就开始编写样式的,但是这里为了方便给大家展示我们只能先搭建完所有的元素统一来配置样式,首先呢我们还是一样在我们的head中添加style标签,在里面编写我们的样式代码,老规矩先为我们的body设置上margin: 0; padding: 0;font-family: Arial, sans-serif;,内外边距都为0还有我们的字体;在我们的bigBox设置宽度50%,背景颜色,外边距上下为40px,然后水平居中,设置盒子模型为标准盒子,内边距为20px,边框圆角30px,然后盒子阴影,这个每个值什么意思我们再上篇文章中为大家讲解了,大家可以看一下;最后我们看一下效果

body {
  font-family: Arial, sans-serif;
  margin: 0;
  padding: 0;
}
.bigBox {
  width: 50%;
  background-color: #ac8c3e;
  margin: 40px auto;
  box-sizing: border-box;
  padding: 20px;
  border-radius: 30px;
  box-shadow: 0px 0px 30px 9px #939393;
}

在这里插入图片描述

盒子内部布局

为我们类名为container的盒子也就是上面的你准备好了吗?盒子设置居中,然后通过text-align: center;设置文字居中,内边距为20px,大家可以保存看一下效果;这里就不一一展示效果了,然后我们为中间的文本域,设置宽度100%,高度200px,外边距上下位20px左右为0,然后我们设置他的边框为none,不展示边框,下面就是文本域下面的区域,我们用了一个类名叫做operate的盒子来包裹按钮跟倒计时,我们为这个盒子设置宽度为20%,然后水平居中,字体居中,继续设置里面的botton按钮,字体大小24px,内边距上下为10px,左右为20px,背景颜色为 #007bff 字体颜色白色,边框设置为none不展示,圆角为5px,在通过cursor: pointer;鼠标悬浮为手状;最后在设置我们id为timer的倒计时,字体大小为48px,然后外边距上下左右都是20px;保存代码我们看一下效果;

.container {
  margin: 0 auto;
  text-align: center;
  padding: 20px;
}

textarea {
  width: 100%;
  height: 200px;
  margin: 20px 0;
  font-size: 20px;
  border: none;
}

.operate {
  width: 20%;
  margin: 0 auto;
  text-align: center;
}
    
button {
  font-size: 24px;
  padding: 10px 20px;
  background-color: #007bff;
  color: #fff;
  border: none;
  border-radius: 5px;
  cursor: pointer;
}

#timer {
  font-size: 48px;
  margin: 20px;
}

在这里插入图片描述


✨ 功能实现

那么代码写到这里呢,其实我们页面已经搭建完整了,但是我们的页面现在处于纯静态页面,也就是说仅仅用于展示, 现在还没有任何的效果,我们想要实现动态的一些交互效果就需要用到我们的JS来完成,下面呢我们就从几个方面来实现我们整体的效果;

获取所需元素和内容

首先呢我们知道点击开始之后,上面的你准备好了吗就要换成我们的范文,首先我们先声明变量来放我们的范文,我们声明变量text值就是我们的范文内容,这给大家找了一段英文的;我们还要通过document.querySelector先获取我们的元素后面会使用;然后我们先为我们的文本域设置内容为空;

  const text =
    "Believe in yourself and all that you are. Know that there is something inside you that is greater than any obstacle. This quote by Christian D. Larson reminds us that we all have the power within us to overcome any obstacle we may face. When we have confidence in ourselves and our abilities, we can achieve great things. So, let's trust ourselves, believe in our dreams, and work hard to make them a reality.";

  const container = document.querySelector(".container");
  const input = document.querySelector("textarea");
  const button = document.querySelector("button");
  const timer = document.getElementById("timer");
  input.value = "";

为按钮注册事件

通过addEventListener为按钮注册时间,我们在函数中首先把倒计时设置为60秒,然后清空我们输入框和范文的内容,然后我们调用startGame函数。

// 添加按钮点击事件监听器
button.addEventListener("click", () => {
  // 设置倒计时时间
  timer.textContent = "60";

  // 清空输入框和输出文本区域
  input.value = "";
  container.textContent = "";

  // 启动游戏
  startGame();
});

启动游戏

上面的代码我们是通过点击按钮然后来用到我们下面的startGame函数,我们在这个函数的前面的首先要声明一个变量countdown用来承接定时器的销毁,在函数中首先呢我们要将按钮禁用,倒计时期间不能重复点击,然后我们将范文展示再我们的container元素中,然后我们运用定时器setInterval,第一参数是一个函数,第二个参数是隔多少秒,下面的意思就是每秒执行一次函数,在函数中我们首先获取到倒计时现在的数值,第一次这里肯定为60,然后这里我们申明常量remainingTime来接受当前秒数-1,我们还有一个判断就是如果当前描述是0那么我们就执行endGame函数,然后我们对描述进行赋值就完成了我们的倒计时效果;下面呢我们继续写endGame函数。

  let countdown;

  function startGame () {
    // 游戏开始后,禁用按钮
    button.disabled = true;

    // 显示文本
    container.textContent = text;



    // 启动倒计时
    countdown = setInterval(() => {
      const remainingTime = parseInt(timer.textContent) - 1;
      if (remainingTime === 0) {
        // 时间用完,游戏结束
        endGame();
      }

      timer.textContent = remainingTime;
    }, 1000);
  }

暂停游戏

endGame函数中我们首先就是停止倒计时,也就是销毁定时器,我们刚才说到了我们申明了一个变量用来承接定时器,这里的销魂我们就可以通过变量来;然后我们要计算得分,计算得分的函数呢我们下面讲解,首先这里你要知道计算得分的函数是调用后返回分数即可,然后我们将分数显示再范文区域,并且取消按钮的禁用;

function endGame () {
  // 停止倒计时
  clearInterval(countdown);

  // 计算得分
  const score = calculateScore();
  const scoreMessage = `你的得分是 ${score} 分!`;
  container.textContent = scoreMessage;

  // 显示按钮和计时器
  // button.style.display = "block";
  // timer.style.display = "block";
  button.disabled = false;
}

分数的计算

在上面我们结束游戏的函数中调用了计算分数的calculateScore 函数,在这个函数中我们需要按照规则生成分数并且返回,看下面首先我们将文本域、范文内容通过.trim()移除两端的空格,并且赋值给变量,然后我们通过split将所有内容按照空格进行拆分,然后我们进行循环每个单词进行一一对应如果相等则分数++,最后将分数return出去,调用的地方就可以直接拿到了。

function calculateScore () {
  const userText = input.value.trim();
  const correctText = text.trim();
  const userWords = userText.split(" ");
  const correctWords = correctText.split(" ");
  let score = 0;

  for (let i = 0; i < userWords.length; i++) {
    console.log(userWords[i], correctWords[i])
    if (userWords[i] === correctWords[i]) {
      score++;
    }
  }

  return score;
}

上面这些就是我们实现的整体思路跟代码,当然这里你完全可以按照自己的私聊来编写逻辑,上面也只是完成小小的功能,大家可以结合自己的想法编写,然后在这里呢有个小小的点,就是我是为了大家能够跟得上逻辑然后按照用户行为的先后顺序来介绍的,当然这样写也没有问题,但是还是建议大家函数要写在调用的前面,比如我们的启动游戏的函数是再按钮点击的时候调用的,那我们可以把启动游戏的函数代码写在点击事件的前面会更好以写;下面的完整代码也给到大家了哦!还有一点就是为了用户体验我们可以禁止用户复制,直接把范文复制到文本域好像不太好,我们可以再css代码的body中添以下代码;

body {
  font-family: Arial, sans-serif;
  margin: 0;
  padding: 0;
  -moz-user-select: none;
  /*火狐*/
  -webkit-user-select: none;
  /*webkit浏览器*/
  -ms-user-select: none;
  /*IE10*/
  -khtml-user-select: none;
  /*早期浏览器*/
  -o-user-select: none;
  user-select: none;
}

完整代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      margin: 0;
      padding: 0;
      -moz-user-select: none;
      /*火狐*/
      -webkit-user-select: none;
      /*webkit浏览器*/
      -ms-user-select: none;
      /*IE10*/
      -khtml-user-select: none;
      /*早期浏览器*/
      -o-user-select: none;
      user-select: none;
    }

    .bigBox {
      width: 50%;
      background-color: #ac8c3e;
      margin: 40px auto;
      box-sizing: border-box;
      padding: 20px;
      border-radius: 30px;
      box-shadow: 0px 0px 30px 9px #939393;
    }

    .container {
      margin: 0 auto;
      text-align: center;
      padding: 20px;
    }

    textarea {
      width: 100%;
      height: 200px;
      margin: 20px 0;
      font-size: 20px;
      border: none;
    }

    .operate {
      width: 20%;
      margin: 0 auto;
      text-align: center;
    }

    button {
      font-size: 24px;
      padding: 10px 20px;
      background-color: #007bff;
      color: #fff;
      border: none;
      border-radius: 5px;
      cursor: pointer;
    }

    #timer {
      font-size: 48px;
      margin: 20px;
    }
  </style>
</head>

<body>

  <div class="bigBox">
    <div class="container">
      你准备好了吗?
    </div>
    <textarea name="" placeholder="开始输入..." id="" style="resize:none" cols="30" rows="10"></textarea>
    <div class="operate">
      <button>开始</button>
      <div id="timer">60</div>
    </div>
  </div>


  <script>
    const text =
      "Believe in yourself and all that you are. Know that there is something inside you that is greater than any obstacle. This quote by Christian D. Larson reminds us that we all have the power within us to overcome any obstacle we may face. When we have confidence in ourselves and our abilities, we can achieve great things. So, let's trust ourselves, believe in our dreams, and work hard to make them a reality.";

    const container = document.querySelector(".container");
    const input = document.querySelector("textarea");
    const button = document.querySelector("button");
    const timer = document.getElementById("timer");
    input.value = "";



    let countdown;

    function startGame () {
      // 游戏开始后,禁用按钮
      button.disabled = true;

      // 显示文本
      container.textContent = text;


      // 启动倒计时
      countdown = setInterval(() => {
        const remainingTime = parseInt(timer.textContent) - 1;
        if (remainingTime === 0) {
          // 时间用完,游戏结束
          endGame();
        }

        timer.textContent = remainingTime;
      }, 1000);
    }

    function endGame () {
      // 停止倒计时
      clearInterval(countdown);

      // 计算得分
      const score = calculateScore();
      const scoreMessage = `你的得分是 ${score} 分!`;
      container.textContent = scoreMessage;

      button.disabled = false;
    }

    function calculateScore () {
      const userText = input.value.trim();
      const correctText = text.trim();
      const userWords = userText.split(" ");
      const correctWords = correctText.split(" ");
      let score = 0;

      for (let i = 0; i < userWords.length; i++) {
        console.log(userWords[i], correctWords[i])
        if (userWords[i] === correctWords[i]) {
          score++;
        }
      }

      return score;
    }

    // 添加按钮点击事件监听器
    button.addEventListener("click", () => {
      // 设置倒计时时间
      timer.textContent = "60";

      // 清空输入框和输出文本区域
      input.value = "";
      container.textContent = "";

      // 启动游戏
      startGame();
    });

  </script>
</body>

</html>

本期推荐

在这里插入图片描述

原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下

👍 点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/493679.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java基础入门-06-【面向对象进阶(多态包final权限修饰符代码块)】

Java基础入门-06-【面向对象进阶&#xff08;多态&包&final&权限修饰符&代码块&#xff09;】 14、面向对象进阶&#xff08;多态&包&final&权限修饰符&代码块&#xff09;1.1 多态的形式1.2 多态的使用场景1.3 多态的定义和前提1.4 多态的运行…

嵌入式设备逆向所需的工具链

导语&#xff1a;本文介绍了嵌入式设备逆向所需的工具链。 相关的应用程序或工具有&#xff1a; UART(Universal Asynchronous Receiver Transmitter&#xff0c;通用异步收发器)&#xff1a; UBoot&#xff1b; Depthcharge&#xff1b; SPI (Serial Peripheral Interface…

利用文本描述替换万物(Inpaint-Anything-Description)

文章目录 引言安装Demo github&#xff1a; https://github.com/Atlas-wuu/Inpaint-Anything-Description 引言 前段时间看了万物分割SAM、文生图Stable Diffusion、开集检测Grounding DINO&#xff0c;它们之间可以互相补充&#xff0c;AIGC变得更加可控。Inpaint Anything将…

RK3568平台开发系列讲解(网络篇)Linux 的 socket 套接字

🚀返回专栏总目录 文章目录 一、套接字的数据结构1.1、struct socket 数据结构1.2、struct sock 数据结构二、套接字的初始化三、套接字与文件四、Socket Buffer沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 Linux 内核支持的套接字如下: 我们创建套接字时,可以…

PCIe物理层弹性缓存机制(详细)解析-PCIe专题知识(四)

目录 前言一、简介二、详细解析2.1 实例解析2.2 具体实现过程 三、总结四、其他相关链接1、PCI总线及发展历程总结2、PCIe物理层总结-PCIE专题知识&#xff08;一&#xff09;3、PCIe数据链路层图文总结-PCIe专题知识&#xff08;二&#xff09;4、PCIe物理层链路训练和初始化总…

国产ChatGPT命名图鉴

很久不见这般热闹的春天。 随着ChatGPT的威名席卷全球&#xff0c;大洋对岸的中国厂商也纷纷亮剑&#xff0c;各式本土大模型你方唱罢我登场&#xff0c;声势浩大的发布会排满日程表。 有趣的是&#xff0c;在这些大模型产品初入历史舞台之时&#xff0c;带给世人的第一印象其…

进程替换函数组介绍exec*

目录 前述 execl execlp execle execv execvp execvpe 前述 介绍后缀的意义&#xff1a; l &#xff08;list&#xff09;&#xff1a;表示参数采用列表。 v&#xff08;vector&#xff09;&#xff1a;参数同数组表示。 p&#xff08;path&#xff09;&#xff1a;自…

力扣题库刷题笔记704-二分查找

1、题目如下&#xff1a; 2、个人Python代码如下&#xff1a; 个人代码如下&#xff1a; class Solution: def search(self, nums: List[int], target: int) -> int: left 0 right len(nums) - 1 while left < right: mid (right left) >> 1 if nums[mid] >…

【C++类和对象之拷贝构造、赋值运算符重载】

拷贝构造、赋值运算符重载 ❀拷贝构造函数 特性 ❀赋值运算符重载 赋值运算符重载格式 &#x1f340;小结&#x1f340; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f389;系列…

【数字图像处理】边缘检测

文章目录 0. 前言1. Sobel算子2. Canny算子3. 深度学习算法3.1 Holistically-Nested Edge Detection&#xff08;HED&#xff09;3.2 Richer Convolutional Features&#xff08;RCF&#xff09; 0. 前言 边缘检测是一种图像处理技术&#xff0c;旨在标识和定位数字图像中的边…

【信息系统安全/计算机系统安全】期末复习(HITWH)

PDF版本及更多资料&#xff08;百度网盘&#xff09;&#xff1a; 链接&#xff1a;信息系统安全期末复习 目录 第一章 绪论 第二章 安全认证 填空题 第三章 访问控制 填空题 第四章 安全审计 填空题 第五章 Windows操作系统安全 填空题 第六章 Linux操作系统安全 填…

JDBCSpring:使用Spring JDBC封装Dao

目录标题 1、工程目录pom.xml文件 2、创建数据表student3、在resources目录创建配置文件applicationContext.xmljdbc.properties 4、创建Bean对象Student 5、创建Dao类UserDao接口 6、插入数据一、直接注入jdbctemplate二、继承jdbcdaosupport类 7、运行结果图 1、工程目录 pom…

go 使用pprof分析性能,trace追踪

前言 pprof是Go程序自带的性能分析工具&#xff0c;prof是profile&#xff08;画像&#xff09;的缩写&#xff0c;用于分析go程序的性能。 Profile Descriptions: allocs: A sampling of all past memory allocations 已分配内存采样 block: Stack traces that led to bloc…

梯度下降算法

梯度下降算法的公式&#xff1a; 公式依次代表为“下次迭代的点”、“目前所在的点”、“学习率”和“最大负向梯度”。按照这个公式&#xff0c;每次迭代都会根据上次的步长减去学习率乘以“梯度”的值&#xff0c;去一步一步更新&#xff0c;这样能可以每次迭代都朝着最大负方…

基于xml的Spring应用-1

基于xml的Spring应用 Spring的get方法 方法定义返回值和参数Object getBean (String beanName)根据beanName从容器中获取Bean实例&#xff0c;要求容器中Bean唯一返回值为Object&#xff0c;需要强转T getBean (Class type)根据Class类型从容器中获取Bean实例&#xff0c;要求…

SpringBoot 创建 WebService

开发环境: IDEA 2022.1.4 目录 1. 概述 2. 实现步骤 2.1 POM现加依赖 2.2 定义接口 IWebService 2.3 创建类 IWebServiceImpl 并实现接口 IWebService 2.4 配置类 CxfConfig 2.5 启动服务 2.6 测试 1. 概述 虽然webservice这块使用很少&#xff0c;但在局域网作服务还是相…

自动化测试之 selenium 的安装以及 selenium IDE 录制自动化脚本的用法

文章目录 1. 什么是自动化测试1&#xff09;单元测试2&#xff09;接口自动化3&#xff09;UI 自动化 2. Selenium 介绍1&#xff09;Selenium IDE2&#xff09;Webdriver3&#xff09;Selenium Grid 3. 如何使用 Selenium IDE 录制脚本4. 在 python 环境中安装 Selenium 框架 …

RSA--维纳攻击--代码和题目分析

文章目录 维纳攻击原理&#xff1a;维纳攻击脚本[羊城杯 2020]RRRRRRRSA 1题目描述&#xff1a;题目分析&#xff1a; 收获与体会&#xff1a; 维纳攻击原理&#xff1a; 两位大佬讲得非常清楚&#xff08;搬运工就是我&#xff09;&#xff1a;https://zhuanlan.zhihu.com/p/…

代码随想录算法训练营第五十二天| 300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组

文章目录 300.最长递增子序列674. 最长连续递增序列718. 最长重复子数组 300.最长递增子序列 想清楚如何推导dp数组是关键 两层for循环&#xff0c;因为递增序列不是连续的 题目链接&#xff1a;代码随想录 解题思路&#xff1a; 1.dp[i]表示i之前包括i的以nums[i]结尾的最长递…

SpringBoot整合Mybatis-Plus实现浏览数据新增、Redis进行热度排名

在开发Web项目时&#xff0c;常用到的技术就是SpringBoot和Mybatis-Plus。本文将介绍如何使用SpringBoot整合Mybatis-Plus实现一个浏览数据新增功能&#xff0c;以及如何用Redis进行热度排名统计&#xff0c;最后用Vue进行数据渲染。 一、SpringBoot整合Mybatis-Plus 1. 新建…