JavaScript設計打字速度測試遊戲的實現

英文 | https://www.geeksforgeeks.org/design-a-typing-speed-test-game-using-javascript/?ref=leftbar-rightbar

翻譯 | web前端開發(ID:web_qdkf)

打字測試的目的是找出在給定的時間內打字的速度。我們將使用JavaScript設計打字遊戲,該遊戲提出了一個簡單的打字挑戰,並通過計算每分鐘字符數(CPM),每分鐘字數(WPM)和鍵入字符的準確性來找到鍵入性能。

遊戲會顯示一系列必須在指定的時限內儘快鍵入的報價。較高的鍵入速度將顯示較高的WPM值。在鍵入過程中將相應地標記輸入錯誤的字符。

我們將首先創建HTML佈局,使用CSS設置樣式,然後使用JavaScript編寫邏輯。

HTML佈局: HTML佈局定義了將在頁面上顯示的元素結構。這包括:

  • 標頭部分:此部分顯示當前鍵入會話的統計信息。這包括剩餘時間的顯示,錯誤數量,準確性,WPM和CPM。

  • 引用部分:此部分顯示必須在輸入區域中鍵入的當前文本。

  • 輸入區域:此部分包含必須在其中鍵入文本的輸入區域。

  • 重新啓動按鈕:這是重新啓動按鈕,一旦時間用完並且遊戲結束,就會顯示該按鈕。

代碼:

<html lang="en"> <head>     <title>Simple Speed Typer</title> 
    <!-- link the CSS file here -->    <link rel="stylesheet" href="style.css"> </head> <body>   <div class="container">     <div class="heading">       Simple Speed Typing     </div>     <div class="header">       <div class="wpm">         <div class="header_text">WPM</div>         <div class="curr_wpm">100</div>       </div>       <div class="cpm">         <div class="header_text">CPM</div>         <div class="curr_cpm">100</div>       </div>       <div class="errors">         <div class="header_text">Errors</div>         <div class="curr_errors">0</div>       </div>       <div class="timer">         <div class="header_text">Time</div>         <div class="curr_time">60s</div>       </div>       <div class="accuracy">         <div class="header_text">% Accuracy</div>         <div class="curr_accuracy">100</div>       </div>     </div> 
    <div class="quote">       Click on the area below to start the game.     </div>     <textarea class="input_area"      placeholder="start typing here..."      οninput="processCurrentText()"      οnfοcus="startGame()">     </textarea>     <button class="restart_btn"      οnclick="resetValues()">       Restart     </button>   </div> 
  <!-- link the JavaScript file here -->  <script src="game.js"> </script> </body> </html>

注意:每個部分都填充有僞數據,以使樣式設計更容易。上面的HTML代碼如下。

CSS樣式: CSS用於對不同部分進行樣式設置,並使其在視覺上更具吸引力。

  • 標題部分使用flex佈局顯示。

  • 給每個元素足夠的填充和邊距。

  • 每個元素的文本大小應使用戶在玩遊戲時易於閱讀。

  • 定義了兩個附加類來表示正確或錯誤鍵入的字母。這些類將在需要時動態添加或刪除。

代碼:

body {   background-color: #fe9801;   color: black;   text-align: center; } 
.container {   display: flex;   flex-direction: column;   align-items: center; } 
.heading {   margin-bottom: 20px;   font-size: 3rem;   color: black; } 
.header {   display: flex;   align-items: center; } 
.timer, .errors, .accuracy, .cpm, .wpm {   background-color: #ccda46;   height: 60px;   width: 70px;   margin: 8px;   padding: 12px;   border-radius: 20%;   box-shadow: black 5px 8px 5px; } 
.cpm, .wpm  {   display: none; } 
.header_text {   text-transform: uppercase;   font-size: 0.6rem;   font-weight: 600; } 
.curr_time, .curr_errors, .curr_accuracy, .curr_cpm, .curr_wpm {   font-size: 2.75rem; } 
.quote {   background-color: #ccda46;   font-size: 1.5rem;   margin: 10px;   padding: 25px;   box-shadow: black 5px 8px 5px; } 
.input_area {   background-color: #f5f5c6;   height: 80px;   width: 40%;   font-size: 1.5rem;   font-weight: 600;   margin: 15px;   padding: 20px;   border: 0px;   box-shadow: black 5px 8px 5px; } 
.restart_btn {   display: none;   background-color: #326765;   font-size: 1.5rem;   padding: 10px;   border: 0px;   box-shadow: black 5px 8px 5px; } 
.incorrect_char {   color: red;   text-decoration: underline; } 
.correct_char {   color: darkgreen; }

HTML佈局和CSS樣式的結果如下所示:

遊戲的主要邏輯:遊戲的主要邏輯在JavaScript文件中定義。有幾個功能可以一起運行遊戲。

步驟1:選擇所有元素並定義變量

首先使用querySelector()方法選擇HTML佈局中的必需元素。爲它們分配了變量名,以便可以輕鬆訪問和修改它們。開頭還將定義在整個程序中將要訪問的其他變量。

// define the time limit let TIME_LIMIT = 60; 
// define quotes to be used let quotes_array = [   "Push yourself, because no one else is going to do it for you.",   "Failure is the condiment that gives success its flavor.",   "Wake up with determination. Go to bed with satisfaction.",   "It's going to be hard, but hard does not mean impossible.",   "Learning never exhausts the mind.",   "The only way to do great work is to love what you do."]; 
// selecting required elements let timer_text = document.querySelector(".curr_time"); let accuracy_text = document.querySelector(".curr_accuracy"); let error_text = document.querySelector(".curr_errors"); let cpm_text = document.querySelector(".curr_cpm"); let wpm_text = document.querySelector(".curr_wpm"); let quote_text = document.querySelector(".quote"); let input_area = document.querySelector(".input_area"); let restart_btn = document.querySelector(".restart_btn"); let cpm_group = document.querySelector(".cpm"); let wpm_group = document.querySelector(".wpm"); let error_group = document.querySelector(".errors"); let accuracy_group = document.querySelector(".accuracy"); 
let timeLeft = TIME_LIMIT; let timeElapsed = 0; let total_errors = 0; let errors = 0; let accuracy = 0; let characterTyped = 0; let current_quote = ""; let quoteNo = 0; let timer = null;

步驟2:準備要顯示的文本

updateQuote()定義了一個處理以下內容的函數:

  • 獲取文本
    引號已用作必須輸入文本遊戲。每個引用都是從預定義數組中一個接一個地獲取的。變量會跟蹤當前的報價索引,並在每次請求新的報價時對其進行遞增。

  • 將字符拆分爲元素
    文本中的每個字符都分爲一系列<span>元素。這使得可以根據用戶是否正確鍵入了每個字符來分別更改其顏色。這些元素被附加到變量中quote_text。

function updateQuote() {   quote_text.textContent = null;   current_quote = quotes_array[quoteNo]; 
  // separate each character and make an element    // out of each of them to individually style them   current_quote.split('').forEach(char => {     const charSpan = document.createElement('span')     charSpan.innerText = char     quote_text.appendChild(charSpan)   }) 
  // roll over to the first quote   if (quoteNo < quotes_array.length - 1)     quoteNo++;   else    quoteNo = 0; }

步驟3:由用戶獲取當前輸入的文本

processCurrentText()定義了一個函數,只要用戶在輸入框中輸入或更改任何內容,就會調用該函數。因此,它與oninput輸入框的事件處理程序一起使用。此函數處理以下事情:

  • 獲取輸入框的當前值輸入區域value屬性用於獲取用戶輸入的當前文本。這被拆分爲一個字符數組以與報價文本進行比較。這存儲在中curr_input_array

  • 爲引用文本的字符着色,根據所輸入引用的字符是否正確,將其顯示爲“紅色”或“綠色”。這是通過選擇我們之前創建的報價的span元素並循環遍歷它們來完成的。然後,元素將根據是否與鍵入的文本匹配來應用上面創建的類。

  • 計算錯誤和準確性
    每次用戶在輸入過程中輸入錯誤時,errors變量都會遞增。這用於通過將正確鍵入的字符數除以用戶鍵入的字符總數來計算精度值。

  • 移至下一個引號
    當輸入文本的長度與引號文本長度匹配時,將updateQuote()調用該函數,該函數將更改引號並清除輸入區域。總錯誤數也將更新以用於下一個報價。

function processCurrentText() { 
  // get current input text and split it   curr_input = input_area.value;   curr_input_array = curr_input.split(''); 
  // increment total characters typed   characterTyped++; 
  errors = 0; 
  quoteSpanArray = quote_text.querySelectorAll('span');   quoteSpanArray.forEach((char, index) => {     let typedChar = curr_input_array[index] 
    // character not currently typed     if (typedChar == null) {       char.classList.remove('correct_char');       char.classList.remove('incorrect_char'); 
      // correct character     } else if (typedChar === char.innerText) {       char.classList.add('correct_char');       char.classList.remove('incorrect_char'); 
      // incorrect character     } else {       char.classList.add('incorrect_char');       char.classList.remove('correct_char'); 
      // increment number of errors       errors++;     }   }); 
  // display the number of errors   error_text.textContent = total_errors + errors; 
  // update accuracy text   let correctCharacters = (characterTyped - (total_errors + errors));   let accuracyVal = ((correctCharacters / characterTyped) * 100);   accuracy_text.textContent = Math.round(accuracyVal); 
  // if current text is completely typed   // irrespective of errors   if (curr_input.length == current_quote.length) {     updateQuote(); 
    // update total errors     total_errors += errors; 
    // clear the input area     input_area.value = "";   } }

步驟4:開始新遊戲

startGame()定義了一個函數,當用戶將焦點放在輸入框上時將調用該函數。因此,它與onfocus輸入框的事件處理程序一起使用。此函數處理以下事情:

  • 重置所有值
    在開始新遊戲之前,所有值都將重置爲其默認值。我們創建一個名爲的不同函數resetValues()來處理此問題。

  • 更新文本
    準備新的文本並通過調用該updateQuote()函數顯示它。

  • 創建一個新計時器
    計時器會跟蹤剩餘的秒數並將其顯示給用戶。它是使用setInterval()重複調用updateTimer()下面定義的函數的方法創建的。在創建新計時器之前,使用清除先前的計時器實例clearInterval()。

function startGame() { 
  resetValues();   updateQuote(); 
  // clear old and start a new timer   clearInterval(timer);   timer = setInterval(updateTimer, 1000); } 
function resetValues() {   timeLeft = TIME_LIMIT;   timeElapsed = 0;   errors = 0;   total_errors = 0;   accuracy = 0;   characterTyped = 0;   quoteNo = 0;   input_area.disabled = false; 
  input_area.value = "";   quote_text.textContent = 'Click on the area below to start the game.';   accuracy_text.textContent = 100;   timer_text.textContent = timeLeft + 's';   error_text.textContent = 0;   restart_btn.style.display = "none";   cpm_group.style.display = "none";   wpm_group.style.display = "none"; }

步驟5:更新計時器

updateTimer()定義了一個函數,該函數將每秒調用一次以跟蹤時間。此函數處理以下事情:

  • 更新時間值會更新
    所有跟蹤時間的變量。該timeLeft值減小,該timeElapsed值增大,並且計時器文本更新爲當前剩餘時間。

  • 完成遊戲
    達到時間限制時將觸發此部分。它調用finishGame()下面定義的函數,從而完成遊戲。

function updateTimer() {   if (timeLeft > 0) {     // decrease the current time left     timeLeft--;       // increase the time elapsed     timeElapsed++;       // update the timer text     timer_text.textContent = timeLeft + "s";   }   else {     // finish the game     finishGame();   } } 

步驟6:整理遊戲

finishGame()定義了一個功能,當必須完成遊戲時將調用該功能。此函數處理以下事情:

  • 刪除計時器
    之前創建的計時器實例將被刪除。

  • 顯示重新啓動遊戲的文本和按鈕
    顯示給用戶的引用文本將更改爲表示遊戲結束的文本。通過將顯示屬性設置爲“阻止”,還可以顯示“重新啓動”按鈕。

  • 計算當前會話的CPM和WPM

  1. 每分鐘字符數(CPM)通過將鍵入的字符總數除以經過的時間,然後將結果乘以60來計算。四捨五入以防止小數點。

  2. 每分鐘字數(WPM)的計算方法是將CPM除以5,然後將結果乘以60。5表示每個字的平均字符數。四捨五入以防止出現小數點。

function finishGame() {   // stop the timer   clearInterval(timer); 
  // disable the input area   input_area.disabled = true; 
  // show finishing text   quote_text.textContent = "Click on restart to start a new game."; 
  // display restart button   restart_btn.style.display = "block"; 
  // calculate cpm and wpm   cpm = Math.round(((characterTyped / timeElapsed) * 60));   wpm = Math.round((((characterTyped / 5) / timeElapsed) * 60)); 
  // update cpm and wpm text   cpm_text.textContent = cpm;   wpm_text.textContent = wpm; 
  // display the cpm and wpm   cpm_group.style.display = "block";   wpm_group.style.display = "block"; }

最後效果

現在可以在任何瀏覽器中玩遊戲了,截圖如下:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章