# Stein, Schere, Papier



## David2456 (5. Jan 2016)

Hallo
Ich bräuchte bei folgender Aufgabe Hilfe. Mein Hauptssachliches Problem besteht in den Methoden. Wie die Werte richtig übergeben werden und wie ich sie richtig zurückgebe. Wäre nett wenn jemand mal über den Code gucken könnte (ja ich weiß das es nicht sehr effizient/professionell geschrieben ist. Ich möchte nur wissen wie ich meine Methode richtig benutze/aufrufe/etc.)
Danke schonmal


```
public class RockPaperScissors {

        public static void main(String[] args) {

        printGreetings();
       
       
        int i = computerMove(i);
        int c = playerMove(c);
       
        boolean b = hasPlayerWon();
        boolean b = isDraw();
       
       // printMoves();
       // printStatistics();
       
        boolean B = askToPlayAgain();
       
        printGoodbye();
       
       
        }
       
        public static void printGreetings(){
            Out.println("Welcome to rock-paper-scissors!");
        }
       
        public static void printGoodbye(){
            Out.println("Thank you for playing. Goodbye!");
        }
       
        public static int computerMove(int i){
            i = (int) (Math.random()*3+1);
                     
            return i2;       
        }
          
       
       
        public static int playerMove(int c){     
            Out.println("Your turn. What do you select? (1) =  Rock, (2) = Paper, (3) = Scissor: ");
          
            c = In.readInt();                      
            return c2;
        }
       
        public static boolean hasPlayerWon() {
           
            if ( i == 1 || c == 2)
            b = true;
       
            if ( i == 2 || c == 3)
            b = true;
       
            if ( i == 3 || c == 1)
            b = true;
           
            else b = false;
            return b;
        }
       
        public static boolean isDraw(){
          
           if ( i == 1 || c == 1)
           b = true;
      
           if ( i == 2 || c == 2)
           b = true;
      
           if ( i == 3 || c == 3)
           b = true;
           
            return b;
        }
       
        //public static void printMoves(){
           
           
           
       // }
       
       // public static void printStatistics(){
           
           
           
       // }
      
       public static boolean askToPlayAgain(){
          
           Out.println("Do you want to play again? (1) = Yes, (2) = No: ");
           int again = In.readInt();
          
           if (again == 1)
               B = true;
               return B;
          
           if (again == 2)
               B = false;
               return B;
       }
    }
```


----------



## kneitzel (5. Jan 2016)

Also kompiliert dein Code? Wenn nicht, dann würde ich das erst einmal beheben. Oder wenn Du nicht weiter kommst, dann komm mit den konkreten Fragen.

Aber generell: Wenn Du einen int an eine Methode übergibst, dann ist das ein "Call by value". Ist also in etwas vergleichbar mit:
Ich habe einen Zettel mit einer Zahl drauf. Wenn ich Dir diesen Wert übergebe, gebe ich Dir nicht den Zettel (bzw. einen Hinweis, wo das auf meinem Zettel steht) sondern nehme einen neuen Zettel, schreibe da die Zahl von meinem Zettel drauf, und gebe Dir (Der Methode) den Zettel dann. Du kannst dann machen was Du willst. Aber wenn Du die Zahl überschreibst, dann ändert sich mein Zettel nicht. Der Zettel, den ich Dir gegeben habe, der wird nach dem Aufruf weggeschmissen und nicht weiter beachtet.

Und wenn Du einen Wert nicht brauchst, dann übergib ihn nicht der Methode. Das "c" und "i" wird ja nicht in der Methode selbst verändert. Daher musst Du die auch nicht übergeben. (Du schaust also nicht erst, was für eine Zahl auf dem Zettel steht.)

Die Idee mit der Rückgabe sieht aber gut aus. Die Methode gibt einen Wert zurück und Du speicherst diesen Wert dann in einer Variablen. Du musst halt nur dafür sorgen, dass der Wert zurück gegeben wird - das c2 und i2 existiert ja nicht.

Konrad


----------



## Jardcore (6. Jan 2016)

Hey David2456,

wenn du die Tipps von Konrad befolgt hast solltest du vielleicht nochmal überlegen ob du vernünftige Namen für die Variabel wählst. Ein b oder B oder c oder alles was nur einen Buchstaben hat ist unbrauchbar.

Du kannst deinen Variablen ganze Wörter verpassen oder sogar Sätze wie 

```
boolean playerHasWon = hasPlayerWon();
```

Beste Grüße,
Jar


----------



## David2456 (8. Jan 2016)

Danke erstmal. Habe jetzt erstmal alle Mehtoden implementiert. Sind auch schon deutlich weniger Fehler, aber habe jetzt Probleme mit den Datentypen. Es ist ja klar das das nicht so funktionieren kann, aber mal Grundlegend. Wie schreibe ich denn die Methoden damit sie erstmal die richtigen Datentypen übergeben bekommen und wie gebe ich die richtigen zurück? Hab das von kneitzel verstanden, aber könntest du das vielleicht mal bei einer Methode anwenden? Dann habe ich ein Beispiel an dem ich mich orientieren kann


----------



## Jardcore (8. Jan 2016)

```
private void doSomething() {
    int wert= gibMirFuenf(); // wert= 5;
    int summe = summiere(10,20); // summe = 30

    // folgendes geht nicht
    int ergebnis = 0;
    summiere(10,20,ergebnis); // ergebnis wäre immernoch 0
}

private int gibtMirFuenf() {
    return 5;
}
private int summiere(int a, int b) {
    return a + b;
}

private void summiere(int a, int b, int ergebnis) {
    ergebnis = a + b;
}
```


----------



## kneitzel (8. Jan 2016)

Ein generelles Beispiel für Rückgabe eines Wertes und Übergabe eines Wertes sind wohl die Getter und Setter.


```
public class Person {

  private String name;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
}
```

Die Funktion getName soll den Namen zurück liefern. Dafür braucht man keinerlei Eingabe und Rückgabetype ist natürlich der Typ von der Variablen name: String.

Zum Setzen des Namens brauche ich natürlich den neuen Namen. Der wird also als Argument übergeben. Aber da ja nur der Name in der Instanz Person gesetzt werden soll, wird nichts zurück gegeben.

Und dies kann alles noch viel komplizierter werden. So kann es notwendig sein, mehr Daten zu übergeben. Oder statt eines gespeicherten Wertes wird erst irgendwas berechnet.

Das alles ist wie mit den Objekten in der realen Welt auch. Wenn Du ein Auto hast, dann kannst Du sagen:
Gib mit den aktuellen Kilometerstand. Braucht kein Argument oder so. Aber zurück wird der Kilometerstand gegeben. Wenn ich sage: fahre nach (München), dann wird das Ziel übergeben (in diesem Fall München. Ich erwarte aber keine Rückgabe sondern dass einfach nur etwas passiert. In diesem Fall wird der Tank wohl leerer werden und die Position wird sich verändern. Aber es gibt keine Rückgabe. wenn Du jetzt sagst, dass dies aber problematisch ist, denn was ist, wenn etwas passiert unterwegs? Dafür hat man die Exceptions. Diese unterbrechen den geplanten Ablauf mit ungeplanten Dingen. So kann das Auto kaputt gehen - dann bekommt man eine AutoKaputtException. Oder der Tankinhalt kann nicht ausreichen - das wäre dann eher eine IllegalOperationException, da erwartet wird, dass man vor dem Aufruf von "fahre nach" prüft, ob der Tank voll genug ist.

Ich hoffe, diese Beschreibung hat etwas geholfen.


----------



## David2456 (8. Jan 2016)

Vielen Danke. Versuche grade in einem Nebenprogramm das zu verstehen. Nun weiß ich aber nicht wieso diese Beispiel Methode nicht funktioniert.

```
public class k {

    public static void main(String[] args) {

        printGreetings();
        computerMove();
      
    }
            public static void printGreetings(){
               Out.println("Welcome to rock-paper-scissors!");
            }
           
            public static void computerMove(){
            int i = (int)((Math.random()) * 3 + 1);
           
            String Cmove;
            if (i == 1){ Cmove = "Rock";}
            if (i == 2){ Cmove = "Paper";}
            if (i == 3){ Cmove = "Scissor";}
            Out.print(Cmove);
           
                  
        }
}
```

Also es geht um computerMove();    Wieso wird dem String kein Wert zugewiesen?


----------



## kneitzel (8. Jan 2016)

Also ich nehme einmal an, dass Du darauf ansprichst, dass Du einen Fehler bekommst, dass Cmove evtl. nicht initialisiert wurde.

Dass i nur 1, 2 oder 3 sein kann, kann der Compiler nicht sehen. Daher hält es der Compiler für möglich, dass keine der drei if Bedingungen erfüllt war.

Ich sehe mehrere Möglichkeiten für diese Problematik:
a) String Cmove = ""; 
Also einfach Cmove direkt initialisieren.

b) Dafür sorgen, dass immer ein Wert gesetzt wird. Da sehe ich mehrere Möglichkeiten.

```
if (i == 1) { ...}
else if (i == 2) { ... }
else { ... } // Also keine Kontrolle auf i==3 mehr. Oder doch noch ein else if (i ==3) { ...} und im else wird eine RuntimeException geworfen.

// Schöner per switch:
switch (i) {
  case 1: Cmove = "..."; break;
  case 2: Cmove = ".."; break;
  case 3: Cmove = ".."; break;
  default throw new RuntimeException("i out of expected range");
} // Ggf. case 3 wieder weg lassen und den Fall 3 im default Zweig abhandeln.
```

Konrad


----------



## David2456 (8. Jan 2016)

Vielen Danke. Bin jetzt so gut wie fertig. Mir fehlt nur noch die letzte Methode. Wie kann ich denn mit einer Methode das Programm an einer bestimmten stelle neustarten?


----------

