Memory-Spiel

Manda

Erfahrenes Mitglied
Hallo erstmal,
bin gerade dabei ein memory-spiel fertig zu kriegen. läuft auch einiger maßen ganz gut, muss es allerdings jetzt erweitern. Da es jetzt ziemlich kompliziert geworden ist (für mich zumindest), blicke ich hier nicht mehr wirklich durch. Ist ziemlich viel code, ich könnte es auch jemanden per mail schicken der sich mit sowas auskennt und vielleicht lust hat sich damit zu beschäftigen. Brauche wirklich hilfe, komme überhaupt nich mehr weiter.
Also folgendes habe ich gemacht:
Ich habe 2Units angelegt(1. Hauptformular(HF), 2. Memoryfeld(MF))
Code:
HAUPTFORMULAR:
void __fastcall TForm1:: DrawGrid1DblClick(TObject *Sender)
{
int x = DrawGrid1->Col;  //den Variablen die pos der zelle zuweisen
int y = DrawGrid1->Row;  //auf die doppel geklickt wurde

if(SpielFeld.OffeneKarten == 0 && SpielFeld.player == 1)//überprüfen ober s1(pc) zug beendet hat, wert mit 0 testen
   SpielFeld.player = 0; //wenn der zug beendet ist, ist s2(mensch) dran player0 also

if(SpielFeld.OffeneKarten == 0 && SpielFeld.player == 0)
{ //überprüfung ob noch keine karte umgdr ist, wenn nich, dann methode KarteOeffnen() mit der pos der karte auf den doppel geklickt wurde
      if(SpielFeld.SpielFeld[x][y] == 22)
         SpielFeld.KarteOeffnen(x,y);
}
else
if(SpielFeld.OffeneKarten == 1 && SpielFeld.player == 0)
{ //wenn karte bereits umgr ist, überprüfung ob die karte an der pos noch zugedeckt ist
        if(SpielFeld.SpielFeld[x][y] == 22) //vergleich mit der dem bildindex (22) für verdeckte karte
        {  //wenn zugedeckt dann methode KarteOeffnen() mit pos aufrufen
           SpielFeld.KarteOeffnen(x,y);
           Timer1->Enabled = 1;    //timer aktivieren
        }
}
DrawGrid1->Repaint(); //tabelle wird neu gezeichnet
}

void __fastcall TForm1:: Timer1Timer(TObject *Sender)
{
Timer1->Enabled = 0; //timer wird deaktiviert
SpielFeld.SchliesseKarten();
Label3->Caption=IntToStr(SpielFeld.Paare[0]);
Label4->Caption=IntToStr(SpielFeld.Paare[1]);

if(SpielFeld.Paare[0] < SpielFeld.Paare[1])
{
        Label5->Caption = "Computer gewinnt";
}
else 
{
        Label5->Caption = "Mensch gewinnt";
}
if(SpielFeld.Paare[0] == SpielFeld.Paare[1])
{
        Label5->Caption = "Unentschieden";
}

DrawGrid1->Repaint();
}

MEMORYFELD:
MemoryFeld:: MemoryFeld()    //konstruktor
{
        int bild = 0;
        int Feld[42];
        OffeneKarten = 0;
        player = 0;
        Paare[0] = 0;
        Paare[1] = 0;

        for(int i=0; i<21; i++)
                for(int j=0; j<2; j++)
                {
                        Aufgedeckt[i][j].x = -1;
                        Aufgedeckt[i][j].y = -1;
                }

        for(int i=0; i<42; i++)
        {
                Feld[i] = bild;
                if(((i+1) % 2 == 0)) bild++;    //sorgt dafür, dass der Wert von 'bild' bei jedem 2. lauf erhöht wird
        }
        randomize();
        random_shuffle(Feld,Feld+42);

        for(int i=0; i<7; i++)
                for(int j=0; j<6; j++)
                {
                InitFeld[i][j] = Feld[j*7+i];   //man bewegt sich immer eine Zelle weiter, zufällig angeordneten werte werden in 'InitFeld' kopiert
                SpielFeld[i][j]= 22;            //das feld 'SpielFeld' wird belegt, auf allen pos mit wert 22
                }
}

void MemoryFeld:: KarteOeffnen(int x, int y)
{
        int a = 0;
        SpielFeld[x][y] = InitFeld[x][y];
        OffeneKartenPos[OffeneKarten].x = x; //OffeneKartenPos erhält die pos der aktuell umgedrehten karten, wenn keine umgr. dann 0 sonst 1
        OffeneKartenPos[OffeneKarten].y = y;

        if(Aufgedeckt[SpielFeld[x][y]][0].x != -1 && !(Aufgedeckt[SpielFeld[x][y]][0].x == x && Aufgedeckt[SpielFeld[x][y]][0].y == y) )
        a = 1;
        Aufgedeckt[SpielFeld[x][y]][a].x = x;//Speichern die pos der gerade umgdr. karten
        Aufgedeckt[SpielFeld[x][y]][a].y = y;
        OffeneKarten++;
}

void MemoryFeld:: SchliesseKarten()
{
        bool treffer = 0;

if(InitFeld[OffeneKartenPos[0].x][OffeneKartenPos[0].y] == InitFeld[OffeneKartenPos[1].x][OffeneKartenPos[1].y])
{//überprüfung ob die aufgedeckten karten gleich sind, greifen mit OffeneKartenPos auf die entsprechende Elemente im Feld InitFeld
  SpielFeld[OffeneKartenPos[0].x][OffeneKartenPos[0].y] = 21;
  for(int i=0; i<2; i++)
  {
   Aufgedeckt[InitFeld[OffeneKartenPos[i].x][OffeneKartenPos[i].y]][i].x = -1;
  }
   Paare[player]++;
   treffer = 1;
}
else
{  //karten werden wieder zu gedeckt, weil unterschiedlich
   SpielFeld[OffeneKartenPos[0].x][OffeneKartenPos[0].y] = 22;
   SpielFeld[OffeneKartenPos[1].x][OffeneKartenPos[1].y] = 22;
}
   OffeneKarten = 0;

   if( (Paare[0]+Paare[1]) != 21 ) //überprüfung ob alle paare aufgedeckt wurden
   {
     if( (player==0 && treffer==0) || (player==1 && treffer ==1) ) //sonst pc am zug
     {
       player = 1;
       ComputerZug();
     }
}
}

void MemoryFeld:: ComputerZug()
{
        int x1, y1, x2, y2, found = 0;
        randomize();
        for(int i=0; i<21; i++)
        {
                if(Aufgedeckt[i][0].x != -1 && Aufgedeckt[i][1].x != -1)
                {//überprüfen ob sich 2 gleiche bilder im element befinden, also beide wert !=-1 haben
                        x1 = Aufgedeckt[i][0].x;//pos auslesen und den variablen zuweisen
                        y1 = Aufgedeckt[i][0].y;
                        x2 = Aufgedeckt[i][1].x;
                        y2 = Aufgedeckt[i][1].y;
                        found = 1;
                }
        }
        found=(found && random(2));
        if(found == 1)
                KarteOeffnen(x2, y2);  //wenn gefunden, dann eine karte umdrehen, die anderen nach dem neu zeichen
        else
        {  //wenn kein paar gefunden, eine zufällige pos im spielfeld erzeugen
                do
                {
                        x1 = random(7);
                        y1 = random(6);
                }
                while(SpielFeld[x1][y1] != 22);
        if(Aufgedeckt[InitFeld[x1][y1]][0].x != -1 && !(Aufgedeckt[InitFeld[x1][y1]][0].x==x1 && Aufgedeckt[InitFeld[x1][y1]][0].y==y1) )
        {//testen ob sich die karten an der zufälligen pos im feld 'aufgedeckt' befinden + dann vergleichen
                KarteOeffnen(Aufgedeckt[InitFeld[x1][y1]][0].x, Aufgedeckt[InitFeld[x1][y1]][0].y);
        }
        else
        {
                do
                {
                        x2 = random(7);
                        y2 = random(6);
                }
                while(SpielFeld[x2][y2] != 22 || (x1==x2 && y1==y2));
                KarteOeffnen(x2,y2);
        }
        }
        KarteOeffnen(x1,y1);
        Form1->DrawGrid1->Repaint();
        Form1->Timer1->Enabled = 1;
}

und die KLASSE:
struct pos{int x; int y;}; //zum speichern der position auf dem spielfeld

class MemoryFeld
{
public:
        MemoryFeld();
        void KarteOeffnen(int x, int y);      //wird aufgerufen, wenn umgedreht+anzeigen soll
        void SchliesseKarten();               //aufruf, wenn vom spielfeld nehmen oder umdrehen
        void ComputerZug();                   //spielzüge vom PC steuern
        int OffeneKarten;                     //speichert die anzahl der aufgedeckten karten
        int player;                           //nimmt die nr des spielers auf, 1=pc 0=mensch
        pos OffeneKartenPos[2];               //speichert die pos. aufgedeckten karten
        int Paare[2];                         //speichert die anzahl der paare, die aufgedeckt wurden
        int InitFeld[7][6];                   //speicherung der indizes der bilder
        int SpielFeld[7][6];                  //speichert den aktuellen zustand des spielfeldes
        pos Aufgedeckt[21][2];                //speichert die pos der karten, die 1x aufgedeckt wurden
};

Also, ist schon ziemlich viel code, und ehrlich gesagt weis ich nicht genau ob das (alles) hier rein gehört, aber ich versuchs trotzdem mal.
Folgendes Problem:
Ich muss nur ein Button ein meiner Anwenung haben ([Alles Aufdecken]), dass wie der name schon sagt, alles aufdeckt, wenn man darauf klickt. Aber nur für eine kurze zeit, dann wieder alles umderehen.
Hinweis: Bildindex 22 = die karte mit dem bild "verdeckt"; und 21 = "aufgedeckt";
 
Hi,
Ich habe das schon hinter mir, anfangs hab ich immer in die falsche Richtung gedacht, aber wo ich es hatte hab ich mir gesagt so schwer ist das doch gar nicht. Deshalb versuch es weiter, du schafst das,nicht gleich aufgeben wenn es wieder Falsch war.

MfG stimon
 
Du könntest mir doch vielleicht einen kleinen Tip geben, wie man daran gehn könnte. Ich versuch das schon eine ganze weile, aber komme nicht dahinter^^. Hast du ein Tip für mich
Eine andere Frage mal,
ich will aus einem Formular(Form1) mit einem button [Einstellungen] auf ein anderes Formular(Form2) zu greifen. Das andere Formular bekomme ich zwar angezeigt, aber kann nichts bearbeiten.
Form2 hat 3eingabefelder, wo was drin steht. In der Aufgabe steht, zuerst diese 3 Eingabefelder Initialisieren mit den entsprechenden Werten, vor dem Aufruf der Funktion. Wie mache ich das
So habe ich von Form1 aus auf Form 2 zu gegriffen:
Form2->Edit1->Text=NMPOP31->Host;
Form2->Edit2->Text=NMPOP31->UserId;
Form2->Edit3->Text=NMPOP31->Password;
Ich kann aber in Form2 nichts bearbeiten. Weist du/ihr vielleicht weiter Bedanke mich für jede hilfe
 
Hi,

ein kleiner Tip, du must ein globales Feld um den aktuellen Zustand des SpielFeld zwischenzuspeichern. Ebenfalls 2 neue Funktionen (kartenschließen u. allesaufdecken).

zu dem Mail-Programm
Das hier steht in FormCreate:
Form2->Edit1->Text=Form1->NMPOP31->Host;
Form2->Edit2->Text=Form1->NMPOP31->UserId;
Form2->Edit3->Text=Form1->NMPOP31->Password;
wenn man so die werte ermittelt geht es auch anders herum, probiers einfach.
Hast du auch richtig included?

Gruß
stimon
 
Genau das mit den Zwischenspeichern ist das Problem, ich weiß nur nicht wo ich das machen soll. Über der Klassen Definition und 2methoden in die klasse reinschreiben?

und zu der anderen Aufg.:
Das andersrum geht irgendwie nicht. Ich Versuche es damit: Form1->... aber was soll ich denn ansprechen? Etwa den Host, UserId und Password
Und das mit includen glaube ich, habe ich richtig gemacht, weil ich ja sonst nicht von Form1 auf Form2 zugreifen könnte oder? Ich kann ja das andere (also Form2) sehn aber nur nicht bearbeiten, kann nicht mal darauf klicken.
Wenn du mir sagen könntest wie ich das Initialisieren kann

Gruß
Manda
 
Ich hab wieder einmal intensiver darüber nachgedacht, vielleicht kannst du mir ja sagen ob ich in die richtige Richtung denke. Folgendes:
Ich schreibe 2Methoden in die Klasse, wie du schon vorgeschlagen hast (kartenschliessen + allesumdrehen). Dann ein Feld wo ich das zwischenspeichern kann, bsp.: int NeuesFeld[7][6] dies dann auch in die klasse( ich glaube mal auch mit den selben dimensionen).
Würden die beiden neuen Methoden so indentisch aussehen wie die bereits vorhandenen? Und speichere ich den Spielstand vielleicht so ab: NeusFeld[x][y] = InitFeld[x][y];
Falls ja, dann müsste ich bestimmt parameter angabe machen, für die Methode 'allesumdrehen'.
Geht dieser Gedanke in die Richtige Richtun!! Ich hoffe du kannst mir sonst noch ein paar tips geben, falls ich "falsch" denke.

Gruß
Manda
 
Hi,

nein nicht InitFeld, sondern das Spielfeld.
Die beiden Methoden sehen nicht so aus wie die anderen, aber es sind alle Fälle ein paar Zeilen dabei, natürlich mit anderen Namen, die Methoden aber auch nicht mehr als 6 Zeilen so zumindest bei mir, aber keine Angst bei mir es. Und glaub mir am Ende fäst du dir an den Kopf!

Hast du auch Unit2 in Form1 included, und kontrolier mal die Enabled Eigenschaft der Kompos. . Ach und das was du ändern willst müste man auch ansprechen.
Initialisieren der Werte in Form2: Das hier steht dann in FormCreate:
Form2->Edit1->Text=Form1->NMPOP31->Host;
Form2->Edit2->Text=Form1->NMPOP31->UserId;
Form2->Edit3->Text=Form1->NMPOP31->Password;


Gruß
stimon
 
Also habe folgendes gemacht:
in der Klasse:
int NSpielFeld[7[[6]; um es zwischenzuspeichern
void AllesAufdecken(int x, int y);
void AllesUmdrehen();

void MemoryFeld::AllesAufdecken(int x, int y)
{
NSpielFeld[x][y] = SpielFeld[x][y];
OffeneKartenPos[OffeneKarten].x = x;
OffeneKartenPos[OffeneKarten].y = y;

if( !(Aufgedeckt[NSpielFeld[x][y]][0].x == 21) && !(Aufgedeckt[NSpielFeld[x][y]][0].y == 21) )
}
Nur weis ich jetzt nicht ob es richitg ist, weis nicht genau was nach der if-abfrage kommt. Hast du einen Tip
Die andere Methode (AllesUmdrehen()) habe ich noch nich geschrieben. Und mein Button sieht folgender maßen aus:

int x = DrawGrid1->Col;
int y = DrawGrid1->Row;
SpielFeld.AllesAufdecken(x,y

Ich hoffe wirklich das es langsam mal klappt, das nervt schon langsam, komme einfach nicht weiter. Naja vielleicht kannst du mir mal sagen ob es so sein könnte!

Gruß
Manda
 
Hi,

Die AllesAufdecken() und Allesschliessen() Methode, übergeben keine werte und es kommen in jeder 2 for-Schleifen zum Einsatz. Zwischenspeichern tust du so:
Code:
allesaufdecken[i][j]=Spielfeld[i][j];
und das ganze unter
Code:
Spielfeld[i][j]=22;
also mehr kann ich wirklich nicht sagen sonst lernst du doch nichts mehr dabei.
Button1 und Timer2 enthalten lediglich dann die Methoden und nix mit
Code:
int x = DrawGrid1->Col;
int y = DrawGrid1->Row;

sondern;
Code:
SpielFeld.AllesAufdecken();

Gruß
stimon
 
Hallo Stimon,

hab mal (wieder) eine Frage, zum E-mail Programm aber.
Das mit include habe ich soweit richtig gemacht. Was meintest du mit "FormCreate"? und was meintest du mit Einstellungen überprüfen, ob Enabled? Sollten die 3EditFelder alle auf false gesetzt sein?
Mein Einstellung Button in Form1 sieht so aus:
Form2->Show();
Form2->Edit1->Text=NMPOP31->Host;
Form2->Edit2->Text=NMPOP31->UserID;
Form2->Edit3->Text=NMPOP31->Password;

Die 3EditFelder in Form2 so:
Edit1: Form1->NMPOP31->Host;
Edit2: Form1->NMPOP31->UserId;
Edit3: Form1->NMPOP31->Password;

Leider kann ich immer noch nicht auf Form2 zugreifen. Dann hab ich es mit deinem Beispiel auch versucht, also:
Form2->Edit1->Text=Form1->NMPOP31->Host;
Form2->Edit2->Text=Form1->NMPOP31->UserId;
Form2->Edit3->Text=Form1->NMPOP31->Password;
Dies habe ich dann in Form2, in den einzelnen EditFeldern geschrieben. Ging leider auch nicht. Hast du vielleicht ne Idee Oder hab ich was falsch verstanden?
Danke schonmal für jeden Tip!

MfG
Manda
 
Zurück