### Memory game using OOP

Hey,
i want to make a memory game where you have to find the couples of numbers in the board but i have some questions.

i don't know if every card should be an object (from the same class) or not. for instance i'd like to do something like this:

`card.GetValue(2,3);`

this function goes trough all the cards and finds the one with xCoord=2 and yCoord=3 and gives me the respective value.

but with classes i can't make a single object (card) and access all the cards from that. i would have to make many cards (card1, card2, ...) but then i can't call that function anymore. (`card1.GetValue(2,3);` is only checking if card1 is at the position 2,3 and i want it to check ALL the cards)
(sorry i can't explain it better)

this is a pseudo code to make you understand a little better my problem, it would be great if you guys can point me in the right direction on what to use / what is best to use in this situation.

 ``12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152`` ``````#include using namespace std; class CCard{ int xCor; int yCor; int value; // This is a number from 1 to 8 bool isFaceUp; public: CCard(int x, int y, int val){ // Constructor xCor = x; yCor = y; value = val; isFaceUp = false; } }; void MakeCards(){ // I can't make many cards like this...(it's also ugly) CCard card1(1,1,2); CCard card2(2,1,3); CCard card3(3,1,7); CCard card4(4,1,5); CCard card5(1,2,1); CCard card6(2,2,4); CCard card7(3,2,8); CCard card8(4,2,2); CCard card9(1,3,7); CCard card10(2,3,6); CCard card11(3,3,8); CCard card12(4,3,1); CCard card13(1,4,6); CCard card14(2,4,3); CCard card15(3,4,4); CCard card16(4,4,5); } void ShowBoard(){ for(int y=0;y<4;y++){ for(int x=0;x<4;x++){ cout << GetCardValue(x,y) << " "; //<- When i got the coord from the user } // i would put them in some function cout << endl; // that returns the value of the card } // (the card that meets the coord) } // in this case the coord are given by the loops BTW int main(){ MakeCards(); ShowBoard(); } ``````

The second question is how to fill the board with 8 PAIRS of numbers
(so i have {1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8} and i want to randomly give these values to the cards at each position in the board.)

the end result should look more or less like this:

 ```5 8 4 7 2 1 8 3 6 3 4 7 2 5 1 6```

thanks in advice for the help! and sorry if i made some mistakes ^^
Last edited on
Use an array for the cards. Set the values with loops. Here is a quite frankly lazy way of doing it, but it will give you the idea.
 ``123456789101112131415161718192021`` ``````class card { public: int posx, posy; }; int main() { int i, j, x = 0; card deck[52]; for(i = 0; i < 13; ++i) { for(j = 0; j < 4; ++j) { deck[x].posx = i; deck[x].posy = j; ++x; } } return 0; }``````

You can also use loops to set the values of the cards to whatever numbers and so forth.
Thanks a lot! that was the push i needed to get me started.
so now i have the deck[4][4] that holds all the cards, for now the only problem is how to put all the PAIRS in random positions of the board

the code so far:
 ``1234567891011121314151617181920212223242526272829303132333435363738394041424344454647`` ``````#include #include #include using namespace std; class CCard{ int xCor; int yCor; int value; bool faceUp; public: CCard(){ // Constructor faceUp = false; } void SetValue(int v){ value = v; } int GetValue(){ return value; } } deck[4][4]; void SetCards(){ for(int y=0;y<4;y++){ for(int x=0;x<4;x++){ deck[x][y].SetValue(rand()%8+1); } } } void ShowBoard(){ for(int y=0;y<4;y++){ for(int x=0;x<4;x++){ cout << deck[x][y].GetValue() << " "; } cout << endl; } } int main(){ srand(time(NULL)); SetCards(); ShowBoard(); }``````

Now of curse i give random values at line 29, but i need to put only couples of numbers from 1 to 8, anyone has a good idea?

thanks again for the time ;)
You could just do a bunch of random swaps, something like this:
 ``12345678910111213141516171819202122232425`` ``````#include #include #include int main() { srand(time(NULL)); int n[16] = {1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8}; int x = 0, y = 0, z = 0, swaps = 0, temp = 0; swaps = rand() % 10 + 10; //Number of random swaps we are going to do. while(x < swaps) //1 / 16 times no swap will happen (do you see why?) { y = rand() % 16; //Choose a random array element. temp = n[y]; //Make a copy of the value in that element. z = rand() % 16; //Choose a random array element. n[y] = n[z]; //Put the second array element into the first. n[z] = temp; //Put the copy of the first into the second. ++x; } for(x = 0;x < 16;++x) { std::cout << n[x] << "\n"; } return 0; }``````

This is for a 1d array, but it's not much extra work to make it for 2d.

Edit: Commented code a bit.
Last edited on
 ``1234`` ``````void SetCards(){ for(int y=0;y<4;y++){ for(int x=0;x<4;x++){ deck[x][y].SetValue(rand()%8+1);``````

your cards ARE randomized... however this doesn't guarentee that there will always be a pair

try something like this
 ``1234567891011121314`` ``````void SetCards(){ bool pair=1; int random;; for(int y=0;y<4;y++) for(int x=0;x<4;x++) { if (pair) { random=rand()%8+1; pair=!pair; } deck[x][y].SetValue(random); } }``````
Last edited on
I'd suggest setting up 2 cards at a time (ensuring they have pairs) and then create a loop which swaps the values (or addresses) of the cards.

 ``1234567891011121314`` ``````int num = 8; //However many pairs you want num *= 2; //Used as pairs to prevent odd cards int cards = new int[num]; //This loop sets up pairs for(int i=0; i

Assuming you've seeded the random algorithm with srand()
Last edited on
@threeright:
I like your idea but i believe it's not working as it should for this project, you are making pairs of random numbers but there can be pairs of the same number inside the deck (for example this may happen):
{1,1,3,3,5,5,1,1,7,7,8,8,6,6,4,4}

@SatsumaBenji:
I like your concept a lot, very nice and clean but if i'm not mistaking the code you provided sets Cards this way:
{0,0,2,2,4,4,6,6,8,8,10,10,12,12,14,14}
to have number from 1 to 8 you just have to modify slightly the code:

 ``1234567891011121314`` ``````int num = 8; //However many pairs you want num *= 2; //Used as pairs to prevent odd cards int cards = new int[num]; //This loop sets up pairs for(int i=0; i

right?

anyway i did it more or less like Mats said, by initializing an array with the pairs and then swapping them.

This is the final code if someone wants to try it, i appreciate if you have any suggestions to improve it!
I may make another version where you navigate trough the cards with WASD or the arrow keys instead of inserting the coordinates.

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168`` ``````#include #include #include using namespace std; //Global variables char coordX, coordY; class CCard{ int value; bool faceUp; public: CCard(){ // Constructor faceUp = false; } void SetValue(int v){ value = v; } void TurnCard(){ faceUp = !faceUp; } int GetValue(){ return value; } bool GetFaceUp(){ return faceUp; } } deck[4][4]; void ShowBoard(){ // Prints the board on screen system("cls"); cout << " 1 2 3 4" << endl << endl; for(int y=0;y<4;y++){ cout << y+1 << " "; for(int x=0;x<4;x++){ if(deck[x][y].GetFaceUp() == true){ // If the card is facing up show it cout << deck[x][y].GetValue() << " "; } else{ // If is facing down show an ASCII character (hidden card) cout << (char)177 << " "; } } cout << endl << endl; } cout << endl; } void SetCards(){ // Set the cards in random order int pairs[16] = {1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8}; int a, b, temp; for(int i=0;i<30;i++){ // Swap 30 times a = rand()%16; b = rand()%16; temp = pairs[a]; pairs[a] = pairs[b]; pairs[b] = temp; } for(int y=0;y<4;y++){ for(int x=0;x<4;x++){ deck[x][y].SetValue(pairs[x +(y * 4)]); // Puts swapped cards in the deck } } } void GetInput(){ // Gets the user input bool isAlreadyUp; do{ do{ // Insert X cout << "Insert coordinate X: "; cin >> coordX; // coordX/Y are char to prevent the program from crashing! if(coordX < (1+48) || coordX > (4+48)){ // i have to check based on the ASCII table (48 = 0) cout << "Invalid selection!" << endl; } }while(coordX < (1+48) || coordX > (4+48)); do{ // Insert Y cout << "Insert coordinate Y: "; cin >> coordY; if(coordY < (1+48) || coordY > (4+48)){ cout << "Invalid selection!" << endl; } }while(coordX < (1+48) || coordX > (4+48)); if(deck[(int)(coordX-48-1)][(int)(coordY-48-1)].GetFaceUp() == true){ // If player inputs an already-matched card cout << "You already found the match for this card!" << endl << endl; isAlreadyUp = true; } else{ isAlreadyUp = false; } }while(isAlreadyUp == true); // Adjust values (easier to work with arrays) coordX--; coordY--; } void Pause(){ // Ugly but works fine for(int i=0;i<2000;i++){ for(int j=0;j<300000;j++); } } int main(){ int holderX, holderY, remaining = 16, tries = 0; char reply; bool secondTurn = false; srand(time(NULL)); while(1){ // Infinite loop SetCards(); do{ // Loop until player matched all cards ShowBoard(); GetInput(); deck[(int)(coordX-48)][(int)(coordY-48)].TurnCard(); // Turns the selected card if(secondTurn == true){ // If player turned the second card we have to look if they match secondTurn = false; tries++; if((((int)(coordX-48)) == holderX) && ((int)(coordY-48) == holderY)){ // The user selected the same card twice! tries--; cout << "You can't select the same card twice!" << endl; Pause(); continue; } if(deck[(int)(coordX-48)][(int)(coordY-48)].GetValue() == deck[holderX][holderY].GetValue()){ // If cards match ShowBoard(); cout << "You matched 2 cards!" << endl; remaining -= 2; } else{ // If cards are different ShowBoard(); cout << "The cards are different!" << endl; deck[(int)(coordX-48)][(int)(coordY-48)].TurnCard(); // Turn cards again deck[holderX][holderY].TurnCard(); } Pause(); } else{ // If this is the first card turned, we store the x,y coords for later use holderX = (int)(coordX-48); holderY = (int)(coordY-48); secondTurn = true; } }while(remaining > 0); cout << "Congratulation! you matched all the cards in " << tries << " tries!" << endl; do{ // Asks the user if he wants to play again cout << "Do you want to play again? (y/n): "; cin >> reply; if(reply == 'n' || reply == 'N'){ return 0; } else if(reply != 'n' && reply != 'N' && reply != 'y' && reply != 'Y'){ cout << "Invalid character, try again." << endl << endl; } }while(reply != 'y' && reply != 'Y'); // Reset varables if player wants to play again remaining = 16; tries = 0; for(int y=0;y<4;y++){ for(int x=0;x<4;x++){ deck[x][y].TurnCard(); // Turns all the cards face down } } } } ``````

Thanks again to you all, this was a very fun project! ^^
Last edited on
Indeed it does... Sorry about that, my bad. (and I've corrected my above cods)

This is because I originally had it grouped in pairs and changed my mind (and forgot to change other bits)
Good spotting though XD
I made the V2, you move with arrow keys and turn the card with spacebar.
I have a little problem when the program asks me if i want to continue.

the first time i write 'y' and the game restarts.
the second time however, in the place where i'm supposed to write 'y' or 'n', there is already a 'y' and sometimes a bounch of spaces too! i think that this happens because i don't flush the memory/buffer/stream or whatever.

can someone help me with this problem?
everything else seems to work fine.

this is the code, it's a bit messy i know... not very easy to follow.

 ``123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254`` ``````#include #include #include #include using namespace std; //Global variables int coordX, coordY; int selector[4][4] = {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; class CCard{ int value; bool faceUp; public: CCard(){ // Constructor faceUp = false; } void SetValue(int v){ value = v; } void TurnCard(){ faceUp = !faceUp; } int GetValue(){ return value; } bool GetFaceUp(){ return faceUp; } } deck[4][4]; void SetCards(){ // Set the cards in random order int pairs[16] = {1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8}; int a, b, temp; for(int i=0;i<30;i++){ // Swap 30 times a = rand()%16; b = rand()%16; temp = pairs[a]; pairs[a] = pairs[b]; pairs[b] = temp; } for(int y=0;y<4;y++){ for(int x=0;x<4;x++){ deck[x][y].SetValue(pairs[x +(y * 4)]); // Puts swapped cards in the deck } } } void ShowBoard(){ // Print/update the board on screen system("cls"); cout << " 1 2 3 4" << endl << endl; for(int y=0;y<4;y++){ cout << y+1 << " "; for(int x=0;x<4;x++){ if(deck[x][y].GetFaceUp() == true){ // If the card is facing up show it's value cout << deck[x][y].GetValue() << " "; } else{ // If is facing down show an ASCII character (hidden card) cout << (char)177 << " "; } } cout << endl; cout << " "; for(int x=0;x<4;x++){ if(selector[x][y] == 1){ // If selector is at x,y show arrow cout << (char)94 << " "; } else{ // Else show nothing (spaces) cout << " "; } } cout << endl; } cout << endl; } void GetInput(){ // Gets the user input while(1){ while(1){ if(GetAsyncKeyState(VK_UP) & 1){ // UP if((coordY-1) < 0){ // If out of boundaries coordY = 3; } else{ coordY--; } break; } if(GetAsyncKeyState(VK_DOWN) & 1){ // DOWN if((coordY+1) > 3){ // If out of boundaries coordY = 0; } else{ coordY++; } break; } if(GetAsyncKeyState(VK_LEFT) & 1){ // LEFT if((coordX-1) < 0){ // If out of boundaries coordX = 3; } else{ coordX--; } break; } if(GetAsyncKeyState(VK_RIGHT) & 1){ // RIGHT if((coordX+1) > 3){ // If out of boundaries coordX = 0; } else{ coordX++; } break; } if((GetAsyncKeyState(VK_SPACE) & 1)){ // SPACE = turns card pointed by selector if(deck[coordX][coordY].GetFaceUp() == true){ // If player selects an already-matched card cout << "You can't select this card again!" << endl << endl; continue; } else{ deck[coordX][coordY].TurnCard(); return; } } } // Everytime the user presses a key the following is executed for(int y=0;y<4;y++){ for(int x=0;x<4;x++){ selector[x][y] = 0; // Clear selector array } } selector[coordX][coordY] = 1; // Sets selector array at right position ShowBoard(); // Updates board } } int main(){ int holderX, holderY, remaining = 16, tries = 0; char reply; bool secondTurn = false; srand(time(NULL)); while(1){ // Infinite loop SetCards(); do{ // Loop until player matched all cards ShowBoard(); GetInput(); if(secondTurn == true){ // If player turned the second card we have to look if they match secondTurn = false; tries++; if((coordX == holderX) && (coordY == holderY)){ // The user selected the same card twice! tries--; cout << "You can't select the same card twice!" << endl; continue; } if(deck[coordX][coordY].GetValue() == deck[holderX][holderY].GetValue()){ // If cards match ShowBoard(); cout << "You matched 2 cards!" << endl; remaining -= 2; } else{ // If cards are different ShowBoard(); cout << "The cards are different!" << endl; deck[coordX][coordY].TurnCard(); // Turn cards again deck[holderX][holderY].TurnCard(); } while(1){ // This is a pause, the user can read the text until he presses an arrow key if(remaining == 0){ // Or if there aren't cards left break; } if(GetAsyncKeyState(VK_UP) & 1){ // UP if((coordY-1) < 0){ // If out of boundaries coordY = 3; } else{ coordY--; } break; } if(GetAsyncKeyState(VK_DOWN) & 1){ // DOWN if((coordY+1) > 3){ // If out of boundaries coordY = 0; } else{ coordY++; } break; } if(GetAsyncKeyState(VK_LEFT) & 1){ // LEFT if((coordX-1) < 0){ // If out of boundaries coordX = 3; } else{ coordX--; } break; } if(GetAsyncKeyState(VK_RIGHT) & 1){ // RIGHT if((coordX+1) > 3){ // If out of boundaries coordX = 0; } else{ coordX++; } break; } } for(int y=0;y<4;y++){ for(int x=0;x<4;x++){ selector[x][y] = 0; // Clear selector array } } selector[coordX][coordY] = 1; // Sets selector array ShowBoard(); } else{ // If this is the first card turned, we store the x,y coords for later use holderX = coordX; holderY = coordY; secondTurn = true; } }while(remaining > 0); cout << "Congratulation! you matched all the cards in " << tries << " tries!" << endl; do{ // Asks the user if he wants to play again cout << "Do you want to play again? (y/n): "; cin >> reply; if(reply == 'n' || reply == 'N'){ return 0; } else if(reply != 'n' && reply != 'N' && reply != 'y' && reply != 'Y'){ cout << "Invalid character, try again." << endl << endl; } }while(reply != 'y' && reply != 'Y'); // Reset varables if player wants to play again remaining = 16; tries = 0; coordX = 0; coordY = 0; for(int y=0;y<4;y++){ for(int x=0;x<4;x++){ deck[x][y].TurnCard(); // Turns all the cards face down selector[x][y] = 0; // Clear selector array } } selector[0][0] = 1; // Sets selector array } } ``````
Topic archived. No new replies allowed.