Codeausführung unterbrechen und auf Event warten



  • Hi,

    ich bin seit gestern auf der Suche und am überlegen wie ich die Ausführung einer Methode zu einem Zeitpunkt unterbrechen kann und erst weitere laufen lasse, wenn ein button_click Event ausgeführt wurde.

    Gibt es da eine Möglichkeit? Mir schwirren schon ein, zwei Ideen im Kopf rum aber ich steh im Moment ein bisschen auf dem Schlauch...

    Ich stelle mir das Codetechnisch in etwa so vor:

    Machwas()
    {
      TuWas();
      MachNochMehr();
      //Hier jetzt die Stelle an der auf das button_click Event gewartet werden muss
      //Das button_click Event wurde ausgeführt es kann weiter gehen
      MachWeiter();
    }
    

    Hat jemand vielleicht einen Ansatz oder eine konkrete Idee?

    Vielen Dank schon mal im voraus!

    Markus



  • Also ich weiß grad nicht wieso man sowas machen sollte?
    Wenn das Button Klick event geflogen ist, kannst du doch in dem Eventhandler für dieses Event die ausführung weiterführen? Erklär mal etwas genau was du wirklich vor hast.



  • Ich programmiere gerade ein Kartenspiel als Projekt für die Schule.

    Ein Spiel besteht aus vier Spielzügen.

    Ein menschlicher Spieler, drei CPU-Spieler.

    Ich habe mir vier einzelnde Methodem überlegt (ja redundant..) je nach dem welchen Spieler als ertses dran ist eine Karte zu spielen.

    Die Methode habe ich ungefähr so angedacht:

    SpielMethode()
    {
      CPU1.PlayCard();
      CPU2.PlayCard();
      //Spieler muss Karte spielen und kann diese durch anklicken wählen
      CPU4.PlayCard();
    }
    

    Man könnte ja auch noch eine extra Methode für den Spieler einbauen die dann evtl. zwingen auf ein Event wartet.

    Ich hoffe ich habs einigermaßen verständlich rüber gebracht.

    Gruß
    Markus



  • Ich hoffe ich habs einigermaßen verständlich rüber gebracht.

    Nöö nich wirklich, das erklärt immernoch nicht das Problem warum du auf ein Event warten willst. Achja du könntest ja anstatt 4 MEthoden, auch ein Interface machen wo du die Methode anbietest und deine Spieler/CPU implementieren dann dieses Interface.



  • Naja, wenn der Code nicht "angehalten" wird, rödelt er ja die Methode durch und lässt den menschlichen Spieler aussen vor.

    Der CPU-Spieler hat seine eigenen Methoden um zu entscheiden welche Karte er spielen muss, aber der menschliche Spieler soll eine via drauf klicken auswählen.

    Das mit dem Interface ist eine gute Idee, so ganz nebenbei!



  • Naja dann ruf doch einfach die Menschen Methoden in dem ButtonClick-EventHandler auf, dann wird solange auf den menschlichen Zug gewartet bis eben die CPU ge"drückt" haben.



  • Also das versteh ich jetzt nicht so ganz.

    Was meinst Du denn jetzt mit Menschen Methoden? Sorry aber ich steh seit gestern total auf dem Schlauch >_<



  • Naja du hast ja sicherlich für den Button Click ein Eventhandler, arbeite dort doch die Menschen Methoden ab, von den du gesprochen hast.



  • Das ganze riecht nach einer schlechten Architektur.
    Erstell einfach ein IPlayer interface, dies bietet ein Property "IsKI" oder ähnliches.
    In der methode zur steuerung des "NextPlayer" (Kann ja variieren wer als nächstes dran ist) wird dann unterschieden, wenn IsKI == true dann wird CalculateCard() aufgeufen und das ruft dann wieder NextPlayer auf, am sonsten passiert nichts und es geht erst weiter nachdem der Benutzer eine Karte oder den Stapel anklickte.



  • Hehe irgendwie habe ich das Gefühl wir reden aneinander vorbei XD

    Ich verusch die Situation noch mal zu erklären:

    Es gibt vier Spieler 3 x CPU und 1 x menschlich.

    Ich habe eine Klasse NewGame. In dieser Klasse, so habe ich es mir Gedacht, wird es eine Methode geben die eine neue Runde des Spiels beihaltet. Eine Runde kann man vergleichen mit einer Hand beim Poker.

    Diese Methode habe ich mir folgendermaßen überlegt:

    NeueRunde()
    {
     CPU1.PlayCard(); // Der erste CPU Spieler legt eine Karte auf den Tisch
     CPU2.PlayCard(); // Der zweite CPU Spieler kann anhand interner Klassenmehtoden entscheiden welche Karte er auf den Tisch legt und tut dies
    
     //Jetzt kommt der menschliche Spieler ins Spiel.
     //Er hat keine Methoden die für Ihn entscheide welche Karte gelegt wird,
     //sonst wäre das Spiel ja auch langweilig. Er kann durch anklicken einer
     //Karte in seiner Hand entscheiden was er spielen will.
     //Wie kann ich hier angeben das der Spieler jetzt dieses Click_Event
     //ausführen muss und es kann erst weitergehen, wenn das passiert ist?
    
     CPU3.PlayCard() // Der dritte CPU-Spieler entscheide wieder mit seinen Methoden welche Karte er spielen soll
    
    // Jetzt wird noch alles ausgewertet und die Punkte werden verteilt.
    
    }
    

    Mein Denk/Lösungsproblem liegt an der Stelle, an der der mesnchliche Spieler SELBER entscheiden muss welche Karte er spielt. Das kann er natürlich durch ein Click_Event machen. Im Eventhandler des Click_Events wird das dann verabreitet und die Karten "auf den Tisch" gelegt.



  • Erstell einfach ein IPlayer interface, dies bietet ein Property "IsKI" oder ähnliches.
    In der methode zur steuerung des "NextPlayer" (Kann ja variieren wer als nächstes dran ist) wird dann unterschieden, wenn IsKI == true dann wird CalculateCard() aufgeufen und das ruft dann wieder NextPlayer auf, am sonsten passiert nichts und es geht erst weiter nachdem der Benutzer eine Karte oder den Stapel anklickte

    Hmmm das klingt sehr interessant, da werd ich noch etwas drüber nachdenken müssen damit ich ganz verstehe. Habe schon länger nichts mehr mit Interfaces zu tun gehabt...



  • Du könntest ein modales Fenster öffnen in dem der Spieler die zu spielende Karte auswähle oder pollen ob die nächste Karte auf dem Stapel gelegt wurde.



  • Oder noch einfacher Du setzt einfach ein Flag welches dir anzeigt ob der Player schon
    seine Kartren ausgespielt hat. Dieses Flag (einfache zb. ein bool bPlayed) kannst Du
    dann in den CPU spielern abragen, und diese Spielen nur aus wenn es true ist.

    bsp:

    bool bPlayed = false;
    
    // in deiner Funktion bim CPU Player 
    
    dann einfach:
    
       if(bPlayed)
       {
          CPUPlayer1Play();
          CPUPlayer2Play();
          bPlayed = false;
       }
    
       Player3Play(); // Hier spielst Du aus
    
       if(bPlayed)
       {
          CPUPlayer3Play();
       }
    


  • Du musst doch auch noch entscheiden können was beim aussetzen passiert...
    Solch eine feste "kontroll-methode" ist eine schlechte idee.

    Spiel Startet:

    var player = GetFirstPlayer();
    player.Proceed();

    und in der Proceed klasse wird entschieden was als nächstes passiert, entweder "CalculateCard()" wenn es ein KI player ist, oder nichts wenn es ein Menschlicher Spieler ist.
    Sobald ein Mensch drann ist, geht es erst in der Click Methode weiter.

    Hier mal etwas Pseudo code:

    public interface IPlayer
    {
        public bool IsKI { get; set; }
        public void Proceed();
    }
    
    public class HumanPlayer : IPlayer
    {
        public bool IsKI { get; set; }
        public void Proceed()
        { }
    }
    
    public class KIPlayer : IPlayer
    {
        public bool IsKI { get; set; }
        public void Proceed()
        {
            CalculateCard();
            TableManager.NextPlayer();
        }
    }
    
    public class TableManager
    {
        public void NextPlayer()
        {
            ActivePlayer = Players[2];
            ActivePlayer.Proceed();
        }
    }
    
    List<IPlayer> Players = new List<IPlayer>();
    Players.Add(new HumanPlayer());
    Players.Add(new KIPlayer());
    Players.Add(new KIPlayer());
    Players.Add(new KIPlayer());
    
    Players.First().Proceed();
    

    Mit ein bischen überlegen und intelligendes abstraieren, kümmern sich die Objekte automatisch darum was wie als nächstes passiert.
    Nicht einfach drauf los Programmieren und alles in die CodeBehind packen wie es gerade passt!

    PS. Ich habe auch schon ein Kartenspiel implementiert (MauMau in allen möglichen Regeln, alles einstellbar, auch Spieler Anzahl) das Projekt ist derzeit durch andere Prioritäten aber eingefrohren.



  • Erst mal Danke für alle Antworten!

    Je öfter ich Deinen Vorschlag lese und je mehr ich darüber nachdenke, desto mehr verstehe ich es 😃 Danke CSL

    Wenn das Projekt fertig ist (spätestens 25.03) werde ich berichten, wie ich es tatsächlich gelöst habe.

    Gruß
    Markus



  • Hallo Gamester,

    generell mußt du bei der GUI-Programmierung ereignisorientiert programmieren (event-based), d.h. du mußt die Aktionen in viele kleine Methoden packen.
    Der Ansatz von CSL ist in Ansätzen schon mal gut, du mußt dann nur noch einen 'CurrentPlayer' im TableManager deklarieren, der dann je nach erfolgreicher Aktion (KI bzw. Button-Click) weitergesetzt wird.

    public class TableManager
    {
        int CurrentPlayer = 0;
    
        public void NextPlayer()
        {
            CurrentPlayer++;
            if(CurrentPlayer >= Players.Count)
               CurrentPlayer = 0;
    
            IPlayer ActivePlayer = Players[CurrentPlayer];
            ActivePlayer.Proceed();
        }
    }
    

    Und beim Button-Click mußt du dann entsprechend die Karte ausspielen und auch NextPlayer aufrufen (d.h. im Prinzip wie bei KIPlayer.Proceed).

    Weitere Aktionen kannst du dann in NextPlayer integrieren (d.h. wenn alle Spieler ihre Aktionen ausgeführt haben oder wenn Spielende ist etc.).

    P.S: Für C++ (und der Borland VCL) hätte ich dir ein selbstgeschriebenes Framework empfehlen können:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-193889-and-highlight-is-.html
    (Th war mein alter Account - extra eingefroren bei 1442 Beiträgen!)



  • Gamester schrieb:

    SpielMethode()
    {
      CPU1.PlayCard();
      CPU2.PlayCard();
      //Spieler muss Karte spielen und kann diese durch anklicken wählen
      CPU4.PlayCard();
    }
    

    definiere doch einfach den Spielablauf etwas um

    SpielMethode()
    {
      //Spieler muss Karte spielen und kann diese durch anklicken wählen
      CPU4.PlayCard();
      CPU1.PlayCard();
      CPU2.PlayCard();
    }
    

    somit hast Du schon mal den Spieler an erster Stelle ... mit etwas "Substitution" kannst Du auch folgendes machen

    //Spieler muss Karte spielen und kann diese durch anklicken wählen
      computer[0].PlayCard(); // CPU 4 - Spieler 4
      computer[1].PlayCard(); // CPU 1 - Spieler 1
      computer[2].PlayCard(); // CPU 2 - Spieler 2
    

    dann muss Du in der Form nur auf den entsprechenden Klick auf die Karte (Button?PictureBox?...) warten ... anschließend rennst Du mit den CPU-Spieler durch

    public void Click_KarteXX(/* ... */)
    {
       legeSpielerKarte();
       for(int i = 0; i < 3; i++) compuer[i].PlayCard();
    }
    

    hand, mogel



  • Was ich bereits schrieb ist natürlich nur ein Teil des ganzen, und war nur Pseudocode.
    Ich habe leider mein Ablaufdiagramm von meinem MauMau nicht mehr, eventuell bekomm ich es noch zusammen:

    1. Beim Spiel start, erstelle Kartenstapel
    Jede Karte bekommt ihre eigene Regel zugeordnet (2 ziehen) und ihre dazugehörige auflösung (blocken, weitere 2 ziehen Karte)
    Das alles je nach Settings.

    2. Spieler werden erstellt.

    3. Es wird ermittelt welcher Spieler anfängt

    4. Next Player wird aufgerufen

    5. Next Player ermittelt wer dran ist, und ruft dessen Ausfürhungsmethode auf

    6. In der Ausfürhungsmethode wird geschaut ob es eine KI ist, wenn nein passiert nichts, wenn ja
    6a. Gewünschte Karte ermitteln
    6b. Karte als Put Request an den Tisch schicken

    7. Wenn ein Spieler auf eine Karte oder den Stapel Klickt
    7a. Ist der Spieler drann?
    7b. Karte als Put Request an den Tisch schicken

    8. Der RuleManager prüft ob die gewünschte Karte gelegt werden darf, dazu fragt er einfach die Karte ob sie mit der Neuen Karte aufgelöst werden kann und antwortet entsprechend.

    9. Karte wird gelegt, dabei wird die Aktive Regel entweder erweitert (Statt 2 jetzt 4 ziehen) oder aufgelöst (Es wurde gezogen, dh 2 ziehen gilt nicht mehr) oder eine neue Regel gesetzt

    10. Next Player wird aufgerufen

    Note:
    - Next Player prüft auch immer ob das Spiel beendet ist.
    - Die KI simuliert in einem eigenen Thread eine Wartezeit, damit man sieht das noch etwas Passiert.
    - Alle Methoden sind am ende sehr kurz, und die eingestellten Rules kümmern sich alle selber um ihr zeug, so hat man auch keine if else ketten
    - Auf solchen wegen kann man belibige Regeln ein und aus schalten, bis hin zur Spieler anzahl.



  • So ich muss mich nochmal bei allen bedanken, speziell bei CSL!

    Habe eben mal ein kleines Testprojekt geschrieben und es funktioniert wunderbar! Genau so wie ich mir das vorgestellt habe 😃

    Manchmal muss man eben in die richtige Denkrichtung geschubst werden, wenn man sich zu sehr auf einen Lösungsweg versteift hat.

    Ich wäre wohl im Leben nicht auf die Lösung durch ein Interface gekommen, obwohl es so nahe liegt... Naja wie Loddar so schön sagt: "Ägän wot lörnd!"



  • Das Projekt für die Schule, ist das auf freiwilliger basis? Wird es bewertet? Schreibst du alles allein? Hast du Grafiken der Karten in verwendung?


Anmelden zum Antworten