Kółko i krzyżyk - nauka OOP

0

Witam, to mój pierwszy post, bo i pierwszy problem podczas krótkiej przygody z programowaniem.
Zadaniem jest napisanie gry kółko i krzyżyk (w konsoli, polegająca na wpisywaniu współrzędnych). Napisałem już coś takiego "strukturalnie", (tzn. w jednej klasie). Teraz gra ma być trochę bardziej rozbudowana i przygotowana na kolejne modyfikacje (żeby łatwo było coś dodać). Dlatego postawiłem sobie za cel napisanie tego obiektowo, co i tak jest zalecane na stronie z której się uczę. Problem w tym, że wszystko dotąd pisałem w jednej klasie i nawet nie wiem jak się do tego zabrać. Rozumiem jak działają programy innych użytkowników napisane w ten sposób ale sam mam problem z tworzeniem.
W grze najpierw ma być do wyboru za pomocą komend gra z innym użytkownikiem lub komputerem na poziomie easy. W następnych etapach mam dodać wyższe poziomy trudności komputerowi.
Wymyśliłem sobie najpierw, że stworzę na początek klasę, która będzie przechowywała wszystko co związane z polem gry. Problem pojawił się taki, że nie mogłem wywoływać metod tej klasy w innych klasach poza klasą Main (ani statycznych ani po utworzeniu obiektu (obiekt dało się utworzyć w innych klasach)). Tylko w klasie Main działało tak jak chciałem. Próbowałem nawet ustawiać wszystkie modyfikatory dostępu w programie na public ale nic to nie dało. Nie rozumiem czemu w klasie Main działa, a w innych nie. Czym ta klasa miałaby się różnić? Klasy, w których chciałem żeby działało też zmieniłem na public.

Pomijając to, nie wiem czy to w ogóle dobry pomysł i zwracam się z pytaniem czy ktoś mógłby mnie nakierować jak zbudować ten program? Nie znam jeszcze takich zagadnień jak dziedziczenie, interfejsy, polimorfizm ale wydawało mi się, że da się bez tego napisać coś sensownego.

5
Saell napisał(a):

Wymyśliłem sobie najpierw, że stworzę na początek klasę, która będzie przechowywała wszystko co związane z polem gry. Problem pojawił się taki, że nie mogłem wywoływać metod tej klasy w innych klasach poza klasą Main (ani statycznych ani po utworzeniu obiektu (obiekt dało się utworzyć w innych klasach)). Tylko w klasie Main działało tak jak chciałem. Próbowałem nawet ustawiać wszystkie modyfikatory dostępu w programie na public ale nic to nie dało. Nie rozumiem czemu w klasie Main działa, a w innych nie. Czym ta klasa miałaby się różnić? Klasy, w których chciałem żeby działało też zmieniłem na public.

Takie gdybanie bez kodu to tylko gdybanie. Jak chcesz konkretnej pomocy to pokaż konkretny kod. Albo starą wersję działającą, to poradzimy jak to zrefaktoryzować. Albo nową wersję nie działającą to poradzimy jak naprawić błędy

0

Robisz błąd, że pchasz się w obiektowe programowanie. To dobra rzecz jak piszesz duże programu, tysiące linii kodu.

Jak robisz program, który da się napisć jednym pierdnięciem to nie ja nie wiem po co Ci ta cała obiektowa otoczka. To, że dodasz klasy != program będzie robił coś więcej, coś ekstra.. po prostu ostatecznie skomplikujesz sobie pracę i tylko oddalisz się od robienia ciekawych programów.

0

Cóż, w takim razie napiszę znowu napiszę funkcyjnie. Myślałem, że na klasach będzie wygodniej i powinienem uczyć się w ten sposób, zwłaszcza, że jak patrzę na rozwiązania na stronie, z której się uczę, większość jest na klasach.

3

OPP jest dobre, gdy chcemy uogólnić pewne partie kodu, móc je łatwiej od siebie odseparować itp biorąc pod uwagę kółko i krzyżyk, czy inne banały przerost formy

Jakby to była prawdziwa apka to owszem - armata na muchę, ale nie widzę niczego złego, jeśli to jest robione w ramach ćwiczeń czy nauki.

Od razu widzę tutaj jedną klasę odpowiedzialną za tablicę (trzymanie stanu gry, pobieranie kolejnych ruchów), do tego jakaś klasa odpowiedzialna za rysowanie na ekranie, plus jeszcze klasa odpowiedzialna za komunikację z userem. A później, w ramach ćwiczeń można zrobić podmianę ruchów - żeby np. zamiast wczytywać z klawiatury, pobierał kolejne ruchy z pliku tekstowego. Jeśli abstrakcje i powiązania klas będą dobrze zrobione, to powinno się dać podmienić jedynie klasę odpowiedzialną za ruchy na nową, bez wprowadzania jakichkolwiek zmian w reszcie kodu. Program niby trywialny, ale spoko jako poligon OOP.

4
Saell napisał(a):

Cóż, w takim razie napiszę znowu napiszę funkcyjnie. Myślałem, że na klasach będzie wygodniej i powinienem uczyć się w ten sposób, zwłaszcza, że jak patrzę na rozwiązania na stronie, z której się uczę, większość jest na klasach.

Java jest językiem obiektowym (przynajmniej według popularnej wersji definicje, według radykalnej wersji definicji językiem obiektowym jest chyba tylko Smalltack) więc najprościej będzie w niej pisać programy zgodne z OOP. Powinieneś też zacząć od OOP ponieważ jest to najpopularniejszy (niekoniecznie najlepsze) paradygmat. I na rozmowach o pracę chcą żeby opowiadać co to OOP

Jak już będziesz miał taki program to zainteresowałbym się biblioteką VAVR oraz stopniowo eliminował z programu mutowalność, zmienność i stanowość tak długo aż uzyskałbym program który jest jednocześnie OOP i funkcyjny* na tyle na ile Java pozwala.

*Tak, uważam że OOP i FP to nie są rzeczy które się wykluczają. Według niektórych interpretacji Haskell też jest OOP, bo ma interfejsy (TypeClassy). Jedyny problem że te obiekty w Haskellu są niemutowalne :P

1

Nie jestem pewny czy dobrze rozumiem, ale jeśli tak jest, to próbujesz wywołać metody jednej klasy w miejscu na deklaracje zmiennych/metod drugiej klasy.
W tej drugiej klasie (tj tej co masz problem z wywołaniem metody) napisz sobie np:

void callMethod (){
       
    }

Wewnątrz tej metody już Ci wszystko pójdzie tak jak w klasie "Main" (swoją drogą, chodzi Ci chyba o metodę "Main", a nie klasę).
W głównej klasie działa Ci to w Main bez problemu, ponieważ Main jest metodą, tak jak w moim przykładzie callMethod.
Nie wiem czy dobrze Ci to tłumaczę, sam jestem amator, ale mam nadzieje, że o to chodziło :)

Przykłady w kodzie:

public class ExampleMain {
    Person pawel = new Person();
    // tutaj miałbyś problem, bo nie jesteś w metodzie, dopiero w main możesz wywołać metody paweł
    public static void main (String [] args){
        Person pawel = new Person();
        pawel.setId(2); // tutaj nie masz problemu

    }
}

public class Person {
    public int id;

    public void setId(int id) {
        this.id = id;
    }
}
public class toUsePerson {
    Person pawel = new Person();
    // tu masz problem bo nie umieszczasz tego w metodzie

    void callMethod (){
        pawel.setId(3); // tu nie ma problemu
    }

}

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