Database/Compte

This commit is contained in:
2026-03-25 20:54:24 +01:00
parent a43574c35a
commit 91aeead9e6
17 changed files with 439 additions and 17 deletions

13
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,13 @@
{
"java.project.referencedLibraries": [
"Projet-Dev/lib/**/*.jar"
],
"java.configuration.runtimes": [
{
"name": "JavaSE-24",
"path": "C:\\Program Files\\Java\\jdk-24",
"default": true
}
],
"java.jdt.ls.java.home": "C:\\Program Files\\Java\\jdk-24"
}

BIN
Jeu.db Normal file

Binary file not shown.

BIN
lib/slf4j-api-2.0.13.jar Normal file

Binary file not shown.

BIN
lib/slf4j-simple-2.0.13.jar Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,211 @@
package linea;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class DatabaseConnection {
private static final Path DB_PATH = resolveDbPath();
private static final String DB_URL = "jdbc:sqlite:" + DB_PATH;
private Connection conn;
private static Path resolveDbPath() {
Path cwd = Paths.get("").toAbsolutePath().normalize();
Path inProjetDev = cwd.resolve("Projet-Dev").resolve("Jeu.db");
if (Files.exists(cwd.resolve("Projet-Dev"))) {
return inProjetDev;
}
return cwd.resolve("Jeu.db");
}
public void connect() {
try {
Path parent = DB_PATH.getParent();
if (parent != null) {
Files.createDirectories(parent);
}
conn = DriverManager.getConnection(DB_URL);
System.out.println("Connexion à la DB OK: " + DB_PATH);
} catch (SQLException e) {
System.err.println("Erreur de connexion DB: " + e.getMessage());
} catch (Exception e) {
System.err.println("Erreur accès fichier DB: " + e.getMessage());
}
}
public void disconnect() {
if (conn == null) {
return;
}
try {
if (!conn.isClosed()) {
conn.close();
System.out.println("Déconnexion DB OK");
}
} catch (SQLException e) {
System.err.println("Erreur à la fermeture DB: " + e.getMessage());
}
}
public void createTables() {
if (conn == null) {
System.err.println("DB non connectée, impossible de créer les tables.");
return;
}
String createCompte = """
CREATE TABLE IF NOT EXISTS Compte (
id_compte INTEGER PRIMARY KEY AUTOINCREMENT,
pseudo TEXT NOT NULL
);
""";
String createNiveau = """
CREATE TABLE IF NOT EXISTS Niveau (
id_niveau INTEGER PRIMARY KEY AUTOINCREMENT,
nom TEXT,
nb_Objet INTEGER NOT NULL
);
""";
String createScore = """
CREATE TABLE IF NOT EXISTS Score (
id_score INTEGER PRIMARY KEY AUTOINCREMENT,
valeur_score INTEGER,
nb_mort INTEGER,
temps_jeu INTEGER,
id_compte INTEGER,
id_niveau INTEGER,
FOREIGN KEY(id_compte) REFERENCES Compte(id_compte),
FOREIGN KEY(id_niveau) REFERENCES Niveau(id_niveau)
);
""";
try (Statement stmt = conn.createStatement()) {
stmt.executeUpdate(createCompte);
stmt.executeUpdate(createNiveau);
stmt.executeUpdate(createScore);
System.out.println("Tables créées / existantes OK");
} catch (SQLException e) {
System.err.println("Erreur création tables : " + e.getMessage());
}
}
public void sauvegarderScore(int valeur, int idCompte, int nbMort, int tempsJeuSec) {
if (conn == null || idCompte <= 0) return;
String sql = "INSERT INTO Score (valeur_score, nb_mort, temps_jeu, id_compte) VALUES (?, ?, ?, ?)";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, valeur);
ps.setInt(2, nbMort);
ps.setInt(3, tempsJeuSec);
ps.setInt(4, idCompte);
ps.executeUpdate();
} catch (SQLException e) {
System.err.println("Erreur sauvegarde score : " + e.getMessage());
}
}
public int getMeilleurScoreParCompte(int idCompte) {
if (conn == null || idCompte <= 0) return 0;
String sql = "SELECT MAX(valeur_score) FROM Score WHERE id_compte = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, idCompte);
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) return rs.getInt(1);
}
} catch (SQLException e) {
System.err.println("Erreur lecture meilleur score : " + e.getMessage());
}
return 0;
}
public int creerCompte(String pseudo) {
if (conn == null || pseudo == null || pseudo.isBlank()) return -1;
String sql = "INSERT INTO Compte (pseudo) VALUES (?)";
try (PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
ps.setString(1, pseudo.trim());
ps.executeUpdate();
try (ResultSet rs = ps.getGeneratedKeys()) {
if (rs.next()) return rs.getInt(1);
}
} catch (SQLException e) {
System.err.println("Erreur création compte : " + e.getMessage());
}
return -1;
}
public int getIdParPseudo(String pseudo) {
if (conn == null || pseudo == null || pseudo.isBlank()) return -1;
String sql = "SELECT id_compte FROM Compte WHERE pseudo = ? LIMIT 1";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, pseudo.trim());
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) return rs.getInt(1);
}
} catch (SQLException e) {
System.err.println("Erreur lecture compte : " + e.getMessage());
}
return -1;
}
public void supprimerCompte(int idCompte) {
if (conn == null || idCompte <= 0) return;
try (PreparedStatement ps1 = conn.prepareStatement("DELETE FROM Score WHERE id_compte = ?");
PreparedStatement ps2 = conn.prepareStatement("DELETE FROM Compte WHERE id_compte = ?")) {
ps1.setInt(1, idCompte);
ps1.executeUpdate();
ps2.setInt(1, idCompte);
ps2.executeUpdate();
} catch (SQLException e) {
System.err.println("Erreur suppression compte : " + e.getMessage());
}
}
public List<String> getPseudos() {
List<String> pseudos = new ArrayList<>();
if (conn == null) return pseudos;
String sql = "SELECT pseudo FROM Compte ORDER BY pseudo";
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
pseudos.add(rs.getString("pseudo"));
}
} catch (SQLException e) {
System.err.println("Erreur lecture comptes : " + e.getMessage());
}
return pseudos;
}
public String getStatsParCompte(int idCompte) {
if (conn == null || idCompte <= 0) {
return "Aucune statistique disponible.";
}
String sql = "SELECT COALESCE(SUM(nb_mort),0) AS morts, "
+ "COALESCE(SUM(temps_jeu),0) AS temps, "
+ "COALESCE(MAX(valeur_score),0) AS meilleur "
+ "FROM Score WHERE id_compte = ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, idCompte);
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
int morts = rs.getInt("morts");
int temps = rs.getInt("temps");
int meilleur = rs.getInt("meilleur");
return "Nombre de morts : " + morts
+ "\nTemps de jeu total : " + temps + " s"
+ "\nMeilleur score : " + meilleur;
}
}
} catch (SQLException e) {
return "Erreur lecture stats : " + e.getMessage();
}
return "Aucune statistique disponible.";
}
}

BIN
linea/Jeu.db Normal file

Binary file not shown.

View File

@@ -1,14 +1,19 @@
package linea;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Jeu implements KeyListener, ActionListener {
@@ -24,15 +29,88 @@ public class Jeu implements KeyListener, ActionListener {
protected Timer horloge;
protected double score = 0;
protected JLabel labScore;
protected JLabel labMeilleurScore;
private DatabaseConnection db;
private int idCompte;
private int meilleurSansCompte = 0;
private int mortsSansCompte = 0;
private int tempsSansCompteSec = 0;
private long debutPartieMs = 0;
private int meilleurActuel() {
return idCompte > 0 ? db.getMeilleurScoreParCompte(idCompte) : meilleurSansCompte;
}
private String statsActuelles() {
if (idCompte > 0) {
return db.getStatsParCompte(idCompte);
}
return "Nombre de morts : " + mortsSansCompte
+ "\nTemps de jeu total : " + tempsSansCompteSec + " s"
+ "\nMeilleur score : " + meilleurSansCompte;
}
private void enregistrerPartie(int scoreActuel, int tempsPartieSec) {
if (idCompte > 0) {
db.sauvegarderScore(scoreActuel, idCompte, 1, tempsPartieSec);
return;
}
meilleurSansCompte = Math.max(meilleurSansCompte, scoreActuel);
mortsSansCompte += 1;
tempsSansCompteSec += tempsPartieSec;
}
//-------------------------------------------------------------------------
// CONSTRUCTEUR
//-------------------------------------------------------------------------
public Jeu() {
public Jeu(DatabaseConnection db, int idCompte) {
this.db = db;
this.idCompte = idCompte;
labScore = new JLabel();
labScore.setText("<html><h3>score : 0</h3></html>");
labScore.setBounds(20, 0, 200, 50);
ecran.add(labScore);
labMeilleurScore = new JLabel();
JPanel panneauScores = new JPanel(new FlowLayout(FlowLayout.LEFT, 20, 0));
panneauScores.setOpaque(false);
panneauScores.add(labScore);
panneauScores.add(labMeilleurScore);
ecran.add(panneauScores, BorderLayout.NORTH);
rafraichirMeilleurScore();
}
private void rafraichirMeilleurScore() {
labMeilleurScore.setText("<html><h3>meilleur : " + meilleurActuel() + "</h3></html>");
}
private boolean choisirNouveauCompte() {
List<String> pseudos = new ArrayList<>(db.getPseudos());
pseudos.add(0, "Sans compte");
String choix = (String) JOptionPane.showInputDialog(
null,
"Choisissez le compte pour la prochaine partie :",
"Changer de compte",
JOptionPane.QUESTION_MESSAGE,
null,
pseudos.toArray(String[]::new),
pseudos.get(0)
);
if (choix == null) {
return false;
}
if ("Sans compte".equals(choix)) {
idCompte = -1;
meilleurSansCompte = 0;
mortsSansCompte = 0;
tempsSansCompteSec = 0;
} else {
idCompte = db.getIdParPseudo(choix);
}
rafraichirMeilleurScore();
return true;
}
//-------------------------------------------------------------------------
@@ -79,6 +157,7 @@ public class Jeu implements KeyListener, ActionListener {
// Création et lancement du timer
horloge = new Timer(40, this);
horloge.start();
debutPartieMs = System.currentTimeMillis();
}
private void resetLevel() {
@@ -88,6 +167,7 @@ public class Jeu implements KeyListener, ActionListener {
// Ré-initialisation des objets graphiques
initialiserPartie();
debutPartieMs = System.currentTimeMillis();
// Relance le timer existant et redonne le focus
if (horloge != null) horloge.restart();
@@ -104,17 +184,39 @@ public class Jeu implements KeyListener, ActionListener {
if (ecran.aCollision()) {
horloge.stop();
Object[] options = {"Relancer", "Quitter"};
int choix = JOptionPane.showOptionDialog(null,
"Perdu\nScore : " + (int)score,
"Game Over",
JOptionPane.DEFAULT_OPTION,
JOptionPane.INFORMATION_MESSAGE,
null, options, options[0]);
if (choix == 0) resetLevel();
else System.exit(0);
int scoreActuel = (int) score;
int tempsPartieSec = (int) ((System.currentTimeMillis() - debutPartieMs) / 1000L);
enregistrerPartie(scoreActuel, tempsPartieSec);
rafraichirMeilleurScore();
while (true) {
Object[] options = {"Relancer", "Changer de compte", "Voir stats", "Quitter"};
int choix = JOptionPane.showOptionDialog(null,
"Perdu\nScore : " + scoreActuel + "\nMeilleur : " + meilleurActuel(),
"Game Over",
JOptionPane.DEFAULT_OPTION,
JOptionPane.INFORMATION_MESSAGE,
null, options, options[0]);
if (choix == 0) {
resetLevel();
break;
}
if (choix == 1) {
if (choisirNouveauCompte()) {
resetLevel();
break;
}
continue;
}
if (choix == 2) {
JOptionPane.showMessageDialog(null, statsActuelles(), "Statistiques", JOptionPane.INFORMATION_MESSAGE);
continue;
}
System.exit(0);
}
return;
}

View File

@@ -1,13 +1,109 @@
package linea;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
public class LineaAppli {
private static String choisirPseudo(DatabaseConnection db, String message, int messageType) {
List<String> pseudos = db.getPseudos();
if (pseudos.isEmpty()) {
JOptionPane.showMessageDialog(null, "Aucun compte disponible.");
return null;
}
return (String) JOptionPane.showInputDialog(
null,
message,
"Comptes",
messageType,
null,
pseudos.toArray(String[]::new),
pseudos.get(0)
);
}
private static Integer menuComptes(DatabaseConnection db) {
while (true) {
Object[] options = {"Sélectionner", "Créer", "Supprimer", "Retour"};
int choix = JOptionPane.showOptionDialog(
null,
"Gestion des comptes :",
"Comptes",
JOptionPane.DEFAULT_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]
);
if (choix == JOptionPane.CLOSED_OPTION || choix == 3) return null;
switch (choix) {
case 0 -> {
String pseudo = choisirPseudo(db, "Sélectionnez un compte :", JOptionPane.QUESTION_MESSAGE);
if (pseudo != null) return db.getIdParPseudo(pseudo);
}
case 1 -> {
String pseudo = JOptionPane.showInputDialog(null, "Nouveau pseudo :");
if (pseudo == null || pseudo.trim().isEmpty()) continue;
pseudo = pseudo.trim();
int id = db.getIdParPseudo(pseudo);
return id > 0 ? id : db.creerCompte(pseudo);
}
case 2 -> {
String pseudo = choisirPseudo(db, "Sélectionnez le compte à supprimer :", JOptionPane.WARNING_MESSAGE);
if (pseudo == null) continue;
int confirm = JOptionPane.showConfirmDialog(
null,
"Supprimer le compte \"" + pseudo + "\" et toute sa progression ?",
"Confirmation",
JOptionPane.YES_NO_OPTION
);
if (confirm == JOptionPane.YES_OPTION) {
int id = db.getIdParPseudo(pseudo);
if (id > 0) db.supprimerCompte(id);
}
}
}
}
}
//-------------------------------------------------------------------------
// Classe de base de l'application, rien à modifier ici
//-------------------------------------------------------------------------
public static void main(String[] arg) {
UIManager.put("OptionPane.cancelButtonText", "Retour");
Jeu jeu = new Jeu();
jeu.demarrer();
DatabaseConnection db = new DatabaseConnection();
db.connect();
db.createTables();
while (true) {
Object[] options = {"Comptes", "Sans compte", "Quitter"};
int choix = JOptionPane.showOptionDialog(null,
"Choisissez une action :",
"Menu", JOptionPane.DEFAULT_OPTION,
JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
if (choix == JOptionPane.CLOSED_OPTION || choix == 2) {
return;
}
switch (choix) {
case 1 -> {
new Jeu(db, -1).demarrer();
return;
}
case 0 -> {
Integer idCompte = menuComptes(db);
if (idCompte != null) {
new Jeu(db, idCompte).demarrer();
return;
}
}
}
}
}
}

BIN
out/linea/Cercle.class Normal file

Binary file not shown.

Binary file not shown.

BIN
out/linea/Jeu.class Normal file

Binary file not shown.

BIN
out/linea/Ligne.class Normal file

Binary file not shown.

BIN
out/linea/LineaAppli.class Normal file

Binary file not shown.

Binary file not shown.

BIN
out/linea/Segment.class Normal file

Binary file not shown.

BIN
out/linea/ZoneDessin.class Normal file

Binary file not shown.