Cette semaine, c'est Josquin qui vous propose un #KataOfTheWeek : 2048
Briefing du Kata : Vous avez en entrée un tableau 2D 4x4 représentant un plateau de 2048. Pour chaque case de ce tableau, vous avez une puissance de 2. Une case vide sera représentée par 0.
Le but de ce kata est de retourner le tableau à l'étape n+1 en supposant que le joueur fait un mouvement vers le bas.
/!\ Attention, bien que l'algorithme parraisse simple, il y a des petites subtilités et je vous conseille fortement d'utiliser une démarche TDD !
Saurez-vous résoudre le problème ?
Bon courage !
Et voici une solution proposée par l'auteur :
La solution que je propose consiste à prendre le nombre le plus bas, et à le descendre. Dans le cas de la première colonne, c'est assez simple, le 2 "tombe" en bas.
Ensuite, si un nombre tombe sur un autre nombre, il faut les faire s'additionner. C'est pourquoi dans la deuxième colonne, on additionne les deux 2 pour en faire un 4. C'est aussi pourquoi je commence par le nombre le plus bas : sinon, ce seront les mauvais 2 qui s'additionneront et le résultat en serait différent.
La colonne 3 possède une difficulté supplémentaire : les nombres vont s'additionner en tombant mais ne doivent pas continuer à s'additionner avec le 8 tout en haut. Pour cela, la solution que j'ai choisit est de créer un tableau supplémentaire qui retient quels nombres ont été additionnés de façon à ne pas les additionner de nouveau.
La colonne 4 quant à elle reprend toutes les difficultés des autres colonnes et est un bon test pour voir si l'algorithme fonctionne bien.
Exemple :
| | | 8 | 2 |
| | 2 | | 2 |
| 2 | 2 | 4 | 2 |
| | 2 | 4 | 2 |
|
V
| | | | |
| | | | |
| | 2 | 8 | 4 |
| 2 | 4 | 8 | 4 |
public static void moveDownward(int [][] board) {
boolean [][] hasAlreadyBeenAdded = new boolean[4][4];
for (int column = 0; column < board[0].length; column++) {
for (int row = board.length - 1; row >= 1; row--) {
if ((board[row][column] == board[row - 1][column]) && board[row][column] != 0 && hasAlreadyBeenAdded[row][column] != true && hasAlreadyBeenAdded[row - 1][column] != true) {
// Sum 2 adjacent numbers
board[row][column] = board[row][column] + board[row - 1][column];
board[row - 1][column] = 0;
hasAlreadyBeenAdded[row][column] = true;
row = board.length - 1;
}
if (board[row][column] == 0 && board[row - 1][column] != 0) {
// Drop the number down
board[row][column] = board[row - 1][column];
board[row - 1][column] = 0;
hasAlreadyBeenAdded[row][column] = hasAlreadyBeenAdded[row - 1][column];
row = board.length;
}
}
}
}
Votre équipe TakiVeille