Vous n'êtes pas identifié(e).
Pages : 1
Voici un gros paquet de code que je partage pour le plus grand plaisir d'apprendre le langage et puis aussi pour profiter du programme en cas de besoin.
Juste une petite remarque avant de déposer cette source:
Avis aux personnes qui passent par là (pas forcément des membres du forum) et qui se servent, la réalisation de cette source m'a demandé du temps et de l'investissement. Ainsi, je partage librement mes sources mais elle n'est pas consacrées a des buts commerciaux. Merci de me laisser ma part de crédits sur le travail effectué en pensant à conserver l'auteur original du code source (c'est a dire moi). Ce n'est pas du WTFPL, c'est du GPLv3.
Vous êtes bien entendu libre de la modifier, de l'améliorer et de la repartager autour de vous, et c'est même souhaité
Vos remerciements, remarques et suggestions également sont les bienvenues et j'espère qu'elle vous pourra vous servir de références sur d'autres projets
Code:
/**
* Carré magique - Magical square
*
* Programme java qui fabrique un carré magique.
* Java program designed to built magical square.
*
* Copyright (C) 2014-07-07 WarLocG(C)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ----------------------------------------------------------------
* Ce programme est partagé librement en respect de la GNU GPLv3.
* Veuillez ne pas réutiliser cette source à des fins commerciaux.
*/
/* imports de lib */
import java.util.Scanner; /* Frappe clavier CLI */
import java.lang.Exception; /* Gestion d'erreur */
import javax.swing.*; /* GUI */
import java.awt.*; /* Container et Component pour GUI */
import java.awt.event.*; /* Listener's pour GUI */
/* structure du programme
*
* main <>--- FabriqueCarreM <>---------------- PasImpairException
* | |
* | |
* (abs)CarreM <>-----------------------------------'
* /\
* /__\
* |
* |-------------------------,
* | |
* CarreMCLI <>-----, ,-----<> CarreMGUI <>--- GUI
* | |
* Case
*
* Explication:
* Réalisation d'un pattern fabrique sur CarreM, selon que l'utilisateur choisira
* CLI ou GUI, le programme fabriquera un CarreM en fonction
*
*/
/* classes */
/** Case contenant les nombres */
class Case{
/* -- Attributs -- */
private int nombre; /* valeur contenue dans la case */
private boolean bordure; /* indique si la case est en bordure */
/* -- Constructeur -- */
public Case(){
this.nombre = 0; /* a la creation, nombre vaut 0 */
this.bordure = false; /* indique si la case est au bord */
}
/* -- Methodes -- */
/** Methode verifiant si la case contient deja une valeur */
public boolean estVide(){
return (this.nombre == 0) ? true : false;
}
public int getNombre(){
return this.nombre;
}
public void setNombre(int nombre){
this.nombre = nombre;
}
/** Verifie si la case est sur un bord */
public boolean estBordure(){
return this.bordure;
}
public void setBordure(boolean bordure){
this.bordure = bordure;
}
}
/** Exception declenchée lorsque le nombre est impair */
class PasImpairException extends Exception{
public PasImpairException(String message){super(message);}
}
abstract class CarreM{
/* -- Attributs -- */
protected int nombreM; /* nombre magique calculé comme etant N² + N* ((N-1)*(int)(N/2)) */
protected int nombre; /* nombre donne en argument */
protected Case[][] matrice; /* tableau de case */
/* -- Constructeur -- */
public CarreM(int nombre) throws PasImpairException{
if (! estImpair(nombre)) throw new PasImpairException("Un carré magique ne peut se créer qu'avec des nombres impairs.");
else{
this.nombre = nombre;
this.nombreM = (nombre * nombre) + (nombre * ((nombre - 1) * (nombre / 2)));
this.matrice = new Case[nombre][nombre];
remplir();
}
}
/* -- Methodes -- */
protected boolean estImpair(int nombre){
return (nombre % 2 == 1) ? true : false;
}
protected int getNombre(){
return this.nombre;
}
protected int getNombreM(){
return this.nombreM;
}
protected boolean verifier(){
int somme;
boolean ok = true;
/* test sur les lignes */
for (int i=0; i<nombre; i++){
somme = 0;
for (int j=0; j<nombre; j++){
somme += this.matrice[i][j].getNombre();
}
ok &= (somme == this.nombreM) ? true : false;
}
/* test sur les colonnes */
for (int i=0; i<nombre; i++){
somme = 0;
for (int j=0; j<nombre; j++){
somme += this.matrice[j][i].getNombre();
}
ok &= (somme == this.nombreM) ? true : false;
}
/* test sur les diagonales */
somme = 0;
for (int i=0; i<nombre; i++){
somme += this.matrice[i][i].getNombre();
}
ok &= (somme == this.nombreM) ? true : false;
return ok;
}
protected void remplir(){
int x,y,n; /* x et y : position dans le plateau; n : nombre actuel */
int carre = this.getNombre() * this.getNombre(); /* le nombre au carré */
/* creer la matrice d'objet Case */
for (int i=0;i<getNombre();i++){
for (int j=0;j<getNombre();j++){
this.matrice[i][j]=new Case();
}
}
/* Algorithme : demo sur 3 x 3
*
* On commence par placer 1 dans la case au centre de la dernière ligne:
* *-----*
* | | | |
* +-+-+-+
* | | | |
* +-+-+-+
* | |1| |
* *-----*
*
* Ensuite, en partant du 1 on se deplace en diagonale bas/droite
* - si on rencontre un bord, on reporte de l autre coté
* - si la case est occupée, on place le nombre au dessus
* *-----*
* | | |2|
* +-+-+-+
* | | | |
* +-+-+-+
* | |1| |
* *-----*
*
* *-----*
* | | |2|
* +-+-+-+
* |3| | |
* +-+-+-+
* | |1| |
* *-----*
* Ici la prochaine case est occupée, on la dépose au dessus
* *-----*
* |4| |2|
* +-+-+-+
* |3| | |
* +-+-+-+
* | |1| |
* *-----*
* Si vous avez correctement posé les nombres, la case centrale aura le nombre
* nombre magique / nombre; dans le cas du 3 * 3, le nombre magique vaut:
* 3² + 3*2*1 = 15; la case centrale devrait donc avoir 15/3 = 5;
*
* Carré terminé:
* *-----*
* |4|9|2|
* +-+-+-+
* |3|5|7|
* +-+-+-+
* |8|1|6|
* *-----*
* Si toutes les cases ont pu etre remplies, c'est bon :)
* Le dernier nombre tombera en normalement sur la case centrale de la premiere ligne
*
* Vérification: lignes, colonnes et diagonales doivent avoir pour valeur le nombre magique
* soit 15
*/
/* detecter le centre de la derniere ligne */
x = this.getNombre()-1;
y = (int)(this.getNombre()/2);
n = 1; /* on commence par poser le 1 */
/* boucler jusqu' a ce que tout les nombres soient incrustés */
try{
/* juste un petit try - catch pour ne pas planter le programme en cas d Exception */
while(n < carre+1){
// on pose le 1
this.matrice[x][y].setNombre(n);
/* detection des bords; dans la mesure ou l on se deplace toujours vers bas/droite
* le test sur les coordonnees 0,0 n est pas utile */
if (x == this.getNombre()-1 | y == this.getNombre()-1){
this.matrice[x][y].setBordure(true);
}
/* test si on est sur une bordure */
if (this.matrice[x][y].estBordure()){
/* si on est arrivé dans le coin bas/droite, la case 0,0 est normalement deja occupée */
if (x == this.getNombre()-1 && y == this.getNombre()-1){
// arrivé dans le coin bas/droite, poser sur la case au dessus */
x--;
}else{
// les autres cas, les cases sont normalement inoccupés. Report normal.
if (x+1 >= this.getNombre()){x=0;} else {x++;}
if (y+1 >= this.getNombre()){y=0;} else {y++;}
}
}else{
// on teste la case suivante
if (this.matrice[x+1][y+1].estVide()){ // vide => on place normalement
//System.out.println("test - rentré dans le cas estVide");
x++;
y++;
} else { // occupée => on place au dessus
//System.out.println("test - rentré dans le cas estOccupe");
x--;
}
}
n++;
// la dernière case devrait normalement tomber sur la case centrale de la premiere ligne
}
}catch(ArrayIndexOutOfBoundsException e){
// passer a la suite
}
}
abstract void construire(); /* fabrique la grille du carre magique (affiche en CLI)*/
abstract void construireTest(); /* verifier si on a un carre magique */
protected String aPropos(){
String apropos = "\nA propos\n\n";
apropos += "Programme réalisé par WarLocG(c). Juillet 2014\n";
apropos += "Ce programme est partagé librement en respect de la GNU GPLv3.\n";
apropos += "Veuillez ne pas réutiliser cette source à des fins commerciaux.";
return apropos;
}
}
/** Carre magique sur console */
class CarreMCLI extends CarreM {
/* -- Constructeur -- */
public CarreMCLI(int nombre) throws PasImpairException{
super(nombre);
construireTest();
construire();
System.out.println(super.aPropos());
}
/* -- Methodes -- */
// a adapter ...
@Override
public void construire(){
int i,j;
/* bord sup de la grille -> *---+---+---* */
String str = "*---";
for (i=0; i<nombre-1; i++){ // partie interne uniq.; car. par car.
str += "+---";
}
str += "*";
System.out.println(str);
/* partie centrale */
for (i=0; i<(nombre*2)-1; i++){ // partie interne uniq.; ligne par ligne
if (! estImpair(i)){
str = "|";
for (j=0; j<nombre; j++){ //partie interne + bord; par 2 car.
str += String.format("%3d",this.matrice[i/2][j].getNombre())+"|";
}
}else{
str = "+";
for (j=0; j<nombre; j++){ //partie interne + bord; par 2 car.
str += "---+";
}
}
System.out.println(str);
}
/* bord inf de la grille -> *---+---+---* */
str = "*---";
for (i=0; i<nombre-1; i++){
str += "+---";
}
str += "*";
System.out.println(str);
}
@Override
public void construireTest(){
System.out.println("Carré magique vaut: "+this.getNombreM());
System.out.println("Nombre central doit valoir: "+this.getNombreM()/this.getNombre());
System.out.println("Nombre central vaut: "+this.matrice[this.getNombre()/2][this.getNombre()/2].getNombre());
System.out.println("Nombre au sommet doit valoir: "+this.getNombre()*this.getNombre());
System.out.println("Nombre au sommet vaut: "+this.matrice[0][this.getNombre()/2].getNombre());
System.out.println("Carré magique vaut: "+this.getNombreM());
System.out.println("La somme doit valoir: "+this.getNombreM());
System.out.println("A passé les tests des sommes: "+super.verifier());
System.out.println();
}
}
/** Carre magique sur interface graphique */
class CarreMGUI extends CarreM {
/* -- Constructeur -- */
public CarreMGUI(int nombre) throws PasImpairException{
super(nombre);
construire();
}
// appel a JFrame et Listener
@Override
public void construire(){
// en commentaire: a quoi la methode sert + classe fournissant la methode a la suite
GUI gui = new GUI(this.getNombre(), this.matrice, this.aPropos()); // Fenetre et titre JFrame
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Operation à la fermeture JFrame
gui.setTitle("Programme Carré magique version GUI"); // Met un titre
gui.pack(); // Dimensionne la fenetre Window
gui.setVisible(true); // Rend visible !important! Window
}
@Override
public void construireTest(){
}
}
class GUI extends JFrame implements ActionListener{
private String apropos = ""; // attributs "global" pour partager avec le listener
public GUI(int nombre, Case[][] matrice, String apropos){
/* -- Attributs importés -- */
this.apropos = apropos;
/* Barre des menus */
JMenuBar menuPrincipal = new JMenuBar();
JMenu jmMenu = new JMenu("Menu");
JMenuItem jmiAPropos = new JMenuItem("A propos");
JMenuItem jmiQuitter = new JMenuItem("Quitter");
/* Contenant et layouts */
Container supportPrincipal = this.getContentPane();
Container supportCase = new Container();
/* Composants (boutons, barre de texte, etc.. */
// aucun ici :P
/* Pré-requis pour affichier la boite */
jmiAPropos.addActionListener(this); // on integre une action lors d'un clic sur "Quitter"
jmiQuitter.addActionListener(this); // on integre une action lors d'un clic sur "A Propos"
jmMenu.add(jmiAPropos); // ajout de l'option "A Propos" dans le menu "Menu"
jmMenu.add(jmiQuitter); // ajout de l'option "Quitter" dans le menu "Menu"
menuPrincipal.add(jmMenu); // ajout du menu "Menu" dans la bar des menus
supportCase.setLayout(new GridLayout(nombre,nombre));
for (int i=0; i<(nombre*nombre); i++){
// cree un tableau de JLabel contenant la valeur dans Case dans la matrice
supportCase.add(new JLabel(String.valueOf(matrice[i/nombre][i%nombre].getNombre())));
// Comme je ne travaille pas avec deux for imbriqués, je calcule ce que vaudrait i et j
}
supportCase.setSize(400,400);
this.setJMenuBar(menuPrincipal); // ajout de la bar des menus a la fenetre
supportPrincipal.add(supportCase); // ajout du corps de la fenetre
}
/* -- Listener -- */
@Override
public void actionPerformed(ActionEvent action){
/* decoupe de la string de l event pour sortir le menuItem correspondant a l action */
String act = action.toString(), str;
int debut = act.lastIndexOf("=")+1, fin = act.lastIndexOf("]");
str = act.substring(debut,fin);
/* switch - case non realisable avec des String, utilisation des if */
if( str.compareTo("A propos")==0){new JOptionPane().showMessageDialog(this,apropos);}
else if( str.compareTo("Quitter")==0){this.dispose();}
else{System.out.println("autre -> dbg: str vaut "+str);}
}
}
/* pattern factory */
/** Pattern factory sur CarreM */
class FabriqueCarreM{
/* -- Methode -- */
public static CarreM build(int choix, int nombre) throws PasImpairException{
if (choix == 1){
return new CarreMCLI(nombre);
}else{ //choix == 2
return new CarreMGUI(nombre);
}
}
}
/* programme principale */
class main{
public static void main(String[] args){
// detection de l'environement pour savoir si X est lancé.. plus tard, sinon via
// arguments lancé dans la commande, genre ${0} --gui pour le mode GUI.
// en attendant, une question est posée dans le terminal
Scanner sc = new Scanner(System.in);
CarreM carre;
System.out.print("CLI ou GUI ?\n 1. CLI\n 2. GUI\nVeuillez repondre par 1 ou 2 svp: ");
int choix = sc.nextInt();
if (choix == 1 | choix == 2){
System.out.println("La matrice sera un carré de combiens ? (ex: 3 => carré de 3x3)");
System.out.print("> ");
int nombre = sc.nextInt();
try{
carre = FabriqueCarreM.build(choix,nombre);
}catch (PasImpairException e){
System.out.println(e.getMessage());
}
} // else abandon
sc.close();
}
}
Ce que ca fait en images:
Partie en CLI:
(capture sur une version encore en phase beta)
Partie en GUI:
Bonne amusement
Hors ligne
Joli travail
Utiliser des logiciels propriétaires, c'est comme les plats préparés, on est incapable de dire les conservateurs qu'ils contiennent, on dira toujours que c'est bon, mais ça ne remplacera jamais le repas fait maison par sa maman.
]:D #! Crunchbang & Archlinux GNU/Linux User ]:D
Hors ligne
Bonsoir, merci pour ce partage !!!
Hors ligne
Pages : 1