/// <summary> /// change les lettres choisies par le joueur /// </summary> /// <param name="p">joueur concerné</param> /// <param name="nbLetterChanges">nombre de lettres à changer</param> public static void changeLetter(ref Structures.player p, int nbLetterChanges) { bool fin = false; while (!fin) { //changement de 7 lettres donc nouveau tirage aléatoire if (nbLetterChanges == 7) { Random rnd = new Random(); for (int j = 0; j < 7; j++) { int rdm = rnd.Next(102); p.player_letters[j] = Structures.game_letters[rdm]; } fin = true; } else { for (int i = 0; i < nbLetterChanges; i++) { //choix de la lettre Console.WriteLine("\nTapez le numéro (de 1 à 7) de la " + (i + 1) + "{0} lettre que vous voulez changer.\n Exemple : A,B,C,D,E,F,G lettre n°1 = A et lettre n°7 = G", (i + 1 != 1 ? "ème" : "ère")); ; int indiceLetter; bool convertedIndLetter = int.TryParse(Console.ReadLine(), out indiceLetter); while (indiceLetter < 1 || indiceLetter > 7 || !convertedIndLetter) { Console.WriteLine(" -----> Votre choix de numéro n'est pas valide ! <------"); Console.WriteLine("\nTapez le numéro (de 1 à 7) de la " + (i + 1) + "{0} lettre que vous voulez changer.\n Exemple : A,B,C,D,E,F,G lettre n°1 = A et lettre n°7 = G", (i+1 != 1 ? "ème" : "ère")); ; convertedIndLetter = int.TryParse(Console.ReadLine(), out indiceLetter); } //changement de la lettre concernée for (int j = 1; j < p.player_letters.Length+1; j++) { if (indiceLetter == j) { Random rnd = new Random(); int alea = rnd.Next(102); p.player_letters[j-1] = Structures.game_letters[alea]; } } fin = true; } } } }
/// <summary> /// ajoute un mot passe en parametre dans la grille /// </summary> /// <param name="Grille">grille de jeu</param> /// <param name="motaAjouter"> mot a ajouter à la grille</param> /// <param name="longueurMot"> longueur du mot</param> /// <param name="position"> indique si le mot devra etre pose horizontalement (1) ou verticalement (0)</param> /// <param name="positionInitialLigne"> ligne initiale</param> /// <param name="positionInitialColonne"> colonne initiale</param> /// <returns>0 si tout s'est bien déroulé</returns> public static int addWordGrille(Structures.box[,] Grille, char [] motaAjouter, int longueurMot, bool position, int positionInitialLigne, int positionInitialColonne) { int iTmp; int i = 0; if (position) { for (iTmp = positionInitialColonne; iTmp < positionInitialColonne + longueurMot; iTmp++) { Grille[positionInitialLigne, iTmp].tok.letter = motaAjouter[i]; Grille[positionInitialLigne, iTmp].tok.value = Letters.findValue(motaAjouter[i]); i = i + 1; } } else { for (iTmp = positionInitialLigne; iTmp < positionInitialLigne + longueurMot; iTmp++) { Grille[iTmp, positionInitialColonne].tok.letter = motaAjouter[i]; Grille[iTmp, positionInitialColonne].tok.value = Letters.findValue(motaAjouter[i]); i = i + 1; } } return 0; }
/// <summary> /// affiche la grille et les caractères de celle ci (a-z, A-Z, ?) /// </summary> /// <param name="grille">grille de jeu</param> public static void afficherGrille(Structures.box[,] grille) { Console.WriteLine(" _______________\n"); Console.WriteLine(" > S C R A B B L E <"); Console.WriteLine(" _______________\n"); Console.WriteLine(" 1 1 1 1 1"); Console.WriteLine(" 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4"); for (int i = 0; i < 15; i++) { Console.WriteLine(" +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); for (int j = 0; j < 15; j++) { if (j == 0) { Console.Write(" "); } char tmp = ' '; if (grille[i, j].tok.value != 0 && char.ToUpper(grille[i, j].tok.letter) >= 'A' && char.ToUpper(grille[i, j].tok.letter) <= 'Z' || grille[i, j].tok.letter == '?') { tmp = grille[i, j].tok.letter; } Console.Write("|"); if (grille[i, j].bonus == 1) { Console.BackgroundColor = ConsoleColor.Magenta; } if (grille[i, j].bonus == 2) { Console.BackgroundColor = ConsoleColor.Red; } if (grille[i, j].bonus == 3) { Console.BackgroundColor = ConsoleColor.DarkCyan; } if (grille[i, j].bonus == 4) { Console.BackgroundColor = ConsoleColor.Blue; } Console.Write(tmp); Console.BackgroundColor = ConsoleColor.Black; } if ((i != 2) && (i != 3) && (i != 4) && (i != 5) && (i !=8) && (i !=9) && (i!=10) && (i!=11)) // Fin de ligne sans légende { Console.Write("| " + i + "\n"); } if (i == 2) // Légende mot compte triple { Console.Write("| " + i + " "); Console.BackgroundColor = ConsoleColor.Red; Console.Write(" "); Console.BackgroundColor = ConsoleColor.Black; Console.Write(" : Mot compte triple \n"); } if (i == 5) // Légende mot compte double { Console.Write("| " + i + " "); Console.BackgroundColor = ConsoleColor.Magenta; Console.Write(" "); Console.BackgroundColor = ConsoleColor.Black; Console.Write(" : Mot compte double \n"); } if (i == 4) // Légende lettre compte triple { Console.Write("| " + i + " "); Console.BackgroundColor = ConsoleColor.Blue; Console.Write(" "); Console.BackgroundColor = ConsoleColor.Black; Console.Write(" : Lettre compte triple \n"); } if (i == 3) // Légende lettre compte double { Console.Write("| " + i + " "); Console.BackgroundColor = ConsoleColor.DarkCyan; Console.Write(" "); Console.BackgroundColor = ConsoleColor.Black; Console.Write(" : Lettre compte double \n"); } if (i == 8 || i==9|| i==10 || i==11) // Affichage du score { Console.Write("| " + i); if (Structures.game_players[i-8].score >= 0 && Structures.game_players[i-8].nom!=null) { if (i == 8 || i == 9) { Console.Write(" "); } Console.Write(" Score de " + Structures.game_players[i-8].nom + " : " + Structures.game_players[i-8].score); } Console.Write("\n"); } } Console.WriteLine(" +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"); }
/// <summary> /// initialise la grille /// </summary> /// <param name="grille">grille de jeu</param> public static void initialiserGrille(Structures.box[,] grille) { Structures.box tmpBox = new Structures.box(); Structures.token tmpTok = new Structures.token(); tmpTok.letter = 'a'; tmpTok.value = 0; tmpBox.bonus = 0; tmpBox.tok = tmpTok; for (int i = 0; i < 15; i++) { for (int j = 0; j < 15; j++) { grille[i, j] = tmpBox; } } // création des bonus //RED for (int i = 0; i < 15; i += 7) { for (int j = 0; j < 15; j += 7) { grille[i, j].bonus = 2; } } //MAG for (int i = 1; i < 5; i++) { grille[i, i].bonus = 1; grille[14 - i, 14 - i].bonus = 1; grille[i, 14 - i].bonus = 1; grille[14 - i, i].bonus = 1; } grille[7, 7].bonus = 1; //CYN for (int i = 0; i < Structures.nbCyans; i++) { grille[Structures.cyanBoxes[i, 0], Structures.cyanBoxes[i, 1]].bonus = 3; } //BLUE for (int i = 0; i < Structures.nbBlues; i++) { grille[Structures.blueBoxes[i, 0], Structures.blueBoxes[i, 1]].bonus = 4; } }
/// <summary> /// determine le premier mot qui donnera au joueur concerné le meilleur score (utilisé pour l'IA et le solveur) /// </summary> /// <param name="Grille">grille de jeu</param> /// <param name="hand">main du joueur</param> /// <param name="Word">tableau de wordScrabble</param> /// <param name="n">nombre de mots proposant le meilleur score</param> /// <param name="scores">tableau des scores pour chaque mot</param> public static void findBestFirstWord(Structures.box[,] Grille, char[] hand, Structures.wordScrabble[] Word, int n, int[] scores) { for (int i = 0; i < n; i++) scores[i] = 0; char[,] Words = new char[20000, 15]; int[] sizes = new int[20000]; int u = searchFirstWord(hand, Words, sizes); for (int i = 0; i < u; i++) { Structures.wordScrabble tmp1; tmp1.letters = new char[15]; for (int j = 0; j < sizes[i]; j++) { tmp1.letters[j] = Words[i, j]; } tmp1.position = true; tmp1.l = sizes[i]; tmp1.x = 7; for (int j = 0; j < sizes[i]; j++) { tmp1.y = 7 - j; int v = Algorythms.valueOfWord(tmp1, Grille); for (int k = 0; k < n; k++) { if (scores[k] < v) { Structures.wordScrabble wordNow; Structures.wordScrabble wordNext; int scoreNow; int scoreNext; wordNow = tmp1; scoreNow = v; for (int h = k; h < n; h++) { wordNext = Word[h]; scoreNext = scores[h]; Word[h] = wordNow; scores[h] = scoreNow; wordNow = wordNext; scoreNow = scoreNext; } break; } } } } }
/// <summary> /// ajoute des lettres du sac (game_letters) non utilisées au chevalet du joueur concerné /// </summary> /// <param name="p"> joueur concerné</param> /// <param name="Grille"> grille du jeu</param> /// <param name="Word"> mot joué par le joueur (pour ne pas piocher les lettres joués lors du tour)</param> /// <returns>retourne 1 s'il reste des lettres dans le sac (game_letters)</returns> public static int takeLetter(ref Structures.player p, Structures.box [,] Grille,Structures.wordScrabble Word) { bool [] used = new bool [7]; int posX=0; int posY=0; //on vérifie les lettres utilisés par le joueur pour ce tour for(int i=0;i<Word.l;i++) { if(Word.position) { posY=i; } else { posX=i; } if(Grille[Word.x + posX,Word.y + posY].tok.value == 0) { bool ok=false; for(int j=0;j<7;j++) { if(p.player_letters[j] == Word.letters[i] && !used[j]) { used[j]=true; ok=true; break; } } if(!ok) { for(int j=0;j<7;j++) { if(p.player_letters[j] == '?') { used[j] = true; } } } } } char [] newLetters = new char [7]; int notUsed=0; // on vérifie les lettres du chevalet non utilisées ce tour for(int i=0;i<7;i++) { if(!used[i]) { newLetters[notUsed] = p.player_letters[i]; notUsed++; } } //on donne des lettres non utilisés du sac (game_letters) for(int i=notUsed;i<7;i++) { if (Structures.letterUsed < 101) { newLetters[i] = Structures.game_letters[Structures.letterUsed]; Structures.letterUsed++; } if(Structures.letterUsed==101) return 0;//il n'en reste plus } for(int i=0;i<7;i++) { p.player_letters[i] = newLetters[i]; } return 1;//il reste des lettres dans le sac }
/// <summary> /// retourne le nombre de mots possibles à jouer sur une ligne /// </summary> /// <param name="line">ligne concernée</param> /// <param name="letters">lettres du joueurs</param> /// <param name="sizes">tableau des tailles valables pour chaque mot</param> /// <param name="nbSizes">nombre de tailles valables</param> /// <param name="result">tableau de wordScrabble</param> /// <param name="position">position verticale ou horizontale</param> /// <param name="x">absscisse</param> /// <returns>nombre de mots possibles sur la ligne</returns> public static int findWordsWithLine(Structures.box [] line, char [] letters, valableSize [] sizes,int nbSizes, Structures.wordScrabble [] result,bool position, int x) { int nbResult=0; int nbJoker=0; for(int letter=0;letter<7;letter++) { if(letters[letter] == '?') { nbJoker++; } } for(int i = 0;i<nbSizes;i++) { for(int j=0;j<Structures.nbWords;j++) { bool [] tabJok = new bool [15]; int jok=nbJoker; if(sizes[i].max - sizes[i].min >= Structures.sizeWords[j]) { //calcul correspondance des lettres bool matchword=true; bool [] used = new bool [7]; bool [] used2 = new bool [15]; for(int k=0;k<Structures.sizeWords[j];k++) { bool found=false; for(int letter=0;letter<7;letter++) { if(letters[letter] == Structures.dictionary[j,k] && !used[letter] && !found) { used[letter]=true; found=true; } } if(!found) { for(int indice=sizes[i].min; indice < sizes[i].max+1;indice++) { if(line[indice].tok.value != 0 && line[indice].tok.letter == Structures.dictionary[j,k] && !used2[indice]) { found=true; used2[indice]=true; } } } if(!found && jok>0) { found=true; tabJok[k]=true; jok--; } if(!found){ matchword=false; break; } } if(matchword) { int firstIndice=-1; int lastIndice = 0; for(int t=sizes[i].min;t <= sizes[i].max;t++) { if(line[t].tok.value != 0) { if(firstIndice==-1) firstIndice=t; lastIndice = t; } } if(Structures.sizeWords[j] >= lastIndice - firstIndice +1) { bool correspond = true; for(int diff=0;diff <= (sizes[i].max - sizes[i].min ) - Structures.sizeWords[j]+1;diff++) { int everPosed=0; for(int indiceMask=0;indiceMask < Structures.sizeWords[j];indiceMask++) { if(line[sizes[i].min+indiceMask+diff].tok.value != 0) everPosed++; if(line[sizes[i].min+indiceMask+diff].tok.value != 0 && char.ToUpper(line[sizes[i].min+indiceMask+diff].tok.letter) != Structures.dictionary[j,indiceMask]) { correspond =false; } } if(correspond && sizes[i].min + Structures.sizeWords[j] + diff- 1 >= lastIndice && everPosed != Structures.sizeWords[j] && everPosed>0) { Structures.wordScrabble tmp; tmp.letters = new char [15]; for(int t=0;t<Structures.sizeWords[j];t++) { if(tabJok[t]) { tmp.letters[t] = char.ToLower(Structures.dictionary[j,t]); } else tmp.letters[t] = Structures.dictionary[j,t]; } if(position) { tmp.x = x; tmp.y= diff+sizes[i].min; } else { tmp.y = x; tmp.x=diff+sizes[i].min; } tmp.l=Structures.sizeWords[j]; tmp.position = position; result[nbResult]=tmp; nbResult++; } } } } } } } return nbResult; }
/// <summary> /// calcule et retourne la valeur du mot passe en parametre dans la grille /// </summary> /// <param name="Word">mot passe en parametre</param> /// <param name="Grille">grille de jeu</param> /// <returns> valeur du mot</returns> public static int valueOfWord(Structures.wordScrabble Word, Structures.box [,] Grille) { int score=0; int multi=1; int posX=0; int posY=0; int valueLetter; int bonusPoints=0; int nbPosed=0; for(int i=0;i<Word.l;i++) { valueLetter = Letters.findValue(Word.letters[i]); if(valueLetter==-1) valueLetter=0; if(Word.position) { posY=i; } else { posX=i; } //calcul du mot lui-même if(Grille[Word.x + posX,Word.y + posY].tok.value == 0) { nbPosed++; switch (Grille[Word.x + posX,Word.y + posY].bonus) { case 1: multi*=2; break; case 2: multi*=3; break; case 3: valueLetter*=2; break; case 4: valueLetter*=3; break; } } score +=valueLetter; if(Grille[Word.x+ posX,Word.y + posY].tok.value == 0) { //calcul des mots autour int j=0,k=0; char [] w = new char [15]; int l=0; int s=0; int mul=1; //horizontale if(Word.position) { while(Word.x -(j+1) >= 0 && Grille[Word.x - (j+1),Word.y + posY].tok.value != 0) { valueLetter = Letters.findValue(Grille[Word.x - (j+1),Word.y + posY].tok.letter); if(valueLetter==-1) valueLetter=0; if(Grille[Word.x - (j+1),Word.y + posY].tok.value == 0) { switch (Grille[Word.x - (j+1),Word.y + posY].bonus) { case 1: mul*=2; break; case 2: mul*=3; break; case 3: valueLetter*=2; break; case 4: valueLetter*=3; break; } } s +=valueLetter; j++; } while(Word.x + (k+1) < 15 && Grille[Word.x + k+1,Word.y + posY].tok.value != 0) { valueLetter = Letters.findValue(Grille[Word.x + k+1,Word.y + posY].tok.letter); if(valueLetter==-1) valueLetter=0; if(Grille[Word.x + k+1,Word.y + posY].tok.value ==0) { switch (Grille[Word.x + k+1,Word.y + posY].bonus) { case 1: mul*=2; break; case 2: mul*=3; break; case 3: valueLetter*=2; break; case 4: valueLetter*=3; break; } } s +=valueLetter; k++; } for(int f = j;f>0;f--) { w[l] = char.ToUpper(Grille[Word.x - f,Word.y + posY].tok.letter); l++; } w[l] = char.ToUpper(Word.letters[i]); l++; for(int m=1;m<=k;m++) { w[l] = char.ToUpper(Grille[Word.x + m,Word.y + posY].tok.letter); l++; } if(wordExist(w,l) && l != 1) { score+=Letters.findValue(Word.letters[i]); score+=s; multi*=mul; } else if(l != 1) return -1; } //vertical else{ while(Word.y -(j+1) >= 0 && Grille[Word.x + posX,Word.y -(j+1)].tok.value != 0) { valueLetter = Letters.findValue(Grille[Word.x + posX,Word.y -(j+1)].tok.letter); if(valueLetter==-1) valueLetter=0; if(Grille[Word.x + posX,Word.y -(j+1)].tok.value == 0) { switch (Grille[Word.x + posX,Word.y -(j+1)].bonus) { case 1: mul*=2; break; case 2: mul*=3; break; case 3: valueLetter*=2; break; case 4: valueLetter*=3; break; } } s +=valueLetter; j++; } while(Word.y + (k+1) < 15 && Grille[Word.x + posX,Word.y + k+1].tok.value != 0) { valueLetter = Letters.findValue(Grille[Word.x + posX,Word.y + k+1].tok.letter); if(valueLetter==-1) valueLetter=0; if(Grille[Word.x + posX,Word.y + k+1].tok.value == 0) { switch (Grille[Word.x + posX,Word.y + k+1].bonus) { case 1: mul*=2; break; case 2: mul*=3; break; case 3: valueLetter*=2; break; case 4: valueLetter*=3; break; } } s+=valueLetter; k++; } for(int e=j;e>0;e--) { w[l] = Grille[Word.x +posX,Word.y - e].tok.letter; l++; } w[l] = Word.letters[i]; l++; for(int m=1;m<=k;m++) { w[l] = Grille[Word.x + posX,Word.y + m].tok.letter; l++; } if(wordExist(w,l) && l != 1) { if(w[0]=='E' && w[1] == 'Z' && w[2] == 'E' && l==3 && wordExist(w,3)) Console.WriteLine("ok"); score+=s; multi*=mul; } else if(l != 1) return -1; } } } if(nbPosed==7) bonusPoints=50; return score *multi + bonusPoints; }
/// <summary> /// retourne le nombre de mots possibles à jouer sur une ligne en prenant compte des cases vides et à travers un appel de la fonction findWordsWithLine /// </summary> /// <param name="line">ligne concernée</param> /// <param name="letters">lettres du joueurs</param> /// <param name="nb">postion verticale ou horizontale</param> /// <param name="position">abscisse</param> /// <param name="Words">tableau de wordScrabble</param> /// <returns>appel de la fonction findWordsWithLine</returns> public static int searchWordByLine(Structures.box [] line,char [] letters, bool nb, int position,Structures.wordScrabble [] Words) { int i=0; int newleft=0; int lastleft=0; valableSize [] sizes = new valableSize [100]; int l=0; while(i < 14) { if(line[i].tok.value != 0) { do { i++; } while(line[i].tok.value != 0 && i < 14); valableSize tmp; tmp.min = lastleft; newleft=i+1; int j = i; int nbBlank = 0; while(j < 14 && nbBlank <= 7) { bool letterExist=false; while(line[j].tok.value == 0 && j < 14 && nbBlank <= 7) { nbBlank++; j++; } if(line[j].tok.value !=0) { tmp.max = j-2; } else { tmp.max = j-1; } sizes[l]=tmp; l++; while (line[j].tok.value != 0 && j < 14) { j++; letterExist = true; } } lastleft=newleft; } i++; } return findWordsWithLine(line,letters,sizes,l,Words,nb,position); }
/// <summary> /// cherche les n meilleurs mots possibles à jouer suivant les lettres du joueurs et les lettres sur le plateau de jeu /// </summary> /// <param name="Grille">grille de jeu</param> /// <param name="letters">lettres du joueur</param> /// <param name="n">nombre de meilleurs mots à chercher</param> /// <param name="Words">tableau de wordScrabble</param> /// <param name="scores">tableau des scores pour chaque mot</param> public static void searchWord(Structures.box [,] Grille,char [] letters,int n, Structures.wordScrabble [] Words, int [] scores) { int m; int v; for(int i=0;i<n;i++) scores[i] = 0; for(int i = 0; i < 15; i++) { Structures.box [] line = new Structures.box [15]; Structures.box [] column = new Structures.box [15]; for(int j = 0;j < 15;j++) { line[j] = Grille[i,j]; column[j] = Grille[j,i]; } Structures.wordScrabble [] WordsTmp = new Structures.wordScrabble [10000]; m =searchWordByLine(line,letters, true, i,WordsTmp); for(int k=0;k<m;k++) { v=valueOfWord(WordsTmp[k],Grille); if(v != -1) { for(int j=0;j<n;j++) { if(scores[j] == -1) { Words[j] = WordsTmp[k]; scores[j] = v; break; } else if(scores[j] < v) { Structures.wordScrabble wordNow; Structures.wordScrabble wordNext; int scoreNow; int scoreNext; wordNow = WordsTmp[k]; scoreNow = v; for(int h=j; h<n;h++) { wordNext = Words[h]; scoreNext = scores[h]; Words[h] = wordNow; scores[h] = scoreNow; wordNow = wordNext; scoreNow = scoreNext; } break; } } } } m=searchWordByLine(column,letters, false, i,WordsTmp); for(int k=0;k<m;k++) { v=valueOfWord(WordsTmp[k],Grille); if(v != -1) { for(int j=0;j<n;j++) { if(scores[j] == -1) { Words[j] = WordsTmp[k]; scores[j] = v; break; } else if(scores[j] < v) { Structures.wordScrabble wordNow; Structures.wordScrabble wordNext; int scoreNow; int scoreNext; wordNow = WordsTmp[k]; scoreNow = v; for(int h=j; h<n;h++) { wordNext = Words[h]; scoreNext = scores[h]; Words[h] = wordNow; scores[h] = scoreNow; wordNow = wordNext; scoreNow = scoreNext; } break; } } } } } }
/// <summary> /// indique si le mot du joueur possède des lettres d'un des mots placés sur la grille /// </summary> /// <param name="Grille">grille de jeu</param> /// <param name="letters">lettres du mot du joueur</param> /// <param name="word">mot du joueur</param> /// <returns>true si le mot du joueur peut etre placé avec les lettres d'un mot sur la grille, false sinon</returns> public static bool hasLetters(Structures.box [,] Grille, char [] letters,Structures.wordScrabble word) { int posX=0; int posY=0; bool [] used = new bool [7]; bool [] usedJok = new bool [7]; bool everPosed=false; for (int i = 0; i < word.l; i++) { if (word.position) { posY = i; } else { posX = i; } if (word.x > 0 && word.x + posX < 15 && word.y > 0 && word.y + posY < 15) { if (Grille[word.x + posX, word.y + posY].tok.value == 0) { bool ok = false; for (int j = 0; j < 7; j++) { if (letters[j] == word.letters[i] && !used[j]) { used[j] = true; ok = true; break; } } if (!ok) { for (int j = 0; j < 7; j++) { if (letters[j] == '?' && !used[j] && !ok) { usedJok[j] = true; ok = true; } } } if (!ok) { return false; } } else if (Grille[word.x + posX, word.y + posY].tok.letter != word.letters[i]) { return false; } else { everPosed = true; } } } return true && everPosed; }