-
Notifications
You must be signed in to change notification settings - Fork 0
/
mocktus.js
211 lines (183 loc) · 8.04 KB
/
mocktus.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
console.log('##################################\nMO-MO-MOCKTUS! TALALALA LA LAAAAA!\n##################################\n\n');
console.log("Chargement du lexique, veuillez patienter...");
const fs = require('fs');
const srcFile = 'data/dict.txt'
let mots = [];
fs.readFile(srcFile, async (err, data) => {
if (err) throw err;
mots = data.toString().split(' ');
console.log("Lexique chargé. Démarrage...");
await run();
});
class GrilleDeMocktus {
constructor(selection) {
this.limiteEssais = 6; // nombre maximum de tentatives
// construction de la grille
//}else if(typeof selection === 'number' && selection){
if(selection && Number.isInteger(Number(selection))){
selection = Number(selection);
while (!mots.find(m => (m.length === selection))) {
let proposition = rl.question("Il n'y a pas de mot de cette taille dans notre dictionnaire, veuillez en proposer un autre:\n");
if (Number.isInteger(Number(proposition))) {
selection = Number(proposition);
}
}
const indices = this.getIndices(selection);
this.word2guess = mots[indices.startIndex + Math.floor(Math.random() * (indices.stopIndex - indices.startIndex))];
//console.log(this.word2guess);
console.log("Un mot de %s lettres a été choisi.", selection);
}else if(typeof selection === 'string' && selection) {
while (mots.find(m => m === selection)) {
let proposition = rl.question("Ce mot n'est pas dans notre dictionnaire, veuillez en proposer un autre:\n");
if (typeof proposition === 'string' && proposition) {
selection = proposition;
}
}
this.word2guess = GrilleDeMocktus.normalizeInput(selection);
console.log("Votre mot est validé.");
}else {
this.word2guess = mots[Math.floor(Math.random() * mots.length)];
console.log("Un mot a été choisi au hasard pour vous.");
}
// Sélectionne la sous-séquence de mots ordonnés qui a le même nombre de lettres et la même lettre de départ
const indices = this.getIndices(this.word2guess.length, this.word2guess[0]);
this.startIndex = indices.startIndex;
this.stopIndex = indices.stopIndex;
}
static normalizeInput(userInput){
return userInput.trim()
.normalize("NFD").replace(/\p{Diacritic}/gu, "") //accents removal: https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript
.replace(/[\u0152|\u0153]/g, "oe")
.toUpperCase();
}
async play() {
console.log('Je vous souhaite une bonne partie, on commence tout de suite.\n');
// Initialisation
const _this = this;
const ligneInitiale = this.word2guess[0] + '-'.repeat(this.word2guess.length - 1);
console.log(ligneInitiale)
for (let essai = 0; essai < this.limiteEssais;) {
let validInput = false;
let userInput;
while (!validInput) {
let tentative = rl.question("");
if ((typeof tentative == 'undefined') || !tentative) {
if(rl.keyInYN("Voulez-vous quitter la partie?"))
validInput = true;
}else{
tentative = GrilleDeMocktus.normalizeInput(tentative);
validInput = _this.isValid(tentative);
if (validInput) {
userInput = tentative;
essai += 1;
}
}
}
if (this.verify(userInput)){
console.log("\nFélicitations! Vous venez de trouver le bon mot!");
break;
}else if(essai === this.limiteEssais-1){
console.log("\nVous n'êtes pas parvenu à trouver le mot %s.\nPlus de chance la prochaine fois!",this.word2guess);
}
}
}
getIndices(taille,lettre){ //taille est obligatoire, sinon il n'y a pas de boundaries, lettre est une option
let startIndex = -1, stopIndex = -1,
inLengthRange = false, inLetterRange = false;
for(let i=0; i<mots.length; i++) {
const mot = mots[i];
if((mot.length === taille) && (!inLengthRange)){
inLengthRange = true;
if(!lettre) // s'il n'y a pas de test de lettre, c'est le startIndex
startIndex = i;
}
if(lettre && inLengthRange){
if((lettre === mot[0]) && !inLetterRange){ // test de première lettre
inLetterRange = true;
startIndex = i;
}
if((lettre !== mot[0]) && inLetterRange){ // test de sortie lettre
stopIndex = i;
break;
}
}
if((mot.length !== taille) && (inLengthRange)){ // test de sortie taille
stopIndex = i;
break;
}
// Effet de bord
if((i === mots.length-1) && (startIndex >= 0))
stopIndex = i;
}
return {
'startIndex': startIndex,
'stopIndex': stopIndex
};
}
isValid(word2test){
// test de taille
if(word2test.length < this.word2guess.length){
console.log("Ce mot est trop court.\nIl devrait faire %s lettres.",this.word2guess.length);
return false;
}else if(word2test.length > this.word2guess.length){
console.log("Ce mot est trop long.\nIl devrait faire %s lettres.", this.word2guess.length);
return false;
}
// test de première lettre
if(word2test[0] !== this.word2guess[0]){
console.log("Votre mot doit commencer par la lettre %s.",this.word2guess[0]);
return false;
}
// test de présence dans le lexique
if(!mots.slice(this.startIndex,this.stopIndex).find(mot => mot === word2test)){
console.log("Votre mot n'est pas présent dans le lexique");
return false;
}
// Sinon...
return true;
}
verify(userInput){
if((typeof userInput === 'undefined') || !userInput)
return false;
let buffMot = this.word2guess.split('');
let word2guessSplit = this.word2guess.split('');
let buffOut = new Array(this.word2guess.length);
let testValue = true;
// symbol definition
const symbolRouge = 'X', symbolJaune = '~', symbolVide ='-';
buffOut.fill(symbolVide);
userInput.split('').forEach((lettre,cle) => {
if(lettre === word2guessSplit[cle]){
buffMot[cle] = '';
buffOut[cle] = symbolRouge
}
});
userInput.split('').forEach((lettre,cle) => {
if(buffOut[cle] !== symbolRouge){
testValue = false;
const matchedLetterIndex = buffMot.findIndex(l => l === lettre);
if(matchedLetterIndex >= 0){
buffMot[matchedLetterIndex] = '';
buffOut[cle] = symbolJaune
}
}
});
console.log(buffOut.join(''));
return testValue;
}
}
const rl = require('readline-sync')
async function run() {
// Accueil de l'utilisateur
console.log("Bonjour, je suis votre hôte, Thierry Bot-Arrow !\nBienvenue dans cette partie de Mocktus!");
// Demande à l'utilisateur de configurer sa grille
let grilleDeMocktus;
let exitToken = false;
let selection = rl.question("Quelle grille voulez-vous? Entrez un de ces paramètres: [string=mot;nombre=taille;rien=random]\n");
grilleDeMocktus = new GrilleDeMocktus(selection);
console.log('Votre sélection vient de générer une nouvelle grille de Mocktus.', selection);
// Lance la partie de GrilleDeMocktus
grilleDeMocktus.play();
// Ajoute le score aux points
// Propose une nouvelle partie
}