Comment créer un clone de Wordle en JavaScript
Dans cet article, vous allez recréer le jeu de devinette Wordle. Cet article couvre la logique de base du jeu mais n’implémente pas le partage de vos résultats. L’article ne couvre pas non plus la fonctionnalité qui génère les statistiques du jeu.
Ce tutoriel est destiné aux développeurs frontaux débutants qui souhaitent créer un projet JavaScript amusant et simple.
Conditions préalables
Ce tutoriel suppose une compréhension de base de.. :
Comment construire le clone de Wordle
Voici les étapes à suivre pour créer le clone de Wordle :
- Configuration du projet
- Création du plateau de jeu
- Création du clavier à l’écran
- Accepter les entrées de l’utilisateur
- Ajout de notifications
- Faire en sorte que le clavier à l’écran génère des entrées
- Ajout d’une animation
Configuration du projet
Avant de construire le jeu, vous devez mettre en place certains composants. Tout d’abord, vous devez créer un dossier pour tout le code source de notre clone. Appelez ce dossier « build ».
Après avoir fait cela, configurez votre serveur de développement.
Serveur réel
Vous allez utiliser un serveur de développement appelé live-server. Cette étape est facultative, mais elle vous évite de devoir recharger la page après chaque modification du code source.
Installez live-server en tapant ce qui suit dans votre terminal :
npm install live-server
HTML Setup
Dans le build, créez un fichier HTML et nommez-le index.html. Mettez le code suivant dans ce fichier :
Clone de Wordle
Le code HTML crée un en-tête pour notre jeu et crée le conteneur pour le plateau de jeu.
Vous allez utiliser une bibliothèque JavaScript appelée Toastr pour les notifications dans le jeu et une bibliothèque CSS appelée Animate.css pour les animations du plateau.
Pour les inclure dans votre projet, ajoutez les liens suivants à l’en-tête de votre fichier index.html.
Ces liens récupèreront les CSS pour Animate.css et Toastr. Placez le code suivant dans index.html, juste avant la balise de fermeture body :
Ce code récupérera le JavaScript de Toastr et de jQuery (car Toastr en dépend).
Configuration du JavaScript
Votre JavaScript sera placé dans un fichier appelé script.js. Créez script.js, et placez-le dans build.
Placez ce code en haut de script.js :
importez { WORDS } de "./words.js" ;
const NUMBER_OF_GUESSES = 6 ;
let guessesRemaining = NUMBER_OF_GUESSES ;
let currentGuess = [] ;
let nextLetter = 0 ;
let rightGuessString = MOTS[Math.floor(Math.random() * MOTS.length)]
console.log(rightGuessString)
Cet extrait de code initialise les variables globales que nous utiliserons pour notre jeu et choisit un mot aléatoire dans le tableau WORDS
comme bonne réponse pour ce tour. Nous enregistrons également la bonne réponse dans la console, afin de déboguer notre code si nécessaire.
La liste des mots autorisés que nous utiliserons sera codée en dur et stockée dans un tableau dans le fichier words.js. Créez words.js, dans build, et copiez le JavaScript de ce lien dans ce fichier.
Words.js devrait ressembler à ceci :
Configuration du CSS
Nommez votre fichier CSS style.css. Style.css doit également être placé dans build.
h1 {
text-align : center ;
}
La seule configuration CSS dont nous avons besoin est un peu de code pour centrer le texte de notre en-tête
Mise en place de l’ensemble
Enfin, liez script.js en tant que module dans votre index.html, puis liez style.css.
À ce stade, votre index.html devrait ressembler à ceci :
Clone de Wordle
et votre structure de fichiers devrait ressembler à ceci :
Démarrez live-server en tapant ceci dans votre console :
construction du serveur en direct
C’est tout pour la configuration.
Comment créer le plateau de jeu
Vous allez créer le plateau de jeu en écrivant une fonction JavaScript. Appelons cette fonction initBoard
. Ajoutez ce code à votre fichier script.js :
function initBoard() {
let board = document.getElementById("game-board") ;
for (let i = 0 ; i < NUMBER_OF_GUESSES ; i++) {
let row = document.createElement("div")
row.className = "letter-row" (rangée de lettres)
for (let j = 0 ; j < 5 ; j++) {
let box = document.createElement("div")
box.className = "boîte aux lettres"
row.appendChild(box)
}
board.appendChild(row)
}
}
initBoard()
Que fait ce code ? initBoard
crée une ligne pour chaque réponse donnée à l’utilisateur et crée 5 cases pour chaque ligne. Il y a une case pour chaque lettre de la réponse, et la fonction les rend toutes enfants de la ligne.
initBoard
ajoute ensuite chaque ligne au conteneur du tableau. Chaque ligne reçoit la classe letter-row
, et chaque boîte reçoit la classe letter-box
.
Ensuite, vous allez styliser le tableau à l’aide de CSS. Placez le code suivant dans votre fichier style.css :
#game-board {
display : flex ;
align-items : center ;
flex-direction : column ;
}
.letter-box {
border : 2px solid gray ;
border-radius : 3px ;
margin : 2px ;
font-size : 2.5rem ;
font-weight : 700 ;
hauteur : 3rem ;
width : 3rem ;
display : flex ;
justify-content : center ;
align-items : center ;
text-transform : uppercase ;
}
.filled-box {
border : 2px solid black ;
}
.letter-row {
affichage : flex ;
}
Ce CSS fait plusieurs choses :
- centre les rangées du tableau horizontalement et verticalement
- définit une hauteur, une largeur et une bordure pour chaque case du tableau
- crée un aspect distinct pour une case remplie d’une lettre
A ce stade, lorsque vous chargez le fichier index.html dans votre navigateur, il devrait ressembler à ceci :
Comment créer le clavier à l’écran
La façon la plus simple de créer le clavier est d’utiliser le HTML. Ajoutez ce code à votre index.html, après le div du plateau de jeu :
Maintenant, donnez du style au balisage en ajoutant ce CSS à la fin de style.css :
#keyboard-cont {
margin : 1rem 0 ;
display : flex ;
flex-direction : column ;
align-items : center ;
}
#keyboard-cont div {
display : flex ;
}
.second-row {
margin : 0.5rem 0 ;
}
.keyboard-button {
font-size : 1rem ;
font-weight : 700 ;
padding : 0.5rem ;
margin : 0 2px ;
curseur : pointeur ;
text-transform : uppercase ;
}
Voilà à quoi devrait ressembler votre index.html dans le navigateur :
Comment accepter les entrées de l’utilisateur
La stratégie pour les entrées utilisateur est simple : lorsque le joueur appuie sur une touche du clavier, nous voulons placer cette touche au bon endroit sur le plateau. Pour ce faire, vous allez écouter l’événement keyup.
Lorsque le joueur appuie sur une touche, vous voulez savoir quelle était cette touche. Si la touche était une seule lettre, vous voulez la placer au bon endroit sur le tableau.
Pour savoir où se trouve le bon endroit sur le plateau, vous vérifiez le nombre de suppositions qu’il reste au joueur et le nombre de lettres qu’il a entrées jusqu’à présent.
Si la touche pressée était Entrée ou Retour arrière, vous vérifiez la réponse ou supprimez une lettre de la réponse actuelle. Toute autre touche est ignorée.
Ajoutez ce code à script.js :
document.addEventListener("keyup", (e) => {
if (guessesRemaining === 0) {
return
}
let pressedKey = String(e.key)
si (pressedKey === "Backspace" && nextLetter !== 0) {
deleteLetter()
return
}
if (pressedKey === "Enter") {
checkGuess()
return
}
let found = pressedKey.match(/[a-z]/gi)
if (!found || found.length > 1) {
return
} else {
insertLetter(pressedKey)
}
})
Le code utilise une expression régulière pour vérifier que la touche sur laquelle nous avons appuyé était une touche alphabétique représentant une seule lettre. Si le nom de la touche ne comporte aucune lettre (il s’agissait d’un chiffre), ou s’il comporte plusieurs lettres (Shift, Tab), nous ignorons l’événement. Sinon, nous insérons la lettre dans le tableau.
insertLetter
Définissons la fonction insertLetter
. Elle ressemble à ceci :
fonction insertLetter (pressedKey) {
if (nextLetter === 5) {
return
}
pressedKey = pressedKey.toLowerCase()
let row = document.getElementsByClassName("letter-row")[6 - guessesRemaining]
let box = row.children[nextLetter]
box.textContent = pressedKey
box.classList.add("filled-box")
currentGuess.push(pressedKey)
nextLetter += 1
}
insertLetter
vérifie qu’il y a encore de la place dans le guess pour cette lettre, trouve la ligne appropriée et place la lettre dans la boîte.
deleteLetter
deleteLetter
ressemble à ceci :
function deleteLetter () {
let row = document.getElementsByClassName("letter-row")[6 - guessesRemaining]
let box = row.children[nextLetter - 1]
box.textContent = ""
box.classList.remove("filled-box")
devinette actuelle.pop()
nextLetter -= 1
}
deleteLetter
récupère la bonne ligne, trouve la dernière case et la vide, puis réinitialise le compteur nextLetter.
checkGuess
La fonction checkGuess
ressemble à ceci :
function checkGuess () {
let row = document.getElementsByClassName("letter-row")[6 - guessesRemaining]
let guessString = ''
let rightGuess = Array.from(rightGuessString)
for (const val of currentGuess) {
guessString += val
}
si (guessString.length != 5) {
alert("Pas assez de lettres !")
retournez
}
if (!WORDS.includes(guessString)) {
alert("Le mot n'est pas dans la liste !")
return
}
for (let i = 0 ; i < 5 ; i++) {
let letterColor = ''
let box = row.children[i]
let letter = currentGuess[i]
let letterPosition = rightGuess.indexOf(currentGuess[i])
// La lettre est-elle dans la bonne position ?
if (letterPosition === -1) {
letterColor = 'grey' (gris)
} else {
// maintenant, la lettre est définitivement dans le mot
// si l'indice de la lettre et l'indice de la bonne estimation sont les mêmes
// la lettre est dans la bonne position
if (currentGuess[i] === rightGuess[i]) {
// coloration verte
letterColor = 'green' (couleur de la lettre)
} else {
// teinte jaune de la boîte
letterColor = 'yellow' (couleur de la lettre)
}
rightGuess[letterPosition] = "#"
}
let delay = 250 * i
setTimeout(()=> {
//d'ombrager la boîte
box.style.backgroundColor = letterColor
shadeKeyBoard(lettre, letterColor)
}, delay)
}
si (guessString === rightGuessString) {
alert("Vous avez deviné juste ! La partie est terminée !")
reste des réponses = 0
retournez à
} else {
guessesRemaining -= 1 ;
devin actuel = [] ;
lettre suivante = 0 ;
si (reste des réponses === 0) {
alert("Vous n'avez plus d'indices, la partie est terminée !")
alert(`Le bon mot était : "${rightGuessString}"`)
}
}
}
checkGuess
est assez longue, alors décomposons-la. Elle fait plusieurs choses :
- Assure-toi que le mot à deviner comporte 5 lettres
- Vérifie que le mot deviné est une liste valide
- Vérifie chaque lettre du mot et les nuance
- Indique à l’utilisateur la fin du jeu
checkGuess
utilise un algorithme simple pour décider de la couleur à donner à chaque lettre :
- Vérifie si la lettre se trouve dans le bon mot
- Si la lettre ne se trouve pas dans le mot, la lettre est grisée
- Si la lettre est dans le mot, vérifiez si elle est dans la bonne position
- Si la lettre est dans la bonne position, elle devient verte
- Sinon, coloration en jaune
checkGuess
utilise une fonction shadeKeyboard
pour colorer les touches du clavier à l’écran, mais elle n’est pas encore définie. Faisons-le maintenant.
shadeKeyboard
function shadeKeyBoard(letter, color) {
for (const elem of document.getElementsByClassName("keyboard-button")) {
if (elem.textContent === lettre) {
let oldColor = elem.style.backgroundColor
if (oldColor === 'green') {
return
}
if (oldColor === 'yellow' && color !== 'green') {
return
}
elem.style.backgroundColor = couleur
pause
}
}
}
shadeKeyBoard
reçoit la lettre du clavier à l’écran que nous voulons colorer et la couleur que nous voulons lui donner. Voici l’algorithme :
- Trouver la clé qui correspond à la lettre donnée
- Si la clé est déjà verte, ne faites rien
- Si la clé est actuellement jaune, ne lui permettez que de devenir verte
- Sinon, nuance la clé passée à la fonction
Comment ajouter des notifications
Ensuite, vous allez remplacer les alertes JavaScript dans checkGuess
par des toasts, en utilisant Toastr.
Passez en revue checkGuess
, et remplacez toutes les alertes qui informent l’utilisateur d’une erreur par des appels à toastr .error()
.
L’alerte qui informe l’utilisateur d’une bonne réponse doit être remplacée par toastr.success()
, et l’alerte qui informe l’utilisateur de la bonne réponse doit être remplacée par toastr.info()
.
Voici à quoi devrait ressembler checkGuess une fois que vous aurez terminé :
function checkGuess () {
let row = document.getElementsByClassName("letter-row")[6 - guessesRemaining]
let guessString = ''
let rightGuess = Array.from(rightGuessString)
for (const val of currentGuess) {
guessString += val
}
si (guessString.length != 5) {
toastr.error("Pas assez de lettres !")
return
}
if (!WORDS.includes(guessString)) {
toastr.error("Le mot n'est pas dans la liste !")
return
}
for (let i = 0 ; i < 5 ; i++) {
let letterColor = ''
let box = row.children[i]
let letter = currentGuess[i]
let letterPosition = rightGuess.indexOf(currentGuess[i])
// la lettre est-elle dans la bonne position ?
if (letterPosition === -1) {
letterColor = 'grey' (gris)
} else {
// maintenant, la lettre est définitivement dans le mot
// si l'indice de la lettre et l'indice de la bonne estimation sont les mêmes
// la lettre est dans la bonne position
if (currentGuess[i] === rightGuess[i]) {
// coloration verte
letterColor = 'green' (couleur de la lettre)
} else {
// teinte jaune de la boîte
letterColor = 'yellow' (couleur de la lettre)
}
rightGuess[letterPosition] = "#"
}
let delay = 250 * i
setTimeout(()=> {
//d'ombrager la boîte
box.style.backgroundColor = letterColor
shadeKeyBoard(lettre, letterColor)
}, delay)
}
si (guessString === rightGuessString) {
toastr.success("Vous avez deviné juste ! La partie est terminée !")
guessRemaining = 0
retournez à
} else {
guessesRemaining -= 1 ;
currentGuess = [] ;
lettre suivante = 0 ;
if (guessesRemaining === 0) {
toastr.error("Vous n'avez plus de mots à deviner, la partie est terminée")
toastr.info(`Le bon mot était : "${rightGuessString}"`)
}
}
}
Comment faire en sorte que le clavier à l’écran génère des entrées ?
Pour faire fonctionner votre clavier à l’écran, il vous suffit d’envoyer un événement key up chaque fois que vous cliquez sur une touche de votre clavier à l’écran. Pour ce faire, ajoutez ce code à script.js :
document.getElementById("clavier-cont").addEventListener("click", (e) => {
const target = e.target
if (!target.classList.contains("keyboard-button")) {
return
}
let key = target.textContent
if (key === "Del") {
key = "Backspace" (retour arrière)
}
document.dispatchEvent(new KeyboardEvent("keyup", {'key' : key}))
})
Cette fonction est à l’écoute d’un clic sur le conteneur du clavier ou sur l’un de ses enfants (les boutons). Si l’élément cliqué n’est pas un bouton, nous quittons la fonction. Sinon, nous envoyons un événement key up correspondant à la touche cliquée.
Comment ajouter une animation
Nous avons déjà installé animate.css, alors écrivons maintenant une fonction JavaScript pour l’utiliser.
const animateCSS = (element, animation, prefix = 'animate__') =>
// Nous créons une Promise et la retournons
new Promise((resolve, reject) => {
const animationName = `${prefix}${animation}` ;
// const node = document.querySelector(element) ;
const node = element
node.style.setProperty('--animate-duration', '0.3s') ;
node.classList.add(`${prefix}animated`, animationName) ;
// Lorsque l'animation se termine, nous nettoyons les classes et résolvons la Promise
function handleAnimationEnd(event) {
event.stopPropagation() ;
node.classList.remove(`${prefix}animated`, animationName) ;
resolve('Animation terminée') ;
}
node.addEventListener('animationend', handleAnimationEnd, {once : true}) ;
}) ;
Cette fonction provient de la page d’accueil d’Animate.css. Elle applique des classes à la cible de l’animation pour déclencher une animation, et lorsque l’animation se termine, elle supprime les classes qu’elle a ajoutées.
La fonction renvoie une promesse pour vous permettre d’effectuer des actions qui ne doivent être exécutées qu’après la fin de l’animation, mais vous n’aurez pas besoin de mettre cela en œuvre dans ce tutoriel.
Maintenant que nous disposons d’une fonction permettant d’animer n’importe quel élément, appliquons-la. Revenez à notre fonction insertLetter
et ajoutez la ligne suivante avant de remplacer le textContent
de box
:
animateCSS(box, "pulse")
Voici à quoi insertLetter
devrait ressembler maintenant :
function insertLetter (pressedKey) {
if (nextLetter === 5) {
return
}
pressedKey = pressedKey.toLowerCase()
let row = document.getElementsByClassName("letter-row")[6 - guessesRemaining]
let box = row.children[nextLetter]
animateCSS(box, "pulse")
box.textContent = pressedKey
box.classList.add("filled-box")
currentGuess.push(pressedKey)
nextLetter += 1
}
Le code indique à insertLetter
de pulser rapidement chaque case, juste avant de la remplir avec une lettre.
Ensuite, vous voulez animer chaque lettre d’une proposition pendant que vous la vérifiez.
Revenez en arrière et modifiez checkGuess
, comme suit :
let delay = 250 * i
setTimeout(()=> {
//flip box
animateCSS(boîte, 'flipInX')
//obscurcir la boîte
box.style.backgroundColor = letterColor
ombrageKeyBoard(lettre, lettreCouleur)
}, delay)
Ce code ajoute une animation pour retourner chaque case verticalement, juste avant de changer la couleur.
Conclusion
Ce tutoriel est terminé. Vous venez de construire un clone de Wordle, et j’espère que vous vous êtes amusé en chemin. Vous pouvez trouver le code complet sur le dépôt GitHub de ce projet.
Laisser un commentaire