Gra bez użycia instrukcji if

0

Mamy napisać grę Sokoban, nie używając intrukcji if.
Mam problem z jedną funkcją.

Mam klasę abstrakcyjną Pole po którym dziedziczą Puste, Skrzynia, Ludzik,Mur.

Klasa Plansza zawiera pozycję ludzika i tablicę dwuwymiarową Pól, na razie 6x6.
Mam problem z działaniem tej funkcji z klasy plansza:

  public void przesunSkrzynie(int ax,int ay,int bx, int by)//współrzędne skrzyni i pola docelowego
  {
      try{
   Pole tmp=pola[ax][ay].copy();
   //zapamietuje jakie bylo tu pole, zwraca nowy obiekt klasy puste,mur itp w zależności czym było
   Pole nowaPozycja= pola[ax][ay].przesun(pola[bx][by]);
   /*ta funkcja ma zwrócić miejsce w tablicy w którym ma znaleźć się przesuwane pole. Konstrukcja jest dziwna ponieważ nie mogę używać if więc korzystam z polimorfizmu.
   znajduje nowa pozycje dla przesuwanego pola, zwraca this albo argument jeśli wywołano ją na skrzynce. Czyli jeśli to nie skrzynia, lub jeśli skrzyni nie można przesunąć zwróci pola[ax][ay] a jeśli to skrzynia to zwróci puste pole czyli pola[bx][by], niby to działa ale później jak robie tak: */
   pola[ax][ay]=new Puste();//ok wstawiam tu puste pole, usuwam to co tu stało
   nowaPozycja=tmp;/*i tu powinno to wrzucić do tablicy ten obiekt który był przedtem pod indeks ax,ay, którego skopiowałem, jeśli to nie skrzynia wstawiony jest w to samo miejsce, jeśli to skrzynia przesuwane jest dalej, ale tego nie robi nie wiem czemu, wygląda tak jakby rezultat zwracany przez przesuń nie był referencją.
*/

   }catch(ArrayIndexOutOfBoundsException e){};
      
  }


A tak wygląda funkcja przesuń dla Skrzynia:

public Pole przesun(Pole docelowe){return docelowe;}
Czyli zwróci pole na które ma zostać przeniesione, wiem na razie że nie sprawdzam czy coś nie stoi na drodze ale to tylko do testów używam. Teraz powinno przesunąć skrzynie niezależnie od tego co stoi za nią, ale skrzynia po prostu znika i na planszy nie jest tworzona nowa.

W javie dopiero od paru dni programuje, wcześniej bylo C i C++ i nie mogę się w tym połapać. Chodzi mi o to żeby funkcja przesuń działała jak taka funkcja w C++: pole.przenies(pole2) zwraca to wskaźnik albo na pole albo na pole2 w zależności jakiego jest dokładnie typu, tym zajmie się polimorfizm i później tylko bym sobie wpisał pod ten adres coś innego, typu Pole.

0

Do opisu typu pola nie używaj hierarchii klas, a enumów. Można wtedy zamiast if użyć switch'a.

public void przesun(Pole cel){
switch(cel.typ)
case TYP.Skrzynia:
//...
case TYP.Sciana:
//...
case Typ.Puste:
//...
}

Ciężko napisać program bez instrukcji decyzyjnych, ale z drugiej strony należy sobie w życiu radzić.

0

if można łatwo zastąpić przez while:

if (X) {
  C;
}

da ten sam wynik co:

F = true;
while (F && X) {
  C;
  F = false;
}

albo:

for (F = true; F; F = false) {
  C;
}

ewentualnie poprzez try-catch:

try {
  checkTrue(X); // rzuca wyjątek TrueException jeśli warunek jest prawdziwy
} catch (TrueException ex) {
  C;
}

no albo z użyciem polimorfizmu. Tak, że warunek na brak ifów w kodzie jest trochę niepoważny.

0

Nie można używać if, switch a nawet pętli, dozwolona jest jedna lub 2 pętle.

Uproszczając chodzi mi o to jak zrobić coś takiego:

Pole tablica[][];
Pole cos=tablica[2][3];
cos=new Skrzynka();

Jak właśnie zrobić tak, żeby odwołać się do elementu [2][3], zmienić go na Skrzynkę za pośrednictwem zmiennej cos? Bo teraz coś takiego nic nie robi, tablica[2][3] pozostaje bez zmian. W javie nigdy nie pisałem, to jest pierwszy program :D No drugi po hello world:P

W C++ bym trzymał tylko wskaźnik do tego elementu i później bym dal new Skrzynka().
Ale w javie podobno są referencje więc to co napisałem powinno zadziałać, ale nie działa.

0

EDIT:

michal_abcd napisał(a)

Pole tablica[][];
Pole cos=tablica[2][3];
cos=new Skrzynka();
Jak właśnie zrobić tak, żeby odwołać się do elementu [2][3], zmienić go na Skrzynkę za pośrednictwem zmiennej cos? Bo teraz coś takiego nic nie robi, tablica[2][3] pozostaje bez zmian.

Nie da się...

0

@michal_abcd
a nie łatwiej zmienić wartość tego tablica[2][3] ?
cos jest referencja do tablica[2][3] więc jeśli zmienisz wartości pól tego obiektu to zmisz tez wartści w tablicy.
Tzn jeśli np. Pole ma metodę zmien_skladnik();
To jeśli zrobisz cos.zmien_skladnik(); to w obiekcie tablica[2][3] ten składnik sie zmieni.

0

@keraj, co się nie da? To jest ćwiczenie opierające się na projektowaniu obiektowym, sensownie użytym polimofizmie i ew. wyjątkach. Zgodnie z kanonami OOP da się, bez większych problemów - odpowiednia dekompozycja + jeden czy dwa wzorce projektowe.

Swoją drogą ciekawie pisałoby się takie rzeczy w języku z multimetodami, jak Common Lisp. W sumie to najciekawsze zadanie jakie na 4p od miesięcy widziałem.

0

Próbowałem tak ale nie działa. Bo jeśli np. w pola[2][3] to jest pole puste i chcę wpisać tam skrzynkę to w metoda zmień w Puste by wyglądała tak:
this=new Skrzynka() a tak chyba nie można zrobić. W tablicy trzymam pola puste, skrzynki i ludzika i później używając polimorfizmu chcę się przesuwać.

No ale skoro się tak nie da rady to będę musiał do funkcji zmień przekazać dodatkowo pozycję w tablicy pola zamienianego i docelowego :/ Albo dodać do Pola dodatkowy składnik określający jego pozycje, ale gościowi się to nie za bardzo podobało.

0

Łatwiej by bylo jakbyś pokazał jak to wygląda w troche szerszym zakresie, tzn jakiś diagram uml jak to zaprojektowałeś, albo przynajmniej hierarchie klas i powiązania.

0

Rzeczywiście zadanie nietrywialne. Dobra... popatrzmy na to w taki sposób.

class Puste() extends Pole{

void umiesc(){

}

}

class Pelne() extends Pole{
void umiesc(){
 throw new IllegalStateException();
}
}

Teraz logika przesuwania:

przesun(Pole cel, Pole zrodlo){

try{
// jak to nie jest mozliwe to rzuca wyjatek i nie kontynuuje przesuwania.
cel.umiesc();
// przepianie tablicy z nowymi obiektami dla cel.pozycja(), i zrodlo.pozycja();

}
catch(ise){
// olewasz choć jest to zuo ;)
}

}

Pytanie jak sprawdzić, że dane pola są sąsiadami. Hm... znacznie ciekawsze pytanie.

0

Przerobiłem trochę kod, rozwiązałem problem ale nie do końca tak jak chciałem.

Zrezygnowałem z tablicy 2 wymiarowej na rzecz jedno wymiarowej, teraz będzie mniej argumentów do przekazania.

Więc mam klasę Plansza, ona zawiera tablicę z Polami. Domyślnie zrobię wczytywanie z jakiegoś pliku, ale chyba bez pętli się tego też nie zrobi i bez if. Może na zajęciach zostanie wyjaśnione czy da się to zrobić czy nie. Na razie na poniedziałek mamy zrobić rysowanie planszy i poruszanie ludzika/ przesuwanie skrzynek. Na razie mam konsolowo, trzeba w graficznym.
Czego najlepiej użyć? Są jakieś fajne biblioteki do tego? (nie wiem czy w javie to się tak nazywa :D) Mam netbeans i tam chyba można poukładać sobie okienko z "klocków". Gdzie można znaleźć dobre tutki do robienia grafiki, buttonów, czytania z klawiatury, wyświetlania bitmap itp. Ogólnie funkcje użyteczne przy tworzeniu gier.

A teraz wracając do tego przesuwania, w klasie Plansza mam metody wGore(), w Dol() itd.
np. metoda wGore() wygląda tak:

public void wGore()
  {
    pola[pozycja+GORA].przesun(this, pozycja+GORA, GORA);
    pola[pozycja].przesun(this, pozycja, GORA);
  }

Działa ona tak, że jak chcę przesunąć ludzika w górę, najpierw przesuwane jest Pole nad nim, a później ludzik.

Funkcja przesun(Plansza,pozycja,kierunek) jest metodą wirtualną Pola, wykonuje one jakieś działanie tylko dla skrzyni i ludzika, bo tylko je można przesuwać.
Dla ludzika i skrzynki wygląda tak:

public void przesun (Plansza p,int przesuwany,int kierunek)
{
    p.pola[przesuwany+kierunek].swap(p, przesuwany+kierunek,przesuwany);
}

I znowu, swap coś zrobi, tylko jeśli przemieszczamy się na puste pole.
Jeszcze mam jedną metodę wirtualna, w Polu: aktualizujPozycje, która dla ludzika wykonuje:

public void aktualizujPozycje(Plansza p, int mojaPozycja){p.pozycja=mojaPozycja;}

W moim rozwiązaniu nie podoba mi się to, że do metod Pola przekazuję Plansze. Macie pomysł jak tego uniknąć?

0
... napisał(a)

@keraj, co się nie da? To jest ćwiczenie opierające się na projektowaniu obiektowym, sensownie użytym polimofizmie i ew. wyjątkach. Zgodnie z kanonami OOP da się, bez większych problemów - odpowiednia dekompozycja + jeden czy dwa wzorce projektowe.
Kurdę, zapomniałem dać cytatu...
Nie da się przekazać referencji do miejsca, tylko do obiektu...
Jak to ktoś ujął, w Javie nie przekazuje się przez referencje, a przez wartość, którą może być referencją do obiektu...

0

Ekhm, przepraszam, źle zinterpretowałem wypowiedź.

Dosyć proste rozwiązanie części problemów - złożyć planszę jako tablicę dwuwymiarową z pól-kontenerów - dziura, puste i ściana (oczywiście nic nie trzyma), do tego 'zawartość' - ludź/kamień. Odpadają problemy z przemieszczaniem/swapowaniem, najprościej to z visitorem poskładać + ew. wyjątkami. To tylko taka sugestia, bo można to na co najmniej kilka innych sposobów rozwiązać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1