/* 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(); } }