-
Notifications
You must be signed in to change notification settings - Fork 415
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2354 from eabhi-me/main
Add a new project of basic typing game
- Loading branch information
Showing
3 changed files
with
198 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<!DOCTYPE html> | ||
<!-- inside index.html --> | ||
<html> | ||
<head> | ||
<title>Typing game</title> | ||
<link rel="stylesheet" href="style.css"> | ||
</head> | ||
<body> | ||
<h1>Typing game!</h1> | ||
<p>Practice your typing skills with a quote from Sherlock Holmes. Click <b>start</b> to begin!</p> | ||
<p id="best-score"></p> | ||
<p id="least-score"></p> | ||
<p id="quote"></p> <!-- This will display our quote --> | ||
<p id="message"></p> <!-- This will display any status messages --> | ||
|
||
<div> | ||
<input type="text" aria-label="current word" id="typed-value" /> <!-- The textbox for typing --> | ||
<button type="button" id="start">Start</button> <!-- To start the game --> | ||
</div> | ||
<script src="script.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
// all of our quotes | ||
const quotes = [ | ||
'When you have eliminated the impossible, whatever remains, however improbable, must be the truth.', | ||
'There is nothing more deceptive than an obvious fact.', | ||
'I ought to know by this time that when a fact appears to be opposed to a long train of deductions it invariably proves to be capable of bearing some other interpretation.', | ||
'I never make exceptions. An exception disproves the rule.', | ||
'What one man can invent another can discover.', | ||
'Nothing clears up a case so much as stating it to another person.', | ||
'Education never ends, Watson. It is a series of lessons, with the greatest for the last.', | ||
]; | ||
// store the list of words and the index of the word the player is currently typing | ||
let words = []; | ||
let wordIndex = 0; | ||
// the starting time | ||
let startTime = Date.now(); | ||
// page elements | ||
const quoteElement = document.getElementById('quote'); | ||
const messageElement = document.getElementById('message'); | ||
const typedValueElement = document.getElementById('typed-value'); | ||
typedValueElement.disabled = true; | ||
|
||
// Load scores from local storage | ||
let bestScore = localStorage.getItem("BestTime") || null; | ||
let leastScore = localStorage.getItem("LeastTime") || null; | ||
|
||
if (bestScore) { | ||
document.getElementById('best-score').innerText = `Best Score: ${bestScore} seconds`; | ||
} | ||
if (leastScore) { | ||
document.getElementById('least-score').innerText = `Least Time: ${leastScore} seconds`; | ||
} | ||
|
||
// at the end of script.js | ||
document.getElementById('start').addEventListener('click', () => { | ||
// get a quote | ||
const quoteIndex = Math.floor(Math.random() * quotes.length); | ||
const quote = quotes[quoteIndex]; | ||
// Put the quote into an array of words | ||
words = quote.split(' '); | ||
// reset the word index for tracking | ||
wordIndex = 0; | ||
|
||
// UI updates | ||
// Create an array of span elements so we can set a class | ||
const spanWords = words.map(word => `<span>${word} </span>`); | ||
// Convert into string and set as innerHTML on quote display | ||
quoteElement.innerHTML = spanWords.join(''); | ||
// Highlight the first word | ||
quoteElement.childNodes[0].className = 'highlight'; | ||
// Clear any prior messages | ||
messageElement.innerText = ''; | ||
|
||
// Setup the textbox | ||
typedValueElement.value = ''; | ||
typedValueElement.disabled = false; // Activate input | ||
typedValueElement.focus(); | ||
|
||
// Start the timer | ||
startTime = new Date().getTime(); | ||
}); | ||
|
||
// at the end of script.js | ||
typedValueElement.addEventListener('input', () => { | ||
// Get the current word | ||
const currentWord = words[wordIndex]; | ||
// get the current value | ||
const typedValue = typedValueElement.value; | ||
|
||
if (typedValue === currentWord && wordIndex === words.length - 1) { | ||
// end of sentence | ||
const elapsedTime = (new Date().getTime() - startTime) / 1000; | ||
const message = `CONGRATULATIONS! You finished in ${elapsedTime} seconds.`; | ||
messageElement.innerText = message; | ||
typedValueElement.disabled = true; | ||
|
||
// Check and update least and best scores | ||
if (!bestScore || elapsedTime < parseFloat(bestScore)) { | ||
bestScore = elapsedTime; | ||
localStorage.setItem("BestTime", bestScore); | ||
document.getElementById('best-score').innerText = `Best Score: ${bestScore} seconds`; | ||
} | ||
|
||
if (!leastScore || elapsedTime > parseFloat(leastScore)) { | ||
leastScore = elapsedTime; | ||
localStorage.setItem("LeastTime", leastScore); | ||
document.getElementById('least-score').innerText = `Least Time: ${leastScore} seconds`; | ||
} | ||
|
||
} else if (typedValue.endsWith(' ') && typedValue.trim() === currentWord) { | ||
// end of word | ||
typedValueElement.value = ''; | ||
wordIndex++; | ||
// reset the class name for all elements in quote | ||
for (const wordElement of quoteElement.childNodes) { | ||
wordElement.className = ''; | ||
} | ||
// highlight the new word | ||
quoteElement.childNodes[wordIndex].className = 'highlight'; | ||
} else if (currentWord.startsWith(typedValue)) { | ||
typedValueElement.className = ''; // Correct typing | ||
} else { | ||
typedValueElement.className = 'error'; // Error state | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* inside style.css */ | ||
/* inside style.css */ | ||
body { | ||
font-family: Arial, sans-serif; | ||
background-color: #f0f0f0; | ||
color: #333; | ||
margin: 0; | ||
padding: 0; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
justify-content: center; | ||
height: 100vh; | ||
} | ||
|
||
h1 { | ||
color: #4CAF50; | ||
margin-bottom: 20px; | ||
} | ||
|
||
p { | ||
font-size: 18px; | ||
margin: 10px 0; | ||
} | ||
|
||
#quote { | ||
font-size: 24px; | ||
font-style: italic; | ||
margin-bottom: 20px; | ||
} | ||
|
||
#message, #best-score { | ||
font-size: 20px; | ||
margin: 10px 0; | ||
} | ||
|
||
div { | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
} | ||
|
||
input[type="text"] { | ||
padding: 10px; | ||
font-size: 18px; | ||
border: 2px solid #ccc; | ||
border-radius: 5px; | ||
margin-bottom: 10px; | ||
width: 300px; | ||
} | ||
|
||
button { | ||
padding: 10px 20px; | ||
font-size: 18px; | ||
color: white; | ||
background-color: #4CAF50; | ||
border: none; | ||
border-radius: 5px; | ||
cursor: pointer; | ||
} | ||
|
||
button:hover { | ||
background-color: #45a049; | ||
} | ||
.highlight { | ||
background-color: yellow; | ||
} | ||
|
||
.error { | ||
background-color: lightcoral; | ||
border: red; | ||
} |