4 Gewinnt | Gewinner herausfinden



  • Guten Tag!

    Ich bin neu hier und hoffe das ich dieses Thema ins richtige Forum gestellt habe. 🙄

    Nun aber zu meinem Anliegen 😋 :

    Ich probiere mich gerade an einem 4 Gewinnt. In diesem kann man in der zwischenzeit gezielt Steine setzten welche danach in einem Spielfeld ausgegeben werden. Zusätzlich wird ein Unentschieden erkannt und auch wenn eine Spalte berreits voll ist (oder nicht vorhanden: 1-7).

    Nun probiere ich aber herauszufinden wie ich einen Gewinner feststellen kann.
    Wie jederman weis, gewinnt man indem man 4 gleichfarbige Steine in einer Horizontalen, Vertiaklen oder Diagonalen Linie hat.
    Die Informationen werden bei mir in einem Array abgespeichert.
    0 = Feld ist leer
    1 = Stein von Spieler 1
    2 = Stein von Spieler 2

    Der Array hat 42 Felder wobei jedes Feld eines dieser Informationen besitzt.
    Man könnte es zwar mit If-Abfragen machen, doch hoffe ich das es eine bessere Lösungsmethode gibt.
    Man siehe das ⚠ unschöne ⚠ beispiel meiner Abfrage bezüglich Unentschieden 😞 :

    if(anz_spielzug[36] > 0 && anz_spielzug[37] > 0 &&
           anz_spielzug[38] > 0 && anz_spielzug[39] > 0 &&
           anz_spielzug[40] > 0 && anz_spielzug[41] > 0 &&
           anz_spielzug[42] > 0)
        {
            result = 1;
        }
    

    Die eigentliche frage ist:
    Wie kann ich in einem Array Felder nach einem bestimmten Schema abfragen und diese Information weiter verarbeiten!?

    Ich erwarte keine direkten Lösungen sondern eher einen Weg wie man dies gescheit lösen kann und bei beispielen eine erklärung dazu damit ich diese auch verstehen kann. 😃

    Falls ihr mehr Infos/Code vom Programm braucht so gebt bescheid.

    Greetz
    Gleànn :p


  • Mod

    Ich bin nicht sicher, auf welchem Niveau du eine Antwort erwartest. Geht es um die technische Umsetzung oder um einen Algorithmus?

    Zwei Algorithmen:
    1. Bei jedem Zug einfach vom neu hinzu gekommenen Stein aus prüfen.
    2. Wenn man das ganze Bord prüfen möchte: In einer bestimmten Richtung durchgehen, zum Beispiel immer von oben nach unten und von links nach rechts. Dann braucht man beim Finden eines Steins nur noch nach unten, rechts, rechts oben und recht unten zu prüfen und spart sich somit viel Arbeit. Man dürfte aber kaum umhin kommen, das ganze Spielfeld zu prüfen (außer die letzten drei Felder, aber das ist die Sonderbehandlung wohl kaum wert).

    Technische Umsetzung: Auf welchem Niveau hast du Schwierigkeiten? Mit ein bisschen Multiplikation und Addition kannst du aus 2D-Koordinaten einen Index im Array berechnen. Damit lässt sich das hübscher aufschreiben. Damit dann ein paar verschachtelte Schleifen und Zähler.



  • Ich denke das Niveau bewegt sich auf Anfänger Basis.
    Zusätzlich denke ich das ich eher auf der Suche war nach einem Alogrithmus welcher den Array systematisch nach jedem Zug alle Felder "scannt" und diese dann Auswertet indem er beispielsweise sagt weiviele 2er-Reihen nebeneiandenr sind, 3er, etc.
    Wobei ich gestehen muss das ich hier selber nicht ganz sicher bin nach was ich wirklich gesucht habe. Mein Ziel war es einfach einen Weg zu finden welcher nicht X-viele If-Abfragen beinhaltet und möglicherweise für die Zukunft auch für andere Sachen zu gebrauchen sind.

    Bezüglich deiner 1 Antwort kann ich viel Anfangen und werde ich sicherlich auch gleich ausprobieren.
    Die 2 Antwort wird denke ich schwerer sein, da sich das Spielbrett nicht mit einem [X][Y]-Array aufbaut, sondern nur einen 1-Dimensionalen beinhaltet welcher nach 7 Werten auf die nächste Zeile versetzt wird.

    Bezüglich der Technischen Umsetzung verstehe ich nicht genau was du meinst, bzw. was dies bringen/machen soll/kann. 😕


  • Mod

    Gleànn schrieb:

    Die 2 Antwort wird denke ich schwerer sein, da sich das Spielbrett nicht mit einem [X][Y]-Array aufbaut, sondern nur einen 1-Dimensionalen beinhaltet welcher nach 7 Werten auf die nächste Zeile versetzt wird.

    Ich weiß. Aber dir ist schon klar, dass da ein einfacher mathematischer Zusammenhang besteht?

    In 2D ist es viel einfacher, eine Bedingung wie "in einer Reihe", "in einer Spalte" oder "diagonal" zu formulieren. Und damit auch die Umsetzung im Computer. Und da du ganz einfach von 2D auf 1D umrechnen kannst, ist das auch kein Hindernis.



  • Ist mir soeben beim überlegen der Umsetzung von 1 aufgefallen.

    Ich bin zwar noch unschlüssig wie ich genau Nr. 2 umsetzten kann, doch anstatt weiter fragen zu stellen welche ich mit etwas Brainstorming vlt. auch selber beantworten kann begebe ich mich besser zurück in den Code und bastle mal ein wenig. 🙂



  • http://www.sps-forum.de/simatic/67356-4-gewinnt-auswertung.html

    ganz unten ist ein wenig C-Code der das macht - es werden einfach die möglichen Strecken vom Spielstein aus bewertet, geht bestimmt aber noch kleiner



  • @Gast3
    Danke für die Antwort, doch da ich atm einen Lösungsweg habe welchen ich zuerst ausprobieren will, schaue ich mir den Code nicht an.



  • immer erst mal selber und dann schauen - viel Erfolg



  • Übersichtlich und visuell ansprechend sind Tabellen mit den Offsets im Array, z.B. horizontal nach rechts und diagonal nach links unten:

    typedef int off[2];
    
    off hor[] =
      {
        {0,0},{1,0},{2,0},{3,0},
      };
    
    off diag_l[] =
     {
              {0,0},
            {-1,1},
          {-2,2},
        {-3,3},
      };
    

    Das dann zum prüfen mit den aktuellen Koordinaten verwurschteln™. 🙂



  • Übersichtlich und visuell ansprechend sind Tabellen mit den Offsets im Array

    Wofür soll das sinnvoll sein? kann man doch alles komplett aus dem Wissen Höhe/Breite, aktuelle Position berechnen - wofür vorhalten?



  • Gast3 schrieb:

    Übersichtlich und visuell ansprechend sind Tabellen mit den Offsets im Array

    Wofür soll das sinnvoll sein? kann man doch alles komplett aus dem Wissen Höhe/Breite, aktuelle Position berechnen - wofür vorhalten?

    Die Tabellen mit den Offsets sind schnell geschrieben und einfach zu handhaben.
    Den Code zum prüfen brauche ich nur einmal zu schreiben und je nachdem welche Tabelle ich reinstecke prüft der mir verschiedene Konstellationen.

    Das gefällt mir.



  • Ich verstehe echt nicht was du damit machen willst

    fuer die Bewegung durch die Tabelle brauche ich doch nur
    einen Richtungs-"Vektor" mit z.B. (X=-1, Y=+1) der Rest ergibt
    sich doch automatisch durchs addieren?

    Ich würde es echt gerne verstehen - kannst du ein Beispiel zeigen wie du deine Offset-Tabelle nutzt?



  • Kurzes Feedback:

    Ich kann in der zwischenzeit die Horizontalen Linien prüfen und bin jetzt bei den Vertikalen dran.
    Leider hab ich die nächsten Tage keine Zeit, doch werde ich mich melden sobald alles entweder funktioniert oder eben nicht. 🙂

    Danke nochmals für die Hilfe!

    @FurbleWruble
    Würde mich auch interessieren was du genau damit meinst!



  • du machst meine Rechnung mit der Richtung einfach als Tabelle - ist ja echt nicht so schön da reicht doch eine einfache Funktion

    void laufe_durch(int start_x, int start_y, int richtung_x, int richtung_y, int distanz)
    {
    for(int i = 0; i < distanz; i++)
    {
    int aktuell_x = start_x + i * richtung_x;
    int aktuell_y = start_y + i * richtung_y;

    printf("%d/%d\n", aktuell_x, aktuell_y);
    }
    }

    //horizontal von 0/0 nach 5/0
    laufe_durch(0,0, 1,0, 5);
    //vertikal von 5/5 nach 5/0
    laufe_durch(5,5, 0,-1, 5);
    //diagonal von 0/0 nach 5/5
    laufe_durch(0,0, 1,1, 5);

    der Gewonnen-Test bleibt bei allen gleich



  • Gleànn schrieb:

    @FurbleWruble
    Würde mich auch interessieren was du genau damit meinst!

    Beispiel:

    #include <stdio.h>
    
    typedef struct {
      int v0, v1;
    } pos, off;
    
    void pos_print(const pos *p) {
      printf("(%d,%d)\n", p->v0, p->v1);
    }
    
    void print(const pos *p, const off *o) {
      pos_print(p);
      for(int i=0; i<3; ++i) {
        pos cur = {p->v0+o[i].v0, p->v1+o[i].v1};
        pos_print(&cur);
      }
    }
    
    void s(const pos *p) {
      print(p, (off[]){
        {0,1},
        {0,2},
        {0,3},    
      });
    }
    
    void sw(const pos *p) {
      print(p, (off[]){
              {-1,1},
            {-2,2},
          {-3,3},
      });
    }
    
    int main(void) {
      s(&(pos){0,0});
      sw(&(pos){42, 31415});
    }
    

    Bei so einfach zu beschreibenden Mustern wie Strecken ist das tatsächlich nicht sooo sexy. 😞
    Evtl. geht die von mir gepriesene "ansprechende Form" auch flöten, weil ich Zeilen einsparen musste, damit es im Vergleich zu Gast3s Lösung nicht wie Codebloat wirkt... (Der Compound Literals wegen wirst Du auch einen C99 Compiler brauchen.)
    Jetzt weißt Du aber, wie ich das meinte.


  • Mod

    Das kommt mir vor, wie die ultimative Lösung, wenn wir mal R-gewinnt programmieren wollen; ein Spiel bei dem die Spielsteine die Form des Buchstabens 'R' bilden müssen, um zu gewinnen.



  • SeppJ schrieb:

    Das kommt mir vor, wie die ultimative Lösung, wenn wir mal R-gewinnt programmieren wollen; ein Spiel bei dem die Spielsteine die Form des Buchstabens 'R' bilden müssen, um zu gewinnen.

    Hahaha...! Kasper gefrühstückt, was? 🙂


Anmelden zum Antworten