Hilfe bei Vier Gewinnt



  • Hallo muss ein Vier Gewinnt mit CPP schreiben...
    hab auch schon angefangen und gibt mir schonmal die Shapes bei start aus...
    bin grade beim herunterfallen der steine... weiss aber nochnet wie ich des animieren soll...
    hab des mal mit ner for schleife versucht
    -> Versuch

    for(int y=1; y<MAXY; y++){
    Panels[y][0]->Color = clRed;
    Sleep(50);
    Panels[y-1][0]->Color = clWhite; }
    }
    

    so nebenbei die steine werden per buttonklick fallengelassen für die 8 felder gibt es jeweils ein button...
    hab jetzt wie oben beim code zu sehen ist einfach mal rot werden lassen dann weiss dann wieder rot usw bis er unten ist... aber wenn ich button drücke zeigt er mir einfach nur unten den roten an und des wars dann auch schon...

    Kann mir jemand vielleicht helfen? Thx

    gruss morphY

    Hier nochmal die vorgaben...
    Ihr Programm hat folgende Minimalbedingungen zu erfüllen:
    – das Spielbrett soll 8 x 8 Felder groß sein
    – es sollen nur zwei Spieler gegeneinander spielen können (kein Spiel gegen den Computer)
    – nach jedem Zug ist zu prüfen, ob es einen Sieger gibt
    – es ist „Unentschieden“ anzuzeigen, wenn alle Felder besetzt sind, aber kein Sieger feststeht
    – es sind die jeweils nächste Zugfarbe und das zuletzt gesetzte Feld anzuzeigen
    – das Herunterfallen der Steine sollen grafisch animiert werden.
    – es muss ein Button vorhanden sein, um das Spielbrett zu leeren und ein neues Spiel
    beginnen zu können
    – Spielbrettdaten und GUI sollen stets voneinander getrennt sein. Die Spielbrettdaten sind
    daher in einem Array zu speichern. Die GUI ist lediglich ein Abbild der Daten.



  • Pack ein Application->ProcessMessages(); in die Schleife.
    Siehe auch die FAQ, "Verzögerungsfunktion".



  • hmm geht soweit

    for(int y=1; y<MAXY; y++){
      Panels[y][0]->Color = clRed;
      Sleep(500);
      Application->ProcessMessages();
      Panels[y-1][0]->Color = clWhite;
    }
    

    jetzt muss ich es hier einbauen...

    if(start == 0){
        Panels[counter2][1]->Color = clRed;
        if(counter2 == 0)
          ShowMessage("STOP Reihe voll");
        else
          counter2--;
      }
      else{
        Panels[counter2][1]->Color = clYellow;
    
        if(counter2 == 0)
          ShowMessage("STOP Reihe voll");
        else
          counter2--;
      }
    
      if(start==0)
        start++;
      else
        start--;
    

    hab das mal soo versucht

    if(start == 0){
        for(int y=counter2; y<MAXY; y++){
        Panels[counter2][1]->Color = clRed;
        Sleep(500);
        Application->ProcessMessages();
        Panels[counter2-1][0]->Color = clWhite;
         }
        if(counter2 == 0)
          ShowMessage("STOP Reihe voll");
        else
          counter2--;
        }
      else{
      for(int x=counter2; x<MAXY; x++){
        Panels[counter2][1]->Color = clYellow;
            Sleep(500);
        Application->ProcessMessages();
        Panels[counter2-1][0]->Color = clWhite;
        }
        if(counter2 == 0)
          ShowMessage("STOP Reihe voll");
        else
          counter2--;
      }
    
      if(start==0)
        start++;
      else
        start--;
    

    und er macht mir des voll krum... manche macht er weiss dann wieder geld usw O.o
    sehr strange...

    sieht hier vielleicht jemand den fehler?

    thx im vorraus

    greetz
    morphY



  • des mit dem optischen fall funzt war net so richtig aber des werd ich noch lösen hab ja noch bissl zeit...

    des spiel sieht schon ganz gut aus... und läuft soweit ^^

    bin grade dabei zu gucken wie ich des mache das er erkennt das vier in einer reihe sind

    ich schreibe in ein 2dimenisonales array die werte 0 und 1 rein
    0 für rot und 1 für gelb

    hat jemand ne idee wie man es einfach ausliesst wo dann vier mal die gleiche zahl ist???

    thx im vor raus

    greetz

    morphY



  • Hallo

    dazu mußt du beim Setzen eines Feldes auf gesetzt (1 oder 0) eben die umliegenden Stellen vergleichen.
    Du hast als Reihen eine Zeile, eine Spalte und zwei Diagonalen, die du nacheinander überprüfst. Von dem geänderten Feld aus gehst du jeweils maximal 3 Position in beide Richtungen der aktuellen Reihe und zählst, wie viele gleichfarbige Felder es direkt hintereinander gibt. Ist die Summe der beiden Richtungen >= 4, hat der Spieler gewonnen.

    bis bald
    akari



  • hab mir da auch schon sowas in der art gedacht O.o

    nur bekomm ich des net gecoded O.o

    will net in meinen kopp... ich weiss zwar was ich machen will aber ich weiss net so richitg wie O.o



  • hatte jetzt mal ne idee... waagerechte und senkrechte gehen auch...

    köönnte man diesen Code noch optimieren???

    void TVierGewinnt::viergewinnt(int cx)
    {
    
      for(int cy=MAXY; cy>=0; cy--)
      {
       //ab hier senkrechte abfrage
        if(feldwerte[cy][cx] == 0)
        {
          if(feldwerte[cy-1][cx] == 0)
          {
            if(feldwerte[cy-2][cx] == 0)
            {
              if(feldwerte[cy-3][cx] == 0)
              {
               ShowMessage("Rot Hat gewonnen");
              }
            }
          }
        }
        else
        {
          if(feldwerte[cy][cx] == 1)
          {
            if(feldwerte[cy-1][cx] == 1)
            {
              if(feldwerte[cy-2][cx] == 1)
              {
                if(feldwerte[cy-3][cx] == 1)
                {
                 ShowMessage("Gelb Hat gewonnen");
                }
              }
            }
          }
        }
        //ab hier ende der Senkrechten abfrage
    
      }//ende for schleife
    
    //ab hier waagerechte abfrage
      for(int cy2=MAXY; cy2>=0; cy2--)
      {
        for(int cx2=0; cx2<=4; cx2++)
        {
          if(feldwerte[cy2][cx2] == 0)
          {
            if(feldwerte[cy2][cx2+1] == 0)
            {
              if(feldwerte[cy2][cx2+2] == 0)
              {
                if(feldwerte[cy2][cx2+3] == 0)
                {
                  ShowMessage("Rot Hat gewonnen");
                }
              }
            }
          }
          else
          {
            if(feldwerte[cy2][cx2] == 1)
            {
              if(feldwerte[cy2][cx2+1] == 1)
              {
                if(feldwerte[cy2][cx2+2] == 1)
                {
                  if(feldwerte[cy2][cx2+3] == 1)
                  {
                    ShowMessage("Gelb Hat gewonnen");
                  }
                }
              }
            }
          }
        }
      }
    
    }
    

    greetz

    morphY



  • Hallo

    auf jeden Fall kann man das optimieren.
    - da du ja diese Überprüfungsfunktion für genau einen Spieler durchführst, kannst du dessen Farbe der Funktion als parameter übergeben

    bool TVierGewinnt::viergewinnt(int cx, int pcolor)
    

    dann brauchst du nur eine Überprüfung auf den Parameter

    if(feldwerte[cy-3][cx] == pcolor) return(true);
    

    als letzten Befehl gibst du false zurück. Wenn du jetzt diese Funktion für einen Spieler aufrufst, bekommst du true zurück, wenn er gewinnt, ansonsten false.
    Daraufhin kannst du deine Meldung anzeigen.

    if(feldwerte[cy][cx] == 0)
        {
          if(feldwerte[cy-1][cx] == 0)
          {
            if(feldwerte[cy-2][cx] == 0)
            {
              if(feldwerte[cy-3][cx] == 0)
              {
               ShowMessage("Rot Hat gewonnen");
              }
            }
          }
    

    daraus machen wir

    for (int Lv = 0; Lv < 4; Lv++)
      if(feldwerte[cy -Lv][cx] == pcolor) return(true)
    

    Ich würde dir ja gerne noch mehr Tips geben. Aber leider blicke ich da nicht durch.
    Mußt du für die Überprüfung nicht einen x- und einen y-Wert übergeben?

    bis bald
    akari



  • wow gute idee 🙂

    habs net so drauf mit cpp ^^ mach des erst nen knappes halbes jahr...

    ne ich muss da nix zurückgeben

    also ich ruf die funktion bei jeden button auf und muss ja jedes mal nen anderen wert für die X achse übergeben ^^ deswegen immer soviel mit x ^^

    hier mal nen beispiel

    void __fastcall TVierGewinnt::btn_einsClick(TObject *Sender)
    {
       fuellen(counter1, xwert);
       counter1--;
       weristdran();
       viergewinnt(xwert);
    }
    

    xwert ist in dem fall 0 !

    bei button 2 ist es xwert+1 usw
    weil er ja im 2 dimensionalen array immer eine spalte weiter muss weil des ja die xachse ist.

    und des y fällt in dem fall eh weg... weil ich haben ja für jeder spallte einen button... und da muss ich nur x übergeben ddamit er weiss in welcher spalte er ist und y zählt er eh von 7 nach 0 runter..
    so ich muss jetzt erstemal deinen code verstehen ^^ weil wenn ich des so kürzen könnte hätte ich es auch einfacher mit dem strucktogramm ^^

    weil wir sollen zur gewinnprüfung noch nen struktogramm machen O.o

    so wie iche s mache sind es ja 100 seiten ^^



  • Hallo

    ach so, habe wohl das Spielprinzip verwechselt.
    du solltest auf jeden Fall die Überprüfung von dem Spieler abhängig machen, den du mit weristdran() ermittelst.
    Und wenn du in viergewinnt() true oder false zurückgibst, hast du nur eine zentrale Gewinn-Nachricht. Außerdem wird die Überprüfung sofort abgebrochen, wenn ein Spieler gewinnt, statt noch alle nachfolgenden Fälle zu überprüfen.
    Im schlimmsten Fall hast du so auch mehrere Gewinn-Nachrichten, wenn mehrere Fälle auf einmal erfüllt werden.

    Wenn ich mir noch mal diesen Punkt der Aufgabenstellung anschaue

    Spielbrettdaten und GUI sollen stets voneinander getrennt sein. Die Spielbrettdaten sind
    daher in einem Array zu speichern. Die GUI ist lediglich ein Abbild der Daten.

    bezweifle ich, das du den mit deinem Aufbau erfüllst.
    Vielleicht solltest du noch mal nachfragen, wie weit die Trennung gehen soll.
    Ich würde nämlich eine unabhängige Klasse TSpielbrett schreiben, die alle wichtigen Daten (Array, aktueller Spieler,...) enthält, und dieser entsprechende Funktion wie ÄndereSpieler() und SetzteFarbe() zuordnen.

    bis bald
    akari



  • das mit gui und so frag ich am mittwoch mal...

    hab aber grade erleuschtung und ferstanden was du damit meintest ^^

    for (int Lv = 0; Lv < 4; Lv++)
      if(feldwerte[cy -Lv][cx] == pcolor) return(true)
    

    da spar ich mir die 4 if abfragen ^^ habsch gar net dran gedacht... nur das mit dem bool rall ich nochnet so... hab des bis jetzt nochnie verwendet... deswegen...

    könntest du mir da bitte nochmal helfen des richitg anzuwenden ???

    bekomm des nicht hin

    bool TVierGewinnt::viergewinnt(int cx, int pcolor)
    {
    
      for(int cy=MAXY; cy>=0; cy--)
      {
        for (int Lv = 0; Lv < 4; Lv++){
        if(feldwerte[cy -Lv][cx] == pcolor)
        return(true);//senkrechte
    
        if(feldwerte[cy][cx+Lv] == pcolor)
        return(true);//waagerechte
        }//ende innere for schleife
      }//ende for schleife
    }
    

    des funzt net so richitg....

    thx im vorraus

    greetz

    morphY



  • hey akari haste mich vergessen???

    ich versteh bei deinem code

    for (int Lv = 0; Lv < 4; Lv++)
      if(feldwerte[cy -Lv][cx] == pcolor) return(true)
    

    wie der dann die einzelnen felder durchfragt... ich blick des net...

    greetz

    morphY



  • Hallo

    was soll ich da noch erklären? Wenn ich mir dein Code aus dem vorletzten Post anschaue, denk ich doch, du weißt was es mit der Schleife auf sich hat.
    Vielleicht hilft die diese Aufdröselung, es zu verstehen:

    int help;
    for (int Lv = 0; Lv < 4; Lv++)
    {
      Help = cy -Lv; // aktuellen um 1 verringerten Spaltenindex berechnen
      if(feldwerte[Help][cx] == pcolor) return(true);
      }
    
    // oder auch
    for (int Lv = cy; Lv > cy -4; Lv--)
      if(feldwerte[Lv][cx] == pcolor) return(true);
    

    Ich glaube, du solltest dir noch mal den Alogithmus an sich durch den Kopf gehen lassen. Ich blicke da nämlich nicht durch.

    bis bald
    akari



  • was des macht habsch schon verstanden...

    nur mein problem ist es damit weiterzuarbeiten...

    weil der gibt ja nun immer true zurück...

    und sobald ich ein stein setze hat der gleich gewonnen... es hapert wohl eher daran das ich nicht mit dem true oder false weiterkomme...

    //gewinnfestellung
    bool TVierGewinnt::viergewinnt(int cx, int pcolor)
    {
      for(int cy=MAXY; cy>=0; cy--)
      {
        for (int cv = 0; cv < 4; cv++){
        if(feldwerte[cy -cv][cx] == pcolor)return(true);
        }
      }//ende for schleife
    }
    
    void __fastcall TVierGewinnt::btn_zweiClick(TObject *Sender)
    {
        fuellen(counter2, xwert+1);
        counter2--;
        weristdran();
        if(viergewinnt(xwert+1, start) == True)
          ShowMessage(start); // wer gewónnen hat...
    
    }
    

    hast du ne mailadresse? da kannsch dir das ja mal schicken 🙂

    greetz
    morphY



  • Hallo

    du mußt noch die richtigen Steine zählen

    //gewinnfestellung
    bool TVierGewinnt::viergewinnt(int cx, int pcolor)
    {
      int count = 0;
      for(int cy=MAXY; cy>=0; cy--)
      {
        count = 0;
        for (int cv = 0; cv < 4; cv++){
          if(feldwerte[cy -cv][cx] == pcolor) count++;
          } 
        if (count == 4) return(true); 
        count = 0;
        // nächste Überprüfung
        }//ende for schleife
    
      return(true);
    }
    

    bis bald
    akari



  • ich weiss echt net was da net stimmt... der macht es immernochnet richitg...

    hab des so gemacht

    //gewinnfestellung
    bool TVierGewinnt::viergewinnt(int cx, int pcolor)
    {
      int count = 0;
      for(int cy=MAXY; cy>=0; cy--)
      {
        count = 0;
        for (int cv = 0; cv < 4; cv++){
          if(feldwerte[cy -cv][cx] == pcolor) count++;
          }
        if (count == 4) return(true);
        count = 0;
        // nächste Überprüfung
        }//ende for schleife
      return(false);
    }
    

    und unten frag ich des dann so ab!

    void __fastcall TVierGewinnt::Bbtn_einsClick(TObject *Sender)
    {
       fuellen(counter1, xwert);
       counter1--;
       weristdran();
       if(viergewinnt(xwert, start) == true);
       ShowMessage(start);
    }
    

    und der sagt immer sobald ich ein stein setze das die farbe die grade gesetzt gat gewonnen hat !

    was mach ich nur falsch

    greetz
    morphY



  • Hallo

    if(viergewinnt(xwert, start) == true); // << Semikolon weg!
       ShowMessage(start);
    

    bis bald
    akari



  • hmm danke geht soweit 🙂

    hab noch nen fehler bei mir gefunden... ist aber behoben ^^
    veränder den start wert ( also wer grade dran ist) zu früh)
    also fragt der mit dem falschen wert ab...

    jetzt habsch nurnoch ein problem ^^ der sagt schon bei 3 das vier gewinnt ist ^^ aber ich debugge mal schnell und dann werd ich den fehler schon finden

    greetz
    morphY

    fettes merci nochmal 🙂

    //edit

    habs

    bool TVierGewinnt::viergewinnt(int cx, int scolor)
    {
      int count = 0;
      for(int cy=MAXY-1; cy>=0; cy--)//MAX=8 muss aber 7 sein ^^ array geht ja nur von 0-7 ^^ also minus 1 und es geht :)
      {
        count = 0;
        for (int cv = 0; cv <= 4; cv++){
          if(feldwerte[cy -cv][cx] == scolor)
          count++;
          }
        if (count == 4) return(true);
        count = 0;
        // nächste Überprüfung
        }//ende for schleife
      return(false);
    }
    

    hmm ich mach jetzt noch auf jeden fall die waagerechte und dann ist erstemal schluss für heute 🙂

    ich meld mich ncohmal wenn es probleme gibt 😃



  • So meine gewinnprüfung läuft nun fehlerfrei...
    das visuelle fallen der steine habsch nun auch gelöst und die ganzen kleinigkeiten sind nun auch erledigt...

    hat jemand ne idee wie ich es am besten löse das er sich die letzten 5 züge speichert, damit man später zuge zurücknehmen kann???

    greetz

    morphY



  • Hallo

    indem ein weiteres Array über ints aufmachst, in dem beim Setzen eines neuen Steines in die erste Position der Wert der neueste Spalten kommt, während alle anderen Positionen um eins nach hinten rutschen und der letzte wegfällt.
    Eventuell bietet die STL einen passenden Container, ansonsten ist sowas auch leicht selbst gemacht.

    bis bald
    akari


Anmelden zum Antworten