#include "gamemanager.h" #include "random" #include <QFileInfo> #include <QDebug> GameManager::GameManager(QObject *parent) : QObject(parent), grid(4, std::vector<int>(4, 0)),m_score(0), m_gameOver(false) { } void GameManager::moveLeft() { if (m_gameOver) { // Si la partie est terminée, ne fais rien return; } for (int i = 0; i < 4; i++) { std::vector<int> newRow(4, 0); // Créer une nouvelle ligne vide int newPos = 0; // Position pour insérer un élément non nul (commence par le début) int temp = 0; // Variable pour mémoriser l'élément à fusionner // Parcourir la ligne de gauche à droite for (int j = 0; j <4; j++) { if (grid[i][j] != 0) { // Si l'élément n'est pas nul if (temp == 0) { // Mémoriser l'élément actuel temp = grid[i][j]; } else if (temp == grid[i][j]) { // Si l'élément est identique au "temp", fusionner newRow[newPos] = temp * 2; // Fusionner en doublant la valeur temp = 0; // Réinitialiser temp après fusion newPos++; // Déplacer la position pour l'élément suivant } else { // Si l'élément n'est pas identique à "temp", le placer dans la nouvelle ligne newRow[newPos] = temp; temp = grid[i][j]; // Mettre à jour temp avec le nouvel élément newPos++; // Déplacer la position pour l'élément suivant } } } // Si l'élément restant dans "temp" n'a pas été placé, on le place if (temp != 0) { newRow[newPos] = temp; } // Mettre à jour la grille avec la nouvelle ligne grid[i] = newRow; } emit addRandomElement(); m_gameOver = isGameOver(); //Mettre a jour l'état et l'enregistrer historyArray.append(gridToJsonArray()); emit gridChanged(); emit calculscore(); } void GameManager::moveRight() { if (m_gameOver) { // Si la partie est terminée, ne fais rien return; } for (int i = 0; i < 4; i++) { std::vector<int> newRow(4, 0); // Créer une nouvelle ligne vide int newPos = 3; // Position pour insérer un élément non nul (commence par la fin) int temp = 0; // Variable pour mémoriser l'élément à fusionner // Parcourir la ligne de droite à gauche for (int j = 3; j >= 0; j--) { if (grid[i][j] != 0) { // Si l'élément n'est pas nul if (temp == 0) { // Mémoriser l'élément actuel temp = grid[i][j]; } else if (temp == grid[i][j]) { // Si l'élément est identique au "temp", fusionner newRow[newPos] = temp * 2; // Fusionner en doublant la valeur temp = 0; // Réinitialiser temp après fusion newPos--; // Déplacer la position pour l'élément suivant } else { // Si l'élément n'est pas identique à "temp", le placer dans la nouvelle ligne newRow[newPos] = temp; temp = grid[i][j]; // Mettre à jour temp avec le nouvel élément newPos--; // Déplacer la position pour l'élément suivant } } } // Si l'élément restant dans "temp" n'a pas été placé, on le place if (temp != 0) { newRow[newPos] = temp; } // Mettre à jour la grille avec la nouvelle ligne grid[i] = newRow; } emit addRandomElement(); m_gameOver = isGameOver(); //Mettre a jour l'état et l'enregistrer historyArray.append(gridToJsonArray()); emit gridChanged(); emit calculscore(); } void GameManager::moveUp() { if (m_gameOver) { // Si la partie est terminée, ne fais rien return; } // Implémentation du mouvement vers le haut for (int j = 0; j < 4; j++) { std::vector<int> newCol(4, 0); // Créer une nouvelle ligne vide int newPos = 0; // Position pour insérer un élément non nul (commence par la fin) int temp = 0; // Variable pour mémoriser l'élément à fusionner // Parcourir la ligne de droite à gauche for (int i = 0; i <4; i++) { if (grid[i][j] != 0) { // Si l'élément n'est pas nul if (temp == 0) { // Mémoriser l'élément actuel temp = grid[i][j]; } else if (temp == grid[i][j]) { // Si l'élément est identique au "temp", fusionner newCol[newPos] = temp * 2; // Fusionner en doublant la valeur temp = 0; // Réinitialiser temp après fusion newPos++; // Déplacer la position pour l'élément suivant } else { // Si l'élément n'est pas identique à "temp", le placer dans la nouvelle ligne newCol[newPos] = temp; temp = grid[i][j]; // Mettre à jour temp avec le nouvel élément newPos++; // Déplacer la position pour l'élément suivant } } } // Si l'élément restant dans "temp" n'a pas été placé, on le place if (temp != 0) { newCol[newPos] = temp; } // Mettre à jour la colonne dans la grille for (int i=0;i<4;i++){ grid[i][j]=newCol[i]; } } emit addRandomElement(); m_gameOver = isGameOver(); //Mettre a jour l'état et l'enregistrer historyArray.append(gridToJsonArray()); emit gridChanged(); emit calculscore(); } void GameManager::moveDown() { if (m_gameOver) { // Si la partie est terminée, ne fais rien return; } // Implémentation du mouvement vers le bas for (int j = 0; j < 4; j++) { std::vector<int> newCol(4, 0); // Créer une nouvelle ligne vide int newPos = 3; // Position pour insérer un élément non nul (commence par la fin) int temp = 0; // Variable pour mémoriser l'élément à fusionner // Parcourir la ligne de droite à gauche for (int i = 3; i>=0; i--) { if (grid[i][j] != 0) { // Si l'élément n'est pas nul if (temp == 0) { // Mémoriser l'élément actuel temp = grid[i][j]; } else if (temp == grid[i][j]) { // Si l'élément est identique au "temp", fusionner newCol[newPos] = temp * 2; // Fusionner en doublant la valeur temp = 0; // Réinitialiser temp après fusion newPos--; // Déplacer la position pour l'élément suivant } else { // Si l'élément n'est pas identique à "temp", le placer dans la nouvelle ligne newCol[newPos] = temp; temp = grid[i][j]; // Mettre à jour temp avec le nouvel élément newPos--; // Déplacer la position pour l'élément suivant } } } // Si l'élément restant dans "temp" n'a pas été placé, on le place if (temp != 0) { newCol[newPos] = temp; } // Mettre à jour la colonne dans la grille for (int i=0;i<4;i++){ grid[i][j]=newCol[i]; } } emit addRandomElement(); m_gameOver = isGameOver(); //Mettre a jour l'état et l'enregistrer historyArray.append(gridToJsonArray()); emit gridChanged(); emit calculscore(); } void GameManager::restartGame(QString partieName) { //demander pour sauvergarder la partie précédente <<<<<<< HEAD if(partieName=="false"){ }else{ enregistrerPartie(partieName); }; ======= enregistrerPartie("partie1"); m_gameOver = false; >>>>>>> e22daca7a3c09bd0a515d12093b0cbf7e3e4e152 // Réinitialisation des variables grid.assign(4, std::vector<int>(4, 0)); historyArray = QJsonArray(); std::random_device rd; std::uniform_int_distribution<int> distrib(0, 15); int num1 = distrib(rd); int num2; // Assure que num2 est différent de num1 do { num2 = distrib(rd); } while (num2 == num1); int rg1= num1/4; int col1= num1 - (4*rg1); int rg2= num2/4; int col2= num2 - (4*rg2); grid[rg1][col1]=2; grid[rg2][col2]=2; //Mettre a jour l'état et l'enregistrer historyArray.append(gridToJsonArray()); emit gridChanged(); emit calculscore(); } void GameManager::addRandomElement() { // Créer une liste pour stocker les indices des cases vides std::vector<std::pair<int, int>> emptyCells; // Parcourir la grille pour trouver toutes les cases vides for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (grid[i][j] == 0) { // Si la case est vide (valeur 0) emptyCells.push_back({i, j}); // Ajouter l'indice de la case à la liste } } } // Si la liste des cases vides n'est pas vide, on ajoute un nouveau '2' if (!emptyCells.empty()) { // Choisir une case vide aléatoire int randomIndex = rand() % emptyCells.size(); int row = emptyCells[randomIndex].first; int col = emptyCells[randomIndex].second; // Placer un '2'ou un '4' dans cette case int randValue = std::rand() % 100; if (randValue < 75) { grid[row][col] = 2; } else { grid[row][col] = 4; }; } } QVector<int> GameManager::getGridValues() const { QVector<int> flattenedGrid; for (const auto& row : grid) { // Parcourt chaque ligne for (int value : row) { // Parcourt chaque colonne flattenedGrid.append(value); } } return flattenedGrid; } QStringList GameManager::getPartieHistorique() { QFile file("historique.json"); qDebug() << "Fichier JSON enregistré à : " << QFileInfo(file).absoluteFilePath(); if (!file.open(QIODevice::ReadWrite)) { qWarning() << "Impossible d'ouvrir le fichier pour écriture :" << file.errorString(); } QJsonDocument doc; if (file.size() > 0) { // Vérifier que le fichier n'est pas vide doc = QJsonDocument::fromJson(file.readAll()); }else{ // Sinon initialiser avec un objet vide doc = QJsonDocument(QJsonObject()); } QJsonObject rootObj = doc.object(); QStringList list = rootObj.keys(); file.close(); qDebug() << "Liste des parties:" << list ; return list; } QJsonArray GameManager::gridToJsonArray() { QJsonArray jsonGrid; for (const auto &row : grid) { QJsonArray jsonRow; for (int cell : row) { jsonRow.append(cell); } jsonGrid.append(jsonRow); // Ajoute chaque ligne } return jsonGrid; } void GameManager::undo() { if (historyArray.size() > 1) { // Vérifiez qu'il y a au moins deux états historyArray.removeLast(); // Supprimez le dernier état QJsonArray previousState = historyArray.last().toArray(); // Récupérez l'avant-dernier état // Mettez à jour la grille avec l'état précédent for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { grid[i][j] = previousState[i].toArray()[j].toInt(); } } emit gridChanged(); // Notifiez que la grille a changé emit calculscore(); } } void GameManager::enregistrerPartie(QString partieName){ QFile file("historique.json"); qDebug() << "Fichier JSON enregistré à : " << QFileInfo(file).absoluteFilePath(); // Ouvrir le fichier en mode lecture/écriture (si existant) if (!file.open(QIODevice::ReadWrite)) { qWarning() << "Impossible d'ouvrir le fichier pour écriture :" << file.errorString(); return; } QJsonDocument doc; if (file.size() > 0) { // Vérifier que le fichier n'est pas vide doc = QJsonDocument::fromJson(file.readAll()); }else{ // Sinon initialiser avec un objet vide doc = QJsonDocument(QJsonObject()); } QJsonObject rootObj = doc.object(); // Récupérer l'objet JSON racine rootObj[partieName] = historyArray; // Ajouter ou remplacer la grille associée à l'ID // Réécriture du fichier avec la nouvelle version file.resize(0); // Effacer le contenu du fichier avant d'écrire la nouvelle version file.write(QJsonDocument(rootObj).toJson()); file.close(); emit historiqueChanged(); } void GameManager::chargerPartie(QString partieName){ QFile file("historique.json"); // Ouvrir le fichier en mode lecture/écriture (si existant) if (!file.open(QIODevice::ReadWrite)) { qWarning() << "Impossible d'ouvrir le fichier pour écriture :" << file.errorString(); return; } QJsonDocument doc; if (file.size() > 0) { // Vérifier que le fichier n'est pas vide doc = QJsonDocument::fromJson(file.readAll()); }else{ // Sinon erreur return; } QJsonObject rootObj = doc.object(); // Récupérer l'objet JSON racine historyArray = rootObj[partieName].toArray(); // Charger la grille QJsonArray previousState = historyArray.last().toArray(); // Récupérez le dernier état de la partie chargée // Mettez à jour la grille for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { grid[i][j] = previousState[i].toArray()[j].toInt(); } } emit gridChanged(); // Notifiez que la grille a changé file.close(); } int GameManager::score() const { return m_score; // Retourne le score actuel } <<<<<<< HEAD ======= void GameManager::calculscore(){ if (m_gameOver) { // Si la partie est terminée, ne calcule pas le score return; } m_score = 0; // Parcourir la grille pour additionner toute les cases for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { m_score+=grid[i][j]; } } emit scoreChanged(); } bool GameManager::isGameOver() { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (grid[i][j] == 0) { // Une case vide est trouvée, donc le jeu n'est pas fini return false; } // Vérifier les possibilités de fusion (horizontale et verticale) if ((i < 3 && grid[i][j] == grid[i + 1][j]) || (j < 3 && grid[i][j] == grid[i][j + 1])) { return false; } } } return true; // Si la grille est pleine et aucune fusion n'est possible, la partie est terminée } >>>>>>> e22daca7a3c09bd0a515d12093b0cbf7e3e4e152