Kamień, Papier, Nożyce w JAVIE. Jak zamienić IF'y na metodę.

0

Witam. Zaczynam zabawę z Javą. Napisałem grę, która działa lecz przez dużą ilość if'ów kod jest bardzo mało czytelny. Próbuję zamienić ify na metody, ale nie bardzo wiem jak. Czy jest mi w stanie ktoś podpowiedzieć?

Kod:

import java.util.Random;
import java.util.Scanner;

public class SPSgame {

    public static void main(String[] args) {

        String[] arr = new String[]{"KAMIEŃ", "PAPIER", "NOŻYCE"};

        Random rnd = new Random();
        Scanner scanner = new Scanner(System.in);
        String playerChoice;
        int i = 0;
        int j = 0;

        System.out.println("*** KAMIEŃ  PAPIER  NOŻYCE ***");


        while (i < 5 && j < 5) {
            String randomChoice = arr[rnd.nextInt(arr.length)];
            System.out.print("Wybierz; k - KAMIEŃ, p - PAPIER, n - NOŻYCE: ");
            playerChoice = scanner.nextLine();
            if (playerChoice.equals("k")) {
                playerChoice = "KAMIEŃ";
                if (randomChoice == "KAMIEŃ") {
                    System.out.println(playerChoice + " VS " + randomChoice);
                    System.out.println("REMIS");
                    System.out.println(i + " : " + j);
                } else if (randomChoice == "PAPIER") {
                    System.out.println(playerChoice + " VS " + randomChoice);
                    System.out.println(i + " : " + (++j));
                } else if (randomChoice == "NOŻYCE") {
                    System.out.println(playerChoice + " VS " + randomChoice);
                    System.out.println((++i) + " : " + j);

                } else {
                    System.out.println("Wpisz poprawny symbol(k/p/n): ");
                }
            } else if (playerChoice.equals("p")) {
                playerChoice = "PAPIER";
                if (randomChoice == "PAPIER") {
                    System.out.println(playerChoice + " VS " + randomChoice);
                    System.out.println("REMIS");
                    System.out.println(i + " : " + j);
                } else if (randomChoice == "NOŻYCE") {
                    System.out.println(playerChoice + " VS " + randomChoice);
                    System.out.println(i + " : " + (++j));
                } else if (randomChoice == "KAMIEŃ") {
                    System.out.println(playerChoice + " VS " + randomChoice);
                    System.out.println((++i) + " : " + j);
                }
            } else if (playerChoice.equals("n")) {
                playerChoice = "NOŻYCE";
                if (randomChoice == "NOŻYCE") {
                    System.out.println(playerChoice + " VS " + randomChoice);
                    System.out.println("REMIS");
                    System.out.println(i + " : " + j);
                } else if (randomChoice == "KAMIEŃ") {
                    System.out.println(playerChoice + " VS " + randomChoice);
                    System.out.println(i + " : " + (++j));
                } else if (randomChoice == "PAPIER") {
                    System.out.println(playerChoice + " VS " + randomChoice);
                    System.out.println((++i) + " : " + j);
                }
            }
        }

            if (i == 5) {
                System.out.println();
                System.out.println("Gratulacje! Wygrałeś :)");
            } else if (j == 5) {
                System.out.println();
                System.out.println("Przykro mi, przegrałeś.");
            }
            
    }
    
}

1

Tak, rozbij to na funkcje i dodaj testy.

3

Ja to bym zrobił tak, że wydzielam logikę odpowiedzialną za gracza do innej klasy, a w main pozostawił jedynie flow, tj. coś takiego:

    enum Hand {
        SCISSORS("NOZYCE", "n", 0), PAPER("PAPIER", "p", 1), ROCK("KAMIEN", "k", 2);

        private final String displayName;
        private final String keyBinding;
        private final int value;

        Hand(final String name, final String keyBinding, final int value) {
            this.displayName = name;
            this.keyBinding = keyBinding;
            this.value = value;
        }

        public int checkAgainst(final Hand that) {
            if (this.equals(that)) {
                return 0;
            }

            if (this.value == (that.value-1) || (this.value == 2 && that.value == 0)) {
                return 1;
            }

            return -1;
        }

        static Hand findByKey(final String key) {
            return Stream.of(values())
                    .filter(e -> e.keyBinding.equals(key))
                    .findAny()
                    .orElseThrow();
        }

        static Hand pickAtRandom() {
            return values()[ThreadLocalRandom.current().nextInt(3)];
        }

        public String getDisplayName() {
            return displayName;
        }
    }

    public static void main(final String[] args) {
        int winCount = 0;
        int loseCount = 0;
        int winningPoint = 5;
        int currentResult;

        Scanner scanner = new Scanner(System.in);

        Hand playerHand, cpuHand;

        System.out.println("*** KAMIEŃ  PAPIER  NOŻYCE ***");
        while (winCount < winningPoint && loseCount < winningPoint) {
            playerHand = Hand.findByKey(scanner.nextLine());
            cpuHand = Hand.pickAtRandom();

            currentResult = playerHand.checkAgainst(cpuHand);
            System.out.println(playerHand.getDisplayName() + " VS " + cpuHand.getDisplayName());

            if (currentResult > 0) {
                winCount++;
                System.out.println("Zwyciestwo");
            } else if (currentResult < 0) {
                loseCount++;
                System.out.println("Przegrana");
            } else {
                System.out.println("Remis");
            }
        }

        System.out.println();
        if (winCount > loseCount) {
            System.out.println("Gratulacje! Wygrałeś :)");
        } else {
            System.out.println("Przykro mi, przegrałeś.");
        }
    }
1
jacob8 napisał(a):

Witam. Zaczynam zabawę z Javą. Napisałem grę, która działa lecz przez dużą ilość if'ów kod jest bardzo mało czytelny. Próbuję zamienić ify na metody, ale nie bardzo wiem jak. Czy jest mi w stanie ktoś podpowiedzieć?

To nie chodzi o zmianę Maina() na metody (na złej strukturze danych wyżej pępka nie podskoczysz), ale o zupełnie inne zaprojektowanie.

Od @wartek01 enum jest cenny ... ja bym pewnie powalczył inaczej nad atytnetyką wyznaczania relacji, ale uznaję. Dobry trop, a całkiem możliwe że osatteczny.

Nie wyobrażam sobie kodu tej gry inaczej, z jednym sprytnym centralnym obiektem. @jacob8 za trudne? Poćwicz enuma ... nie wiem, do orła i reszki ?

0
ZrobieDobrze napisał(a):
jacob8 napisał(a):

Witam. Zaczynam zabawę z Javą. Napisałem grę, która działa lecz przez dużą ilość if'ów kod jest bardzo mało czytelny. Próbuję zamienić ify na metody, ale nie bardzo wiem jak. Czy jest mi w stanie ktoś podpowiedzieć?

To nie chodzi o zmianę Maina() na metody (na złej strukturze danych wyżej pępka nie podskoczysz), ale o zupełnie inne zaprojektowanie.

Od @wartek01 enum jest cenny ... ja bym pewnie powalczył inaczej nad atytnetyką wyznaczania relacji, ale uznaję. Dobry trop, a całkiem możliwe że osatteczny.

Nie wyobrażam sobie kodu tej gry inaczej, z jednym sprytnym centralnym obiektem. @jacob8 za trudne? Poćwicz enuma ... nie wiem, do orła i reszki ?

Problem w tym, że dopiero uczę się podstaw i staram się to utrwalać w praktyce. Chciałbym na razie ten kod napisać jakoś estetyczniej/ krócej/ lepiej, a nie od razu zmieniać cały kod. Nie od razu Rzym zbudowano. Doceniam porady, ale na razie poziom nie ten, a nie da rady nauczyć się wszystkiego na raz :D

1
jacob8 napisał(a):

Witam. Zaczynam zabawę z Javą. Napisałem grę, która działa lecz przez dużą ilość if'ów kod jest bardzo mało czytelny. Próbuję zamienić ify na metody, ale nie bardzo wiem jak. Czy jest mi w stanie ktoś podpowiedzieć?

Czy w ogóle wiesz, jak napisać metodę i ją wywoływać?
Czy jesteś w stanie zastąpić np. wszystkie linijki, w których wypisujesz bieżący wynik, czymś a'la print_result (być może z pewnymi parametrami) zamiast System.out.println(i + " : " + j);?

Jeśli tak, spróbuj zastanowić się, co robi fragment:

                if (randomChoice == "KAMIEŃ") {
                    System.out.println(playerChoice + " VS " + randomChoice);
                    System.out.println("REMIS");
                    System.out.println(i + " : " + j);
                } else if (randomChoice == "PAPIER") {
                    System.out.println(playerChoice + " VS " + randomChoice);
                    System.out.println(i + " : " + (++j));
                } else if (randomChoice == "NOŻYCE") {
                    System.out.println(playerChoice + " VS " + randomChoice);
                    System.out.println((++i) + " : " + j);

                } else {
                    System.out.println("Wpisz poprawny symbol(k/p/n): ");
                }

I spróbuj go zastąpić jedną metodą z nazwą w miarę opisującą, co to robi. W tym przypadku byłoby to coś a'la CompareChoicesAndPrintComparisonResultAndChangeCurrentScoresAndValdiatePlayerInput.

W miarę rozwoju będziesz się uczył, że taka metoda to zło, a dobrą praktyką jest rozbijanie metod na mniejsze, które robią tylko jedną rzecz.
Potem będziesz rozbijał metody na mniejsze i mniejsze.

Jak uznasz, że jest git i w zasadzie sensu dalej nie ma, to spoko, zostaw tak, jak jest.

Wtedy przepisz "grę" na rock paper scissors lizard spock.

0

Kiedy próbuję stworzyć metodę o której piszesz "print_result", to muszę od nowa definiować i i j. Metoda działa, ale z każdym przejściem pętli wynik się resetuje.

Właśnie nie wiem jak zastąpić te If'y jakąś metodą i czy jest wgl opcja napisania jednej metody dla całego fragmentu z IF, żeby ją wywołać 3 razy. Właśnie po to jest ten post, że nie mam pojęcia jak np. zamienić ten fragment jakąś metodą:

if (playerChoice.equals("k")) {
playerChoice = "KAMIEŃ";
if (randomChoice == "KAMIEŃ") {
System.out.println(playerChoice + " VS " + randomChoice);
System.out.println("REMIS");
System.out.println(i + " : " + j);
} else if (randomChoice == "PAPIER") {
System.out.println(playerChoice + " VS " + randomChoice);
System.out.println(i + " : " + (++j));
} else if (randomChoice == "NOŻYCE") {
System.out.println(playerChoice + " VS " + randomChoice);
System.out.println((++i) + " : " + j);

            } else {
                System.out.println("Wpisz poprawny symbol(k/p/n): ");
            }

Wszystkie odpowiedzi są bardzo pomocne, ale chcę najpierw poćwiczyć funkcje bo jestem dopiero na początku drogi z programowaniem. Wydaje mi się, że najlepiej sobie utrwalę ćwiczyć na swoim kodzie :)

0
jacob8 napisał(a):

Kiedy próbuję stworzyć metodę o której piszesz "print_result", to muszę od nowa definiować i i j. Metoda działa, ale z każdym przejściem pętli wynik się resetuje.
Właśnie nie wiem jak zastąpić te If'y jakąś metodą i czy jest wgl opcja napisania jednej metody dla całego fragmentu z IF, żeby ją wywołać 3 razy. Właśnie po to jest ten post, że nie mam pojęcia jak np. zamienić ten fragment jakąś metodą:
(...)

Mkey, wydaje się, że jednak problem tkwi w tym, że ogólnie nie umiesz w metody i parametry. Sugeruję, abyś poczytał o nich i zastosował na prostszych przykładach.

W Twoim problemie metoda, której chcesz, ma mieć kilka parametrów (wszystkie zmienne, których używasz w zastępowanym fragmencie) i ma zmienić wartości niektórych z nich.
Zrób sobie prostsze zadanie - napisz kod, w którym

  • zdefiniujesz kilka zmiennych (i, j, k)
  • zdefiniujesz metodę która doda do i oraz j wartość k (blablabla)
  • będziesz mógł ją kilkukrotnie wykonać z oczekiwanym rezultatem.
i = 0, j = 1, k = 5
blablabla(...tu jakieś coś, do czego musisz dojść...)
wypisz wartosci i, j
k = 6
blablabla(...tu jakieś coś, do czego musisz dojść...)
wypisz wartosci i, j
k = 10
blablabla(...tu jakieś coś, do czego musisz dojść...)
wypisz wartosci i, j

Jak uzyskasz rezultat
i = 5, j = 6
i = 11, j = 12
i = 21, j = 22
przenieś mechanizm na oryginalny problem.

0

@Los Bomberos:

Czy chodzi o coś takiego?

MAIN:

public class MetodyMain {
    public static void main(String[] args) {

        AddK addK =  new AddK();

        addK.addition(5);

        // Dalsza część kodu..

        addK.addition(6);
        addK.addition(10);
        
    }
}

Osobna klasa z metodą:

public class AddK {

    private int i = 0;
    private int j = 1;
    private int k;

    public AddK() {}

    public void addition(int k) {
        i = i + k;
        j = j + k;
        System.out.println("i = " + i);
        System.out.println("j = " + j);
    }
}

0

@jacob8:

Zabawa z klasami i metodami jest mało rozwojowa, gdy koncepcje klas (metod) są niejasne, a najbardziej to widać po nazwach.

Na początek o metodzie myśl jako JEDEN czasownik (czyli add a nie rzeczownik addition), i tu problem z ilością, bo metoda robi więcej *). AddIAndAddKAndPrintBoth()
A nazwa klasy AddK ... no właśnie, nie wiadomo co to K, a w dodatku czasownik, gdy powinien być rzeczownik.
Nazwa jest ważna, jak nie odpowiada rzeczywistości ma uwierać jak wrzód poniżej pleców, raczej dłuższa, opisowa (czyli nie 'K')

Moim zdaniem nie oswoisz OOP na podobnych abstrakcjach. Klasy AddK nie da się poddać analizie, bo nic nie wiadomo, a bez analizy nie ma rozwoju.
Wydaje się bardziej rozwojowe będzie ćwiczyć na czymś dotykalnym, realnym, Jabłko, Gruszka, KoszykOwoców,. add(), eat() etc.

*) Owszem, w realnym kodzie metoda robi więcej, ale ta grupa czynności nadal ma klarowną nazwę-parasolkę, np zamów() w oczywisty sposób musi zrobić to i owo, ale cel jest jeden

0

Na prawdę doceniam wszystkie rady, ale czy jest mi ktoś w stanie pokazać jak zamienić te ify na jakąś metodę, albo uprościć ten kod, bez zmiany całej koncepcji? Zdaje sobie sprawę jak dużo musze się jeszcze nauczyć, ale chciałbym mieć jakiś przykład na którym mógłbym się wzorować, albo z którego mógłbym to zrozumieć.

0

Zawodowi programiści też wrzucają całość kodu do kosza (z jakiegos pwoodu). Ale nie widzimy w tym zupełnej głupiej straty, to nieudane poprzednie rozwiązanie przyniosło doświadczenie, pomysł jak to naprawdę zrobić itd To się nazywa "proof of concept" — ZrobieDobrze 2022-10-13 18:34

Słowo się rzekło ...
Właśnie @jacob8 posłałem do kosza ze 100 linii kodu do komercyjnej aplikacji, kilka razy po pół godziny / godzinę zygania, niepełna dniówka.
Nie szło to (ale mówiąc po twojemu : coś wychodziło, "działało") , nie prowadziło do długofalowego wykorzystania, nie było dobrego pomysłu, cel był uzyskany ale w zły sposób

Bez żalu, z frajdą, że mam to przemyślane, doczytałem doc, zaprojektowałem ideę inaczej ... za tą stówkę mam 15-20 linii, które realizują - i bardziej elastycznie - poprzedni cel.

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