[ANDROID STUDIO] Voting App Indexfehler und Verlierer-ermittlung

  • Antworten:6
  • OffenNicht stickyBentwortet
  • Forum-Beiträge: 18

12.10.2020, 14:10:46 via Website

Hey Leute,

benötige einmal wieder Eure Hilfe.
ich bin gerade dabei eine Voting App zu machen. Soweit stimmt auch alles. Es gibt nur zwei Probleme.

Also die App läuft wie folgt ab:
- Es öffnet sich mit dem Startknopf die Frage, der Spieler der dran ist und ein Gridview, mit allen Spielern
- der Startknopf verschwindet mit setVisibility(View.GONE); und ein neuer Button (Der den nächsten Spieler aufruft) wird eingeblendet.
- Jetzt stimmt der Spieler, der dran ist, ab, für wen er sich entscheidet und drückt auf weiter.
- Der nächste Spieler ist dran und sieht die Auswahl des Spielers zuvor nicht.

Bis hier läuft alles wie es soll, nur kommen jetzt die Probleme.

Sagen wir es spielen 5 Spieler. Spieler 1-4 wählen und die Auswahl der jeweiligen Spieler wird in einem Array gespeichert. Wenn der fünfte Spieler jetzt nach seiner Auswahl auf Weiter druckt, wird seine Auswahl nicht gespeichert. Es sind dann keine 5 Werte im Array, sondern nur 4. Ich habe leider keine Ahnung, an was das liegt. Also der fünfte Spieler wird angezeigt, aber nicht gewertet.

Hier einmal der Code zum Startbutton: Den braucht ihr wahrscheinlich nicht, aber das er Mal dabei ist.

//Button zum Starten und ersten mal anzeigen der Frage
btn_start.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            nextTat(tatNr);

    //ist glaub unwichtig. Hier wird nur der GridView angezeigt
            setGridView();

    //Es wird die Methode aufgerufen, um den nächsten Spieler anzuzeigen
            setPlayer(playerNumber);
            playerNumber++;

    //Wie beschrieben wird hier der Startbutton durch den Nächste Spieler Button "getauscht"
            btn_start.setVisibility(View.GONE);
            btn_next.setVisibility(View.VISIBLE);
        }
    });

Button nächster Spieler:

//Button um nächsten Spieler auswählen zu lassen
 btn_next.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
    //Hier ist glaub ich der Fehler. Wenn ich <= mache, kommt ein OutofBounds. Ist wahrscheinlich sehr einfach, aber ich komme leider nicht auf die Lösung
            if (playerNumber < listPlayerNames.size()) {

        //Schaut, ob ein Gridview Eintrag ausgewählt wurde
                if (isClicked) {

        //Hier wird das Array mit dem neuen Wert befüllt. Das funktioniert soweit ganz gut, auch wenn es vielleicht nicht die beste Lösung ist
                    vote[getGridViewPosition()] = (vote[getGridViewPosition()]) + 1;

        //Es wird die Methode aufgerufen, um den nächsten Spieler anzuzeigen
                    setPlayer(playerNumber);
                    playerNumber++;

        //Wird wieder zurück gesetzt
                    isClicked = false;
                    setGridView();
                } else {
                    Toast.makeText(Votinggame.this, "wähle jemand aus", Toast.LENGTH_SHORT).show();
                }
            } else {
                playerNumber = 0;

        //Wenn jeder gewählt hat, geht es wieder von vorne los und der Verlierer wird angezeigt
                btn_next.setVisibility(View.GONE);
                btn_start.setVisibility(View.VISIBLE);
                gridView.setVisibility(View.GONE);
                textViewLooser.setVisibility(View.VISIBLE);
                showLoser(vote);
            }
        }
    });

Methode, um die erste und nächsten Fragen anzuzeigen

private void nextTat(int tatNr) {
    if (tatNr < tatListe.size()) {
        currentTat = tatListe.get(this.tatNr);
        votingFrage.setText(currentTat.getVotingfrage());
        this.tatNr++;
    } else {
        Toast.makeText(this, "Ende. Alle Fragen wurden gestellt", Toast.LENGTH_SHORT).show();
}

}

Und zu guter Letzt das letzte Problem. Kann zwar den Verlierer anzeigen, aber keine Ahnung, was man tun soll, wenn zwei Spieler die selbe Anzahl an Stimmen haben. Hier mal der Code:

//Methode, um den Verlierer anzuzeigen
private void showLoser(int[] vote) {
    //mit kleinstmöglichem Wert initialisieren
    int largest = Integer.MIN_VALUE;

    //um Loser herauszufinden
    int looser = 0;

    //größtes Element des Arrays finden
    int index = 0;
    while( index < vote.length ) {
        //prüfen, ob größtes kleiner als Element ist
        if( largest < vote[index] ) {

            //update largest Wert
            largest = vote[index];
            looser = index;
        }
        index++;
    }
    textViewLooser.setText(listPlayerNames.get(looser) + "\n hat verloren");
}

Sorry, dass der Text jetzt doch so lang geworden ist.

Danke euch schon mal im Voraus!

Diskutiere mit!
Beste Antwort
  • Forum-Beiträge: 1.434

13.10.2020, 10:36:00 via Website

//Hier ist glaub ich der Fehler. Wenn ich <= mache, kommt ein OutofBounds. Ist wahrscheinlich sehr einfach, aber ich komme leider nicht auf die Lösung
if (playerNumber < listPlayerNames.size())

das es bei <= einen Fehler gibt ist auch logisch.#
listLPlayerName ist ein Array was 5 Elemente (0,1,2,3,4) enthält. Was gibt dir size() zu rück?
Einen int mit dem Inhalt „5“.
Wenn du nun auf kleiner oder gleich prüfst, also auch auf gleich 5, was passiert, ist der Fehler.
Warum von wo bis wo gehen die Elemente in dem Array ? (vom 0 bis 4 ) sind 5 Elemente, "0" ist das erste . Wenn du nun mit 5 vergleichst, Fehler es gibt keine 5 in dem Array. Das wäre das das 6. Element was es nicht gibt.

Das mit dem setzen auf 0 am ende wird wohl richtig sein.

Wenn der fünfte Spieler jetzt nach seiner Auswahl auf Weiter druckt, wird seine Auswahl nicht gespeichert.

Das befüllen deines "vote" Array machst du nur beim Klick auf den zweiten „Next“ Button.
Beim ersten Start Button nicht.
Also speicherst du den ersten Player erst wenn der Next Button gedrückt wird.

Da scheint dein Fehler in der (deiner) Logik zu stecken.

Es wird immer einer weniger in dem Array sein.

wie läust es bei dir ab?

Klick Start Button kein speichern.
Klick Next Button ,erst mal testen ob ende erreicht , testen ob geklickt , wenn ja speichern , und danach neuen Player anzeigen Player um eins erhöhen.

klar da bleibt der letzte auf der Strecke. da er nicht gespeichert wird.

So jetzt solltest du selber auf eine vernünftige Lösung kommen.

Tipp beim letzten abschließenden klick machst du nichts. Ja du baust die button wider um aber aber was fehlt hier? Um ein sinnvolles Ergebnis anzuzeigen?

— geändert am 13.10.2020, 11:21:12

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 11.168

12.10.2020, 14:54:20 via Website

Hallo,

vermutlich liegt der Fehler wirklich hier:

if (playerNumber < listPlayerNames.size()) {

Wie wird deine listPlayerNames initialisiert und welche größe hat diese?
Beachte dass playerNumer im Intervall [0,4] = 5 Spieler ist und list PlayerNames.size() i.d.r eine 5 zurückgeben müsse. Der Logik nach sollte es gehen, da ich aber deine initialisierten Werte nicht kenne, musst du das überprüfen.
Am besten per Log oder Debugger.

Beim verlierer suchst du aus deinen Votes das minimum raus, wie du es jetzt hast.
Anschließend iterierst du nochmal über alle votes und suchst alle raus die die selbe (minimale) Anzahl haben. Damit solltest du den Fall abedcken, wenn mehrere Spieler die gleiche Anzahl votes haben.

LG Pascal //It's not a bug, it's a feature. :) ;)

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 18

12.10.2020, 18:01:09 via Website

Hey, vielen Dank erstmal für Deine Antwort!

Wie wird deine listPlayerNames initialisiert und welche größe hat diese?

Also beim Start der App wird abgefragt, wie viel Spieler es sein sollen. Es kann ein Wert zwischen 2-20 gewählt werden. In der nächsten Activity kann man dann die Namen eingeben. Hier werden die Namen dann in einer ArrayList gespeichert und im Anschluss in ein String Array umgewandelt. Dann kommt dieser Schritt:

 StringBuilder sb = new StringBuilder();
    for (int i = 0; i < arr.length; i++) {
        sb.append(arr[i]).append(",");
    }

Das wird gemacht, um die Namenliste mit den SharedPreferences an andere Activities zu übergeben.

In der Voteactivity wird dann dieser Schritt gemacht:

sharedpreferences = getSharedPreferences(mypreference, Context.MODE_PRIVATE);
String[] playerNames = sharedpreferences.getString(Name, "").split(",");
listPlayerNames = new ArrayList<>(Arrays.asList(playerNames));

Log:

Log.d("log", "Liste Größe: " + listPlayerNames.size());
    for (int i = 0; i < listPlayerNames.size(); i++) {
        Log.d("votingLogcat", "Liste Eintrag nr" + i + " = " + listPlayerNames.get(i));
    }

liste größe: 5
Liste Eintrag nr0 = Player1
Liste Eintrag nr1 = Player2
Liste Eintrag nr2 = Player3
Liste Eintrag nr3 = Player4
Liste Eintrag nr4 = Player5

Ich verstehe zwar das Problem, aber die Lösung...

Beim verlierer suchst du aus deinen Votes das minimum raus, wie du es jetzt hast.
Anschließend iterierst du nochmal über alle votes und suchst alle raus die die selbe (minimale) Anzahl haben. Damit solltest du den Fall abedcken, wenn mehrere Spieler die gleiche Anzahl votes haben.

Super, das hat wunderbar funktioniert. Vielen Dank!

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 1.434

12.10.2020, 19:09:05 via Website

Hallo mal eine Frage hierzu

//Es wird die Methode aufgerufen, um den nächsten Spieler anzuzeigen
setPlayer(playerNumber);
playerNumber++;

wieso erhöhst du den Spieler nachdem du ihn angezeigt hast ?
wenn der mit der setPlayer( ) Methode nächst angezeigt wird müsste er doch vorher erhöht werden ?

welche Nummer hat denn der User der am gerät ist?

verstehe auch nicht warum du den Player bei else auf null setzt.

— geändert am 12.10.2020, 20:00:47

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 18

13.10.2020, 09:23:15 via Website

Hey,

wieso erhöhst du den Spieler nachdem du ihn angezeigt hast ?
wenn der mit der setPlayer( ) Methode nächst angezeigt wird müsste er doch vorher erhöht werden ?

Das ist eine gute Frage. Das habe ich glaub so übernommen, da in der ersten Runde ja der erste Spieler angezeigt werden soll. Wenn PlayerNumber dann vor der Methode erhöht wird, kommt ja direkt player2 dran. Wenn ich das bei den nächsten Methodenaufrufen davor setze, bekomme ich beim letzten durchgang den IndexoutofBounce. Habe es danach erhöht, um bei der nächsten If Abfrage if (playerNumber < listPlayerNames.size())das abzufangen. Aber irgendwie ergibt das nicht so viel Sinn. Sollte das vielleicht ändern.

welche Nummer hat denn der User der am gerät ist?

Das kommt drauf an, welcher Spieler dran ist. Spieler1 hat die Nr. 0...Spieler5 die Nr 4.

verstehe auch nicht warum du den Player bei else auf null setzt.

Das nach dem letzten Spieler - in der nächsten Runde - wieder der erste Spieler anfängt. Stimmt das so nicht?

Hilfreich?
Diskutiere mit!
Beste Antwort
  • Forum-Beiträge: 1.434

13.10.2020, 10:36:00 via Website

//Hier ist glaub ich der Fehler. Wenn ich <= mache, kommt ein OutofBounds. Ist wahrscheinlich sehr einfach, aber ich komme leider nicht auf die Lösung
if (playerNumber < listPlayerNames.size())

das es bei <= einen Fehler gibt ist auch logisch.#
listLPlayerName ist ein Array was 5 Elemente (0,1,2,3,4) enthält. Was gibt dir size() zu rück?
Einen int mit dem Inhalt „5“.
Wenn du nun auf kleiner oder gleich prüfst, also auch auf gleich 5, was passiert, ist der Fehler.
Warum von wo bis wo gehen die Elemente in dem Array ? (vom 0 bis 4 ) sind 5 Elemente, "0" ist das erste . Wenn du nun mit 5 vergleichst, Fehler es gibt keine 5 in dem Array. Das wäre das das 6. Element was es nicht gibt.

Das mit dem setzen auf 0 am ende wird wohl richtig sein.

Wenn der fünfte Spieler jetzt nach seiner Auswahl auf Weiter druckt, wird seine Auswahl nicht gespeichert.

Das befüllen deines "vote" Array machst du nur beim Klick auf den zweiten „Next“ Button.
Beim ersten Start Button nicht.
Also speicherst du den ersten Player erst wenn der Next Button gedrückt wird.

Da scheint dein Fehler in der (deiner) Logik zu stecken.

Es wird immer einer weniger in dem Array sein.

wie läust es bei dir ab?

Klick Start Button kein speichern.
Klick Next Button ,erst mal testen ob ende erreicht , testen ob geklickt , wenn ja speichern , und danach neuen Player anzeigen Player um eins erhöhen.

klar da bleibt der letzte auf der Strecke. da er nicht gespeichert wird.

So jetzt solltest du selber auf eine vernünftige Lösung kommen.

Tipp beim letzten abschließenden klick machst du nichts. Ja du baust die button wider um aber aber was fehlt hier? Um ein sinnvolles Ergebnis anzuzeigen?

— geändert am 13.10.2020, 11:21:12

Hilfreich?
Diskutiere mit!
  • Forum-Beiträge: 18

13.10.2020, 12:07:59 via Website

Hey,

danke für die ausführliche Antwort!
Bin gerade leider noch unterwegs. Werde es nachher direkt probieren und melde mich dann wieder.

Vielen Dank!

Edit:
Also es hat funktioniert! Vielen Dank nochmal :)
Habe jetzt einfach noch einmal ein
vote[getGridViewPosition()] = (vote[getGridViewPosition()]) + 1;

in die else Bedingung zum PlayerNumber = 0; gesetzt. Jetzt geht es

Super!

— geändert am 13.10.2020, 12:54:52

Hilfreich?
Diskutiere mit!