Java

Aplety - Kółko i krzyżyk


Aplety - Kółko i krzyżyk

No to napiszemy sobie grę, która może uatrakcyjnić naszą stronę internetową. Zanim zaczniemy powinieneś/powinnaś zapoznać się z podstawami pisania apletów. Grą tą będzie kółko i krzyżyk, więc zastanówmy się jakich obiektów potrzebujemy.
1. Na pewno musi być jakiś element, który będzie pokazywał jaki jest stan gry(czyja kolej, kto wygrał). Wykorzystamy do tego metodę paint(), która narysuje nam informację o tym.
2. Teraz plansza do gry podzielona na 9 pól. Zrobimy ją z 9 przycisków button.
3. Jeszcze przyda się opcja rozpoczęcia gry od nowa, czyli jeszcze jeden przycisk.
Takie założenia przyjąłem ja gdy postanowiłem napisać tą gierkę, więc myślę że na początek to wystarczy. Na samym początku należy importować dwie klasy, które są bardzo często używane w apletach, mianowicie:


import java.awt.*;      // ta pozwala na umieszczanie przycisków itd.
import java.awt.event.*;  // ta pozwala na obsługę zdarzeń

u mnie plik z grą to kik.class więc piszę:
public class kik extends Applet implements ActionListener { // kik dziedziczy bezpośrednio z //klasy Applet i implementujemy klasę nasłuchującą zdarzenia(ActionListener)

Jest to niezbędne aby nasz program mógł reagować na zdarzenia(aby po kliknięciu pojawiło się na przycisku O lub X itd.). Teraz utworzymy zmienną, która będzie przechowywać stan gry:
String user = "O"; // grę będzie zaczynało kółko

Następnie należy zadeklarować obiekty - przyciski:
Button b1 = new Button(),
    b2 = new Button(),
    b3 = new Button(),
    b4 = new Button(),
    b5 = new Button(),
    b6 = new Button(),
    b7 = new Button(),
    b8 = new Button(),
    b9 = new Button(),
    we = new Button("Nowa Gra");

chyba można się domyślić, które przyciski do czego służyć nam będą. Teraz z przycisków zrobimy planszę( wrzucimy je do kontenera):
GridLayout - rozmieszczenie siatkowe, polega na rozmieszczeniu komponentów w prostokątnej siatce o podanej liczbie kolumn i wierszy; wszystkie klatki tej siatki mają identyczne rozmiary,

Panel gridLayoutPanel()
{
  Panel panel = new Panel();
  panel.setLayout(new GridLayout(3,3));>  // trzy kolumny i trzy wiersze(razem 9 pól)
  panel.add(b1); panel.add(b2); panel.add(b3);        //dodajemy przyciski
  panel.add(b4); panel.add(b5); panel.add(b6);
  panel.add(b7); panel.add(b8); panel.add(b9);
  return panel;
}

Teraz wywołamy metodę paint(), która będzie nam pokazywać jaki jest stan gry:

public void paint(Graphics g) //przykrywamy metodę paint()
 {
  g.drawString(user, 140, 70);        // wyświetla wartość Stringa user
  g.drawString("Stan gry/kolej:", 40, 70); //wyświetla napis do wartości user
} // aby gracz się nie pogubił ;)

Przyszła pora na inicjalizację apletu:
public void init() {
        Panel panel = gridLayoutPanel();
        setLayout(new BorderLayout());
        add("South",panel);
        b1.addActionListener(this);
        b2.addActionListener(this);
        b3.addActionListener(this);
        b4.addActionListener(this);
        b5.addActionListener(this);
        b6.addActionListener(this);
        b7.addActionListener(this);
        b8.addActionListener(this);
        b9.addActionListener(this);
    add("North",we);
    we.addActionListener(this);
    }

Na początku wrzucamy do apletu naszą planszę (panel), następnie każdy przycisk ustawiamy aby nasłuchiwał zdarzeń( aby mógł na nie reagować). Na końcu wrzucamy przycisk Nowa Gra i ustawiamy dla niego także ActionListener. Mamy już ustawione wszystko jeśli chodzi o interfejs graficzny naszej gry. Teraz należy oprogramować wciskanie przycisków. Do roboty:
public void actionPerformed(ActionEvent e) {
przesłonięcie metody actionPerformed, w tej części obsługuje się zdarzenia.
if(e.getSource() instanceof Button)
{
        System.out.println(((Button)e.getSource()).getLabel());

Tutaj pobieramy tzw. etykietę przycisku.
getSource() - informuje jaki przycisk został wciśnięty
getLabel() - informuje jaki jest napis na przycisku
dodam jeszcze bo się nam przyda:
setLabel() - ustawia teks na przycisku
Teraz obsłużymy ustawianie krzyżyka lub kółka na przycisku w zależności od graczy i tego czy na przycisku nie ma już jakiegoś znaku.

if (((Button)e.getSource()).getLabel()=="" &&  user == "X") { //jeśli nie ma napisu na                                                   //       przycisku, a jest kolej krzyżyka to
((Button)e.getSource()).setLabel("X");       //umieść na przycisku X
user = "O";                                        // zmień gracza na O
 repaint(); }                // przemaluj( bez tego nazwa zmiennej by się zmieniła ale napis nie) 
 
if (((Button)e.getSource()).getLabel()=="" &&  user == "O") {
((Button)e.getSource()).setLabel("O");
user = "X";
repaint(); }

No i teraz zostało nam jedynie sprawdzanie czy ktoś nie wygrał oraz obsłużenie przycisku NOWA GRA.
if (((Button)e.getSource()).getLabel()=="Nowa Gra") {        // jeśli wciśnięto nowa gra
  b1.setLabel(""); b2.setLabel(""); b3.setLabel(""); b4.setLabel("");
  b5.setLabel(""); b6.setLabel(""); b7.setLabel(""); b8.setLabel("");
  b9.setLabel("");
  user = "O"; repaint();
}      // wyczyść napisy na przyciskach oraz ustaw wartość user na początkową

I teraz najdłuższa część. Należy sprawdzić wszystkie możliwości w jakich ktoś może wygrać:
if (b1.getLabel() == "X" && b2.getLabel() == "X" && b3.getLabel() == "X") {
    user = "wygrał X"; repaint();
  }  else
    if (b4.getLabel() == "X" && b5.getLabel() == "X" && b6.getLabel() == "X") {
    user = "wygrał X"; repaint();
    }  else
    if (b7.getLabel() == "X" && b8.getLabel() == "X" && b9.getLabel() == "X") {
    user = "wygrał X"; repaint();
    }  else
    if (b1.getLabel() == "X" && b5.getLabel() == "X" && b9.getLabel() == "X") {
    user = "wygrał X"; repaint();
    }  else
    if (b3.getLabel() == "X" && b5.getLabel() == "X" && b7.getLabel() == "X") {
    user = "wygrał X"; repaint();
    }  else
    if (b1.getLabel() == "X" && b4.getLabel() == "X" && b7.getLabel() == "X") {
    user = "wygrał X"; repaint();
    }  else
    if (b2.getLabel() == "X" && b5.getLabel() == "X" && b8.getLabel() == "X") {
    user = "wygrał X"; repaint();
    }  else
    if (b3.getLabel() == "X" && b6.getLabel() == "X" && b9.getLabel() == "X") {
    user = "wygrał X"; repaint();
    }  else
 
    if (b1.getLabel() == "O" && b2.getLabel() == "O" && b3.getLabel() == "O") {
user = "wygrało O"; repaint();
}  else
    if (b4.getLabel() == "O" && b5.getLabel() == "O" && b6.getLabel() == "O") {
    user = "wygrało O"; repaint();
    }  else
    if (b7.getLabel() == "O" && b8.getLabel() == "O" && b9.getLabel() == "O") {
    user = "wygrało O"; repaint();
    }  else
    if (b1.getLabel() == "O" && b5.getLabel() == "O" && b9.getLabel() == "O") {
    user = "wygrało O"; repaint();
    }  else
    if (b3.getLabel() == "O" && b5.getLabel() == "O" && b7.getLabel() == "O") {
    user = "wygrało O"; repaint();
    }  else
    if (b1.getLabel() == "O" && b4.getLabel() == "O" && b7.getLabel() == "O") {
    user = "wygrało O"; repaint();
    }
          else
    if (b2.getLabel() == "O" && b5.getLabel() == "O" && b8.getLabel() == "O") {
    user = "wygrało O"; repaint(); }
    else
    if (b3.getLabel() == "O" && b6.getLabel() == "O" && b9.getLabel() == "O") {
    user = "wygrało O"; repaint();
    } else if (b1.getLabel() != "" && b2.getLabel() != "" && b3.getLabel() != "" &&
      b4.getLabel() != "" && b5.getLabel() != "" && b6.getLabel() != "" &&
      b7.getLabel() != "" && b8.getLabel() != "" && b9.getLabel() != "")
    { user ="REMIS !!!"; }


Na końcu jeżeli żaden z warunków nie jest spełniony, a jednak wszystkie przyciski są "zapisane" to wyskakuje słówko REMIS!!! To wszystko jest może długim kodem ale za to bardzo prostym. Jeśli trzy przyciski o tym samy napisie leżą w jednej linii to wtedy wyskakuje odpowiedni napis:
 

if (b3.getLabel() == "O" && b6.getLabel() == "O" && b9.getLabel() == "O") {
    user = "wygrało O"; repaint();

użyto tu operatora && aby otrzymać informacje czy trzy przyciski tworzące jedną linię mają ten sam napis("O").        W przypadku jakiś wątpliwości proszę pisać do mnie.


Może na koncu podam cały kod tak na wszelki wypadek :).
( w dziale Kody źródłowe - Java)

14 komentarzy

prezi84 2009-12-19 00:06

sprawdzanie wszystkich warunków przy korzystaniu z tablic wygląda tak:
    public boolean isWinner(String s) {
        if( (b[0].getLabel() == s && b[1].getLabel() == s && b[2].getLabel() == s) ||
            (b[3].getLabel() == s && b[4].getLabel() == s && b[5].getLabel() == s) ||
            (b[6].getLabel() == s && b[7].getLabel() == s && b[8].getLabel() == s) ||
            (b[0].getLabel() == s && b[4].getLabel() == s && b[8].getLabel() == s) ||
            (b[2].getLabel() == s && b[4].getLabel() == s && b[6].getLabel() == s) ||
            (b[0].getLabel() == s && b[3].getLabel() == s && b[6].getLabel() == s) ||
            (b[1].getLabel() == s && b[4].getLabel() == s && b[7].getLabel() == s) ||
            (b[2].getLabel() == s && b[5].getLabel() == s && b[8].getLabel() == s) )
            return true;
        return false;
    }
i wywołanie
        if(isWinner(krzyzyk)) { napis = "wygrał "+krzyzyk; repaint(); } else
        if(isWinner(kolko)) { napis = "wygrało "+kolko; repaint(); }  else
        for(int i=0; i<9; i++) {
            if(b[i].getLabel() == "")
                break;
            if(i==8) napis ="REMIS !!!";
        }
Cały program przy korzystaniu z tablic i małej optymalizacji zajmuje niecałe 70 linii

@Programista312 - jakie łatwiejsze sposoby niby są niż sprawdzanie tych raptem 8 warunków? Toż nawet stworzenie pętli, sprawdzającej czy tokeny są ustawione w rzędach lub kolumnach zajmie więcej niż 8 linii kodu.

prezi84 2009-12-18 02:19

działa fajnie, doskonały pomysł z tymi przyciskami
jednak kod strasznie nadmiarowy - można to znacznie krócej napisać, np. używając tablic:
Button [] b = new Button[9];
i wszędzie stosować pętle:
      for(int i=0; i<9; i++)
          b[i] ...
sprawdzanie warunków też wtedy można znacznie uprościć

longman 2006-05-28 14:48

działa, ale jak by wyglądał kod z jakimś gif'em jako plansza i rysowanymi "o" i "x"? Ile z tego pozostanie kodu?

longman 2006-05-28 14:46

działa, ale jak by wyglądał kod z jakimś gif'em jako plansza i rysowanymi "o" i "x"? Ile z tego pozostanie kodu?

Programista312 2009-01-01 22:17

Wypisywać wszystkie kombinacje ,są łatwiejsze sposoby!

dawciobiel 2004-11-22 06:19

juz ok, dodałem tam jeszcze
"import java.applet.*;"
i stworzyłem kik.html :
"<APPLET CODE="kik.class" WIDTH="250" HEIGHT="250"></APPLET>"

jaro. 2004-05-10 14:59

Dziekuje,

dla mnie się przydał!

Na jego podstawie zaliczylem applet dla uniwerku.

MrGhost 2003-10-25 11:35

Bardzo dobry artykuł...

RiccoXXX 2003-06-11 20:56

Czytelnosc mniej istotna, sam artykul calkiem dobry.

Marooned 2003-05-03 11:11

Cały kod w znacznikach &lt; b > - bardzo nieczytelny.