Cześć!
Dla poćwiczenia Swinga napisałem w Javie grę kółko i krzyżyk :)
Podzieliłem ten projekt na 3 klasy:
- Element – klasa dziedziczy po JButton – i jest elementem na planszy.
- ElementListener – obsługa kliknięć.
- KolkoIKrzyzyk – klasa z main’em.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | package kolkoikrzyzyk; import java.awt.Dimension; import java.awt.GridLayout; import javax.swing.JFrame; import javax.swing.JPanel; /** * * @author Matt */ public class KolkoIKrzyzyk extends JFrame{ /** * @param args the command line arguments */ public static void main(String[] args) { KolkoIKrzyzyk kik = new KolkoIKrzyzyk(); kik.setMinimumSize(new Dimension(400, 400)); kik.setDefaultCloseOperation(EXIT_ON_CLOSE); kik.setResizable(false); kik.setTitle("Gra w Kółko i Krzyzyk"); JPanel plansza = new JPanel(); plansza.setLayout(new GridLayout(3,3)); Element a[][]= new Element[3][3]; int wyniki[][]= new int[3][3]; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { a[i][j]= new Element(); wyniki[i][j]=0; } } for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { a[i][j].addActionListener(new ElementsListener(a, wyniki, plansza)); plansza.add(a[i][j]); } } kik.add(plansza); kik.setVisible(true); } } |
Tutaj nic bardzo skomplikowanego się nie dzieje. Tworzymy layout – czyli Grida z elementami naszej klasy dziedziczącej po JButton i każdemu przypisujemy ActionListener – czyli nasz ElementListener.
Kolejną klasą którą przedstawę będzie klasa Element.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public class Element extends JButton{ int stan=0; public Element() { } @Override public void paint(Graphics g) { super.paint(g); if(stan == 1) { g.drawLine(0, 0, 160, 150); g.drawLine(130, 0, 0, 120); } else if(stan==2) { g.drawOval(10, 10, 110, 110); } } } |
Klasa ma swoj stan. Domyślnie jest to stan 0. Zmienna odpowiedzialna za stan jest publiczna więc nie ma żadnych setterów. Od jej wartości jest uzależnione to co będzie na tym obiekcie rysowane. Jeśli stan = 1 to rysujemy dwie kreski (krzyżyk) jeśli 2 to koło. I w sumie tyle ;)
3 klasa jest odpowiedzialna za całą logikę gry. Nie jest ona jakoś super napisana, ale działa :) Szczególnie sam algorytm napisany jest kiepsko, tzn zakłada każdą możliwość wygrania ale jest napisany na zwykłych ifach. Tak czy siak, oto klasa:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | package kolkoikrzyzyk; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Random; import javax.swing.JOptionPane; import javax.swing.JPanel; /** * * @author Matt */ public class ElementsListener implements ActionListener{ private Element[][] elemenst; private int[][] ints; JPanel plansza; public ElementsListener(Element[][] el, int[][] w, JPanel p) { elemenst=el; ints=w; plansza=p; } private boolean sprawdz(int a, boolean t) { if(a==1){ //===== poziom if(ints[0][0]==1 && ints[0][1]==1 && ints[0][2]==1) { if(t) JOptionPane.showMessageDialog(null, "Wygrales!!"); return true; } if(ints[1][0]==1 && ints[1][1]==1 && ints[1][2]==1) { if(t) JOptionPane.showMessageDialog(null, "Wygrales!!"); return true; } if(ints[2][0]==1 && ints[2][1]==1 && ints[2][2]==1) { if(t) JOptionPane.showMessageDialog(null, "Wygrales!!"); return true; } } if(a==2){ //==== pion dla usera if(ints[0][0]==1 && ints[1][0]==1 && ints[2][0]==1) { if(t) JOptionPane.showMessageDialog(null, "Wygrales!!"); return true; } if(ints[0][1]==1 && ints[1][1]==1 && ints[2][1]==1) { if(t) JOptionPane.showMessageDialog(null, "Wygrales!!"); return true; } if(ints[0][2]==1 && ints[1][2]==1 && ints[2][2]==1) { if(t) JOptionPane.showMessageDialog(null, "Wygrales!!"); return true; } if(ints[0][0]==1 && ints[1][1]==1 && ints[2][2]==1) { if(t) JOptionPane.showMessageDialog(null, "Wygrales!!"); return true; } if(ints[0][2]==1 && ints[1][1]==1 && ints[2][0]==1) { if(t) JOptionPane.showMessageDialog(null, "Wygrales!!"); return true; } if(ints[0][2]==2 && ints[1][1]==2 && ints[2][0]==2) { if(t) JOptionPane.showMessageDialog(null, "Wygral komputer!!"); return true; } if(ints[0][0]==2 && ints[0][1]==2 && ints[0][2]==2) { if(t) JOptionPane.showMessageDialog(null, "Wygral komputer!!"); return true; } if(ints[1][0]==2 && ints[1][1]==2 && ints[1][2]==2) { if(t) JOptionPane.showMessageDialog(null, "Wygral komputer!!"); return true; } if(ints[2][0]==2 && ints[2][1]==2 && ints[2][2]==2) { if(t) JOptionPane.showMessageDialog(null, "Wygral komputer!!"); return true; } //========== w dol to pion if(ints[0][0]==2 && ints[1][0]==2 && ints[2][0]==2) { if(t) JOptionPane.showMessageDialog(null, "Wygral komputer!!"); return true; } if(ints[0][1]==2 && ints[1][1]==2 && ints[2][1]==2) { if(t) JOptionPane.showMessageDialog(null, "Wygral komputer!!"); return true; } if(ints[0][2]==2 && ints[1][2]==2 && ints[2][2]==2) { if(t) JOptionPane.showMessageDialog(null, "Wygral komputer!!"); return true; } if(ints[0][0]==2 && ints[1][1]==2 && ints[2][2]==2) { if(t) JOptionPane.showMessageDialog(null, "Wygral komputer!!"); return true; } } return false; } @Override public void actionPerformed(ActionEvent e) { Element source = (Element) e.getSource(); int x = 0,y = 0; boolean koniec = false; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { if(elemenst[i][j]== source)// [1] { x=i; y=j; break; } } } elemenst[x][y].stan=1;[2] ints[x][y]=1;[2] koniec = sprawdz(1, true);[2] if(koniec) { for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { elemenst[i][j].stan=0;[3] ints[i][j]=0;[3] } } plansza.repaint();[3] } Random rn = new Random(); int rn1=0,rn2=0; int time=0; if(koniec == false) {[4] while(true) { time++; rn1=rn.nextInt(3);[4] rn2=rn.nextInt(3); [4] if(time>70)[5] { koniec=true;[5] break;[5] } if(elemenst[rn1][rn2].stan == 0) {[6] elemenst[rn1][rn2].stan=2; ints[rn1][rn2]=2;[6] break; } else { continue; } } } plansza.repaint(); koniec=sprawdz(2, true);[7] boolean end=true; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { if(ints[i][j]==0) end = false; } } if(sprawdz(1, false)==false && sprawdz(2, false)==false && end == true) {[8] JOptionPane.showMessageDialog(null, "Remis!"); koniec=true; } if(koniec)[9] { for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { elemenst[i][j].stan=0; ints[i][j]=0; } } plansza.repaint();[9] koniec=false; } }} |
Co tu robimy? Do konstruktora przekazujemy tablicę elementów z planszy, odpowiadające im wartości intów i samą planszę żeby można było ją odświeżyć po kliknięciu (repaint()).
Metoda sprawdź to owe nieszczęsne ify ;) przyjmuje 2 argumenty – jeśli pierwszy argument jest 1 to sprawdza czy użytkownik wygrał a jeśli 2 to czy komputer. Jeśli drugi argument jest true to wyświetla okienko powiadamiające o ewentualnej wygranej.
[1] Szukam w tablicy Elementów obiektu który został naciśnięty zeby móc go zmienić.
[2] Ustawiam stan na „Krzyżyk” i sprawdzam ewentualną wygraną.
[3] Jeśli nastąpiła wygrana to czyszczę planszę i odświeżam ją – gra zaczyna się od początku.
[4] Jeśli nie nastąpiła wygrana to losuję ruch komputera.
[5] Jeśli 70 razy komputer nie zdołał znaleźć pola które jest puste to zakładam remis.
[6] Jeśli znalazł to stawiamy kółko.
[7] Sprawdzamy wygraną komputera.
[8] Jeśli nie wygrał komputer ani człowiek a gra nie ma statusu zakończonej to jest remis.
[9] Czyszczę i odświeżam planszę.
Mateusz Mazurek
Super pomocna strona :) fajnie wytłumaczone.
Mam Tylko dylemat jak można było by poprawić stan losowania przez komputer kolejnego ruchu?