Bataille navale avec affichage graphique fenêtré
/* Auteur: Nicolas JANEY */
/* nicolas.janey@univ-fcomte.fr */
/* Fevrier 2005 */
import java.awt.*;
import java.awt.event.*;
import java.io.*;
/* La classe contient une fonction principale */
/* d'utilisation en tant qu'application. */
/* Elle etend la classe Frame pour la creation */
/* d'une fenetre. */
/* Elle implemente les interfaces WindowListener, */
/* ActionListener et MouseListener pour autoriser */
/* la gestion des evenements fenetre, action et souris. */
public class BatailleNavaleGraphique extends Frame
implements WindowListener,
ActionListener,
MouseListener {
/* Objets menu */
private MenuBar mb = new MenuBar();
private Menu m1 = new Menu("Fichier");
private MenuItem mnj = new MenuItem("Nouveau jeu");
private MenuItem mq = new MenuItem("Quitter");
/* Chaine de caracteres affichee sur le plateau de jeu */
private String message ="";
/* Position de la souris lors d'un clic */
private int mousex = -1;
private int mousey = -1;
/* Description du plateau de jeu */
private static int [][] tst;
/* Description de la flote */
private static boolean [][] fl;
/* Constructeur */
public BatailleNavaleGraphique() {
/* Appel au constructeur de la super-classe Frame */
/* pour donner un titre a la fenetre */
super("Bataille navale");
/* Ajout d'un ecouteur de fenetre a la fenetre */
/* pour gerer les evenements fenetre */
/* L'ecouteur est l'objet BatailleNavaleGraphique */
/* lui-meme qui etend l'interface WindowListener */
addWindowListener(this);
/* Ajout d'un ecouteur de souris a la fenetre */
/* pour gerer les evenements souris */
/* L'ecouteur est l'objet BatailleNavaleGraphique */
/* lui-meme qui etend l'interface MouseListener */
addMouseListener(this);
/* Ajout d'une barre de menu a la fenetre */
setMenuBar(mb);
/* Ajout des menus a la barre de menu */
mb.add(m1);
m1.add(mnj);
m1.addSeparator();
m1.add(mq);
/* Ajout d'un ecouteur d'action aux menus idoines */
/* pour gerer leurs evenements d'activation */
/* L'ecouteur est l'objet BatailleNavaleGraphique */
/* lui-meme qui etend l'interface ActionListener */
mq.addActionListener(this);
mnj.addActionListener(this);
/* Le blanc est la couleur de fond de la fenetre */
setBackground(Color.white);
/* Ajustement de la taille de la fenetre en fonction */
/* de la taille du plateau de jeu */
setSize(24*tst.length+8,24*tst.length+72);
/* Activation de la fenetre */
setVisible(true);
}
/* Test si un bateau est present en (x,y) */
public boolean bateauPresent(int x,int y) {
if ( !dansTableau(fl,x,y) )
return(false);
return(fl[y][x]);
}
/* Test si le bateau present en (x,y) est coule */
public boolean bateauCoule(int x,int y) {
boolean sens = true;
int xi = x;
int yi = y;
while ( ( yi >= 0 ) && ( bateauPresent(xi,yi-1) ) ) {
yi--;
sens = true; }
while ( ( xi >= 0 ) && ( bateauPresent(xi-1,yi) ) ) {
xi--;
sens = false; }
int xf = xi;
int yf = yi;
while ( ( yf < fl.length ) && ( bateauPresent(xf,yf+1) ) ) {
yf++;
sens = true; }
while ( ( xf < fl.length ) && ( bateauPresent(xf+1,yf) ) ) {
xf++;
sens = false; }
if ( sens ) {
for ( y = yi ; y <= yf ; y++ )
if ( tst[y][xi] != 1 )
return(false); }
else {
for ( x = xi ; x <= xf ; x++ ) {
if ( tst[yi][x] != 1 )
return(false); } }
return(true);
}
/* Test de la fin du jeu */
public boolean testJeuFiniBatailleNavale() {
for ( int y = 0 ; y < fl.length ; y++ )
for ( int x = 0 ; x < fl.length ; x++ )
if ( ( fl[y][x] ) && ( tst[y][x] != 1 ) )
return(false);
return(true);
}
/* Calcul du carre de la distance entre deux positions */
public int distance2(int x1,int y1,int x2,int y2) {
int dx = x2-x1;
int dy = y2-y1;
return(dx*dx+dy*dy);
}
/* Lecture d'une position jouee */
public int [] positionEssai() {
int [] pos = new int[2];
boolean good = false;
do {
while ( ( mousex == -1 ) && ( mousey == -1 ) )
try {
Thread.sleep(200); }
catch ( Exception e ) { };
for ( int y = 0 ; y < tst.length ; y++ )
for ( int x = 0 ; x < tst[y].length ; x++ ) {
int px = 12+24*x;
int py = 60+24*y;
if ( distance2(px,py,mousex,mousey) < 100 ) {
pos[0] = x;
pos[1] = y;
mousex = -1;
mousey = -1;
return(pos); } }
mousex = -1;
mousey = -1; }
while ( !good );
return(pos);
}
/* Fonction principale de gestion du jeu */
public void batailleNavale() {
int nbt = 0;
while ( !testJeuFiniBatailleNavale() ) {
nbt++;
repaint();
int [] pos = positionEssai();
if ( fl[pos[1]][pos[0]] ) {
tst[pos[1]][pos[0]] = 1;
message = "Bateau en ("+pos[0]+","+pos[1]+")";
if ( bateauCoule(pos[0],pos[1]) )
message = "Bateau coule!"; }
else {
tst[pos[1]][pos[0]] = 0;
message = "Pas de bateau en ("+pos[0]+","+pos[1]+")"; } }
message = "Toute la flote est coulee en "+nbt+" tours";
repaint();
}
/* Affichage du plateau de jeu */
public void paint(Graphics g) {
for ( int y = 0 ; y < tst.length ; y++ ) {
for ( int x = 0 ; x < tst.length ; x++ )
switch ( tst[y][x] ) {
case -1 : g.drawLine(12+24*x,60+24*y,12+24*x,60+24*y);
break;
case 0 : g.drawRect(10+24*x,58+24*y,4,4);
break;
case 1 : g.drawLine(10+24*x,58+24*y,14+24*x,62+24*y);
g.drawLine(10+24*x,62+24*y,14+24*x,58+24*y);
break; } }
g.drawString(message,10,58+tst.length*24);
}
/* Reinitialisation du jeu */
public void nouveauJeu() throws IOException {
/* Creation d'une nouvelle flote */
fl = initFlote();
/* Creation d'un nouveau plateau */
tst = initPlateau(fl);
/* Effacement du message de la fenetre */
message ="";
/* Redimensionnement de la fenetre */
setSize(24*tst.length+8,24*tst.length+72);
/* Reaffichage du plateau de jeu */
repaint();
}
/* Reactions aux evenements fenetre */
public void windowActivated(WindowEvent e) {
}
public void windowClosed(WindowEvent e) {
}
public void windowClosing(WindowEvent e) {
/* Interruption du programme */
System.exit(0);
}
public void windowDeactivated(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowOpened(WindowEvent e) {
}
/* Reaction aux evenements action */
public void actionPerformed(ActionEvent e) {
/* Si l'entree de menu "Quitter" est utilisee */
if ( e.getSource() == mq ) {
/* Interruption du programme */
System.exit(0); }
/* Si l'entree de menu "Nouveau jeu" est utilisee */
if ( e.getSource() == mnj ) {
/* Reinitialisation du jeu via la fonction nouveauJeu */
try {
nouveauJeu(); }
catch (IOException ioe) {} }
}
/* Reaction aux evenements souris */
/* Si la souris est cliquee */
public void mouseClicked(MouseEvent e) {
/* Affectation des variables mousex et mousey */
/* avec les coordonnees de la souris */
mousex = e.getX();
mousey = e.getY();
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
/* Fonctions de generation aleatoire d'une flotte */
/* de navires sur un plateau de jeu */
static BufferedReader flux = new BufferedReader(new InputStreamReader(System.in));
public static boolean dansTableau(boolean [][] t,int xi,int yi) {
if ( xi < 0 )
return(false);
if ( yi < 0 )
return(false);
if ( xi >= t.length )
return(false);
if ( yi >= t.length )
return(false);
return(true);
}
public static boolean placementPossible(boolean [][] t,int xi,int yi,int xf,int yf,int sens) {
if ( !dansTableau(t,xi,yi) )
return(false);
if ( !dansTableau(t,xf,yf) )
return(false);
if ( sens == 0 ) {
for ( int x = xi-1 ; x <= xf+1 ; x++ )
for ( int y = yi-1 ; y <= yi+1 ; y++ )
if ( dansTableau(t,x,y) )
if ( t[y][x] )
return(false); }
else {
for ( int x = xi-1 ; x <= xi+1 ; x++ )
for ( int y = yi-1 ; y <= yf+1 ; y++ )
if ( dansTableau(t,x,y) )
if ( t[y][x] )
return(false); }
return(true);
}
public static void place(boolean [][] t,int xi,int yi,int xf,int yf,int sens) {
if ( sens == 0 ) {
for ( int x = xi ; x <= xf ; x++ )
t[yi][x] = true; }
else {
for ( int y = yi ; y <= yf ; y++ )
t[y][xi] = true; }
}
public static void placeBateau(int taille,boolean [][] t) {
int xi,yi,xf = 0,yf = 0;
int sens;
do {
xi =(int) (Math.random() * t.length);
yi =(int) (Math.random() * t.length);
sens =(int) (Math.random() * 4);
switch (sens) {
case 2 : xf = xi;
yf = yi+taille-1;
break;
case 3 : xf = xi;
yf = yi;
yi = yf-taille+1;
break;
case 0 : yf = yi;
xf = xi+taille-1;
break;
case 1 : yf = yi;
xf = xi;
xi = xf-taille+1;
break; } }
while ( !placementPossible(t,xi,yi,xf,yf,sens/2) );
place(t,xi,yi,xf,yf,sens/2);
}
public static boolean [][] genereFlote(int n,int n1,int n2,int n3,int n4, int n5) {
boolean [][] t = new boolean[n][n];
for ( int i = 0 ; i < n ; i++ )
for ( int j = 0 ; j < n ; j++ )
t[i][j] = false;
for ( int i = 0 ; i < n5 ; i++ )
placeBateau(5,t);
for ( int i = 0 ; i < n4 ; i++ )
placeBateau(4,t);
for ( int i = 0 ; i < n3 ; i++ )
placeBateau(3,t);
for ( int i = 0 ; i < n2 ; i++ )
placeBateau(2,t);
for ( int i = 0 ; i < n1 ; i++ )
placeBateau(1,t);
return(t);
}
/* Fonction principale */
public static boolean [][] initFlote() throws IOException {
/* Lecture au clavier de la taille du damier */
System.out.print("Taille du damier : ");
int n = Integer.valueOf(flux.readLine()).intValue();
/* Lecture au clavier des nombres de bateaux */
/* de taille 1, 2, 3, 4 et 5 */
System.out.println("Nombres de bateaux : ");
System.out.print("Taille 1 : ");
int n1 = Integer.valueOf(flux.readLine()).intValue();
System.out.print("Taille 2 : ");
int n2 = Integer.valueOf(flux.readLine()).intValue();
System.out.print("Taille 3 : ");
int n3 = Integer.valueOf(flux.readLine()).intValue();
System.out.print("Taille 4 : ");
int n4 = Integer.valueOf(flux.readLine()).intValue();
System.out.print("Taille 5 : ");
int n5 = Integer.valueOf(flux.readLine()).intValue();
/* Generation de la flote sur le damier */
return(genereFlote(n,n1,n2,n3,n4,n5));
}
public static int [][] initPlateau(boolean [][] fl) throws IOException {
/* Generation et initialisation du tableau */
/* des cases testees */
int [][] tst = new int[fl.length][fl[0].length];
for ( int i = 0 ; i < fl.length ; i++ )
for ( int j = 0 ; j < fl[0].length ; j++ )
tst[i][j] = -1;
return(tst);
}
public static void main(String [] args) throws IOException {
/* Initialisation du jeu */
fl = initFlote();
tst = initPlateau(fl);
/* Lancement du jeu */
BatailleNavaleGraphique bng = new BatailleNavaleGraphique();
bng.batailleNavale();
}
}
Auteur: Nicolas JANEY
UFR Sciences et Techniques
Université de Besançon
16 Route de Gray, 25030 Besançon
nicolas.janey@univ-fcomte.fr