Laden...

ShowDialog Alternative in Wpf?

Erstellt von Tzigo vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.286 Views
T
Tzigo Themenstarter:in
20 Beiträge seit 2019
vor 4 Jahren
ShowDialog Alternative in Wpf?

Hallo zusammen,

ich bin hier schon eine Weile am basteln, aber finde nicht wirklich ein zufriedenstellende Lösung.

Kurz zum Problem:

Ich habe für meine Kinder ein kleines Spiel ähnlich wie Memory geschrieben.
Sie können Anzahl der Spiele, Anzahl der Felder und halt auch Anzahl der Spieler einstellen.

Im Singleplayer funktioniert das recht gut, aber sobald mehrere Spieler gewählt werden stoße ich auf mein Problem.

Die Anzahl der Spiele wird durch eine For-Schleife gezählt, deren Wert je nach Anzahl der Spiele und Spieler variiert.
Es soll sowas wie Hotseat-Modus werden. Also soll bei jedem Durchlauf der Spieler gewechselt werden und das Spiel selber in einem neuem Window ausgeführt werden. Das habe ich bisher per ShowDialog gelöst um die Schleife während des jeweiligen Spiels zu pausieren. Das sperrt mir aber natürlich das MainWindow, wo sich aber alle Controlbuttons und Co befinden (Spiel beenden, Neustart etc.).

Gibt es irgendeine Möglichkeit die Schleife zu pausieren, abgesehen von ShowDialog, solange das Spielwindow offen ist?

Bin für jeden Tip dankbar.

Liebe Grüße

Tzigo

132 Beiträge seit 2013
vor 4 Jahren

Bin mir nicht sicher ob ich dich richtig verstehe. Also ist das Kernproblem eine For-Schleife laufen zu lassen, die du pausieren können möchtest ohne das der UI-Thread blockiert wird? Du könntest die Schleife in einem neuen Thread ausführen und den bei Bedarf mit Thread.Sleep() pausieren.

T
Tzigo Themenstarter:in
20 Beiträge seit 2019
vor 4 Jahren

Die Idee mit der Schleife in einem neuen Thread kam mir auch schon, da aber innerhalb der Schleife das neue Window geöffnet wird, sollte das doch bei Thread.Sleep() auch pausieren oder bin ich da auf dem Holzweg? Abgesehen davon müsste ich ja eine Zeit für den Sleep angeben, welche ich aber nicht weiß.

4.931 Beiträge seit 2008
vor 4 Jahren

Hallo,

besser ist es, du erzeugst dir eine Membervariable (bzw. Eigenschaft), welche den aktuellen Spieler darstellt und erstellst passende Methoden zum Ändern, wie z.B.


public int CurrentPlayer { get; private set; }

public int MaxPlayers { get; private set; }

public void NewGame(int maxPlayers)
{
   CurrentPlayer = 0;
   MaxPlayers = maxPlayers;
   // ...
}

public bool NextPlayer()
{
    CurrentPlayer++;

    return CurrentPlayer < MaxPlayers;
}

Und wenn nach einem Durchlauf eines Spielers NextPlayer() true zurückgibt, aktivierst du die Anzeige für den CurrentPlayer.

T
461 Beiträge seit 2013
vor 4 Jahren

Die Anzahl der Spiele wird durch eine For-Schleife gezählt, deren Wert je nach Anzahl der Spiele und Spieler variiert.
.
.
.
Gibt es irgendeine Möglichkeit die Schleife zu pausieren, abgesehen von ShowDialog, solange das Spielwindow offen ist?

Ich verstehe nicht ganz den 1sten Satz. Die Anzahl der Spiele wird durch eine For-Schleife gezählt, also stimmt es wie ich es mir vorstelle, es gibt eine bestimmte Anzahl an Spiel-runden, ein so ein gesamtes Spiel wird in innerhalb einer Schleife abgebildet?

Ist das so richtig?

Ich habe den Titel mal angepasst, so dass Suchende auch etwas damit anfangen können. EDIT: Ich sollte beim Wort "Shift" im Titel das "f" nicht vergessen... 😄

T
Tzigo Themenstarter:in
20 Beiträge seit 2019
vor 4 Jahren

Entschuldigt die verspätete Antwort, bei uns sind noch Ferien, da bin ich lieber mit den Kids unterwegs, als am Rechner zu sitzen.

Ich verstehe nicht ganz den 1sten Satz. Die Anzahl der Spiele wird durch eine For-Schleife gezählt, also stimmt es wie ich es mir vorstelle, es gibt eine bestimmte Anzahl an Spiel-runden, ein so ein gesamtes Spiel wird in innerhalb einer Schleife abgebildet?

Ist das so richtig?

Ganz genau, so ist es.

Hier der betreffende Codeschnipsel:


        private void MultiPlayer()
        {
            Games = Settings.Games * 2;

            for (int i = 0; i < Games; i++)
            {
                if (Settings.Player.Equals("Player1"))
                {
                    multiPlayer = new MultiPlayer();
                    multiPlayer.Owner = this;
                    multiPlayer.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                    Nullable<bool> Start = multiPlayer.ShowDialog();  
                    if (Start == true)
                    {
                        gameWindow = new GameWindow();
                        double top = double.Parse(Application.Current.MainWindow.Top.ToString()) - 31;
                        double left = double.Parse(Application.Current.MainWindow.Left.ToString()) + 229;
                        gameWindow.Top = top;
                        gameWindow.Left = left;

                        Nullable<bool> Game = gameWindow.ShowDialog();  <-- Hier ersetzen durch ??
                        if (Game == true)
                        {
                            Player1Points = Player1Points + AktivePlayerPoints;
                            AktivePlayerPoints = 0;
                            Player1Score.Text = Player1Points.ToString();
                            SetPlayer();
                        }
                    }
                }
                else
                {
                    multiPlayer = new MultiPlayer();
                    multiPlayer.Owner = this;
                    multiPlayer.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                    Nullable<bool> Start = multiPlayer.ShowDialog();
                    if (Start == true)
                    {
                        gameWindow = new GameWindow();
                        double top = double.Parse(Application.Current.MainWindow.Top.ToString()) - 31;
                        double left = double.Parse(Application.Current.MainWindow.Left.ToString()) + 229;
                        gameWindow.Top = top;
                        gameWindow.Left = left;

                        Nullable<bool> Game = gameWindow.ShowDialog();
                        if (Game == true)
                        {
                            Player2Points = Player2Points + AktivePlayerPoints;
                            AktivePlayerPoints = 0;
                            Player2Score.Text = Player2Points.ToString();
                            SetPlayer();
                        }
                    }
                }
            }

            ShowFin();
        }


4.931 Beiträge seit 2008
vor 4 Jahren

Wie schon geschrieben, mußt du deinen Code umstellen. Bei der Programmierung von GUI (WinForms, WPF, ...)-Anwendungen mußt du status- und ereignisorientiert vorgehen (nicht prozedural, wie in deinem Code) - es gibt also keine "Game Loop".

Du brauchst also Daten, welche den aktuellen Gamestatus repräsentieren (wie in meinem Beispiel oben CurrentPlayer, MaxPlayers, ...), welche dann bei Interaktion mit dem Benutzer (Ereignisse) verändert werden (z.B. nach Spieleraktion die Anzeige für den nächsten Spieler bereitstellen).

Noch als zusätzliche Infos:
Generell sollten UI und Logik ("Spielregeln") getrennt (unabhängig voneinander) erstellt werden.
Und insbesondere bei WPF sollte man MVVM benutzen: [Artikel] MVVM und DataBinding (also nicht direkt UI-Elemente per Code angesprochen werden, wie z.B. bei Player1Score.Text).

PS: Auch deine Code-Duplizierung ist überflüssig (verwende für die Spieler eine List<Player>).
Und Codezeilen wie


double.Parse(Application.Current.MainWindow.Top.ToString())

sind ein Fall für Coding Styles Horror: eine Zahl in einen string umwandeln, um ihn dann sogleich wieder als double zu parsen 😉