Entwickler-Ecke

Basistechnologien - Menüauswahl in Consolenprogramm für Kniffel/Yahtzee


DragStar - Di 29.09.20 08:43
Titel: Menüauswahl in Consolenprogramm für Kniffel/Yahtzee
Hallo zusammen!

Ich bin dabei Kniffel/Yahtzee als Konsolenprogramm zu entwickeln.
Nachdem der User 5 zufällig generierte Zahlen von 1-6 angezeigt bekommt, soll er aus einem Menü von 1-13 die passende aussuchen, die am meisten Punkte bringt (kleine Straße, Full House, Dreierpasch, usw). Das habe ich soweit auch schon alles.
Da jede Möglichkeit nur 1 mal ausgewählt werden kann, soll die bereits auswählte Option nicht mehr in der nächsten Runde angezeigt werden, bis alle 13 Möglichkeiten belegt sind (evtl auch mit 0 Punkten). Dann ist das Spiel beendet.

Jetzt zu meinem Problem:
Wie kann ich das am besten umsetzen, dass es den Menüpunkt nicht mehr anzeigt, wenn dieser bereits ausgewählt wurde?

Würde mich freuen, wenn jemand eine Idee für mich hat. Vielen Dank! :-)


jaenicke - Di 29.09.20 08:51

Hallo und :welcome:

Du hast nicht gezeigt wie du das Menü anzeigst, aber ich vermute mal du hast eine Prozedur, die das Menü ausgibt?

Nachdem eine Eingabe gemacht wurde, müsstest du dir für den entsprechenden Eintrag merken, dass er schon ausgewählt wurde. Bei der Ausgabe gibst du diese Einträge dann nicht mehr aus.

Also so ungefähr:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
var
  FirstItemUsed: Boolean;
  SecondItemUsed: Boolean;
  ThirdItemUsed: Boolean;

procedure PrintMenu;
begin
  if not FirstItemUsed then
    Writeln('FirstItem');
  if not SecondItemUsed then
    Writeln('SecondItem');
  if not ThirdItemUsed then
    Writeln('ThirdItem');
end;

// Menüeintrag 1 wurde ausgewählt:
  ...
  FirstItemUsed := True;
  ...

Schöner geht das mit Arrays, aber ich vermute das ist eine Übung, so dass diese Version hier die einfachste ist.


Th69 - Di 29.09.20 09:04

Hallo,

@jaenicke: Dieses ist eine C#/.Net-Frage. ;-)

@DragStar: Du wirst ja sicherlich für die Punkte auch schon ein Array (bzw. List<int>) benutzen? Entweder ein zweites Array (bzw. Liste) mit bool-Werten dafür anlegen oder aber du könntest -1 (bzw. irgendein anderer negativer Wert) als Initialisierungswert nutzen und diesbzgl. abfragen.


DragStar - Di 29.09.20 09:17

Ok. Danke erstmal für eure Hilfe.

Mein Gedanke war jetzt, jede Möglichkeit als einen Eintrag in einer Liste zu speichern.
Wenn dieser Eintrag bzw. die Möglichkeit ausgewählt wurde, soll der entsprechende Eintrag in eine andere Liste geaddet werden, damit man auch sagen kann, dass dieser bereits ausgewählt wurde, sollte er erneut ausgewählt werden wollen.
In der Menüliste wird dieser entsprechende Eintrag logischweise removed.

Meint ihr das geht auch so? :-)

Die Idee kam mir erst, nachdem ich die Frage hier gestellt hatte.


Th69 - Di 29.09.20 11:27

Ja, das geht, wäre aber umständlicher. ;-)


jaenicke - Di 29.09.20 16:44

user profile iconTh69 hat folgendes geschrieben Zum zitierten Posting springen:
@jaenicke: Dieses ist eine C#/.Net-Frage. ;-)
Oops :oops:, aber die Aussage stimmt trotzdem, nur mit etwas anderer Syntax. :)


DragStar - Do 01.10.20 10:56

So, nun stehe ich immer noch vor dem selben Problem.

Ich habe mal im Anhang 2 Bilder hinzugefügt. Bräuchte jetzt mal genauere Tipps, ich komme leider selber zu keiner Lösung und das frustriert mich so langsam :?

Vielleicht kann mir jemand weiterhelfen!? Das wäre echt klasse!
Danke!


Th69 - Do 01.10.20 13:06

Willst du wirklich die schon ausgewählten Menüpunkte gar nicht mehr anzeigen? Dann sieht der Spieler doch gar nicht mehr, welche Punkte er schon gemacht hat.

Du solltest m.E. das etwas anders aufsetzen.
Zeige zu Beginn eines Zuges immer die komplette Punktübersicht. Dann würfel und frage nach verschiedenen Optionen (es fehlt ja noch bis zu 2x Neuwürfeln bzw. Würfel liegen lassen) und erst bei "Werten" fragst du nach der Menünummer und dort läßt du dann (in einer Schleife) nur die Menüpunkte zu, die der Spieler noch nicht gesetzt hat (z.B. mit Anzeige einer Fehlermeldung à la "Menüpunkt wurde schon gewählt").

Es wäre auch einfacher, wenn du Logik- und UI-Code voneinander trennst, d.h. eine eigene Klasse für die Spiellogik erstellst (dafür wäre u.a. ein enum für die verschiedenen Wertungsmöglichkeiten sinnvoll) und die Menü(UI)-Klasse nutzt dann nur die Spiellogikklasse (dann brauchst du auch die ganzen Listen nicht als Methodenparameter zu übergeben).


DragStar - Do 01.10.20 13:34

Das habe ich gemacht. Es addiert die Punkte hinzu und zeigt nach jeder Auswahl die aktuellen Punkte an.

Die Typen (Full House, Straße, usw) hab ich als enum in einer Klasse angelegt.

Habe es nun hinbekommen, diese auszublenden, nach der jeweiligen Auswahl.

Ich habe in meiner Menü-Klasse eine Liste angelegt (List<int> selectedMenuPoints) und darin werden die ausgewählten hinzugefügt.
In meinem "if" sage ich dann


C#-Quelltext
1:
2:
3:
4:
if (selectedMenuPoints.Contains(i))
{
    continue;
}

dann wird die bereits auswählte Option nicht mehr angezeigt. Funktioniert! :-)

Klar, später mache ich dann noch so, dass man 3 mal würfeln kann und die gewünschten Würfel, die man behalten möchte, auswählen kann.

Moderiert von user profile iconTh69: C#-Tags hinzugefügt
Moderiert von user profile iconTh69: Highlight- durch C#-Tags ersetzt


DragStar - Do 01.10.20 16:20

Wie kann ich Werte, die größer als 0 sind, in grüner Schrift anzeigen lassen?

Console.ForegroundColor = ConsoleColor.Green; klappt nicht so ganz.



C#-Quelltext
1:
Console.WriteLine(String.Format($" {i,-4} {menuTypes[i - 1],-11} -> {eyesCount[i]} = {scoreUpperSection[i],-2} Points"));                    


scoreUpperSection[i] soll grün sein, wenn der Wert mindestens 1 beträgt.


Ralf Jansen - Do 01.10.20 16:42

Dann mußt du den WriteLine in mehrere Writes aufteilen und zwischen den einzelnen Write aufrufen passenden die ForeColor setzen.
ForeColor bezieht sich immer auf alles was geschrieben wird.