#uno game help

85 messages · Page 1 of 1 (latest)

craggy mango
#

cpp```
void initializeDeck() {
string colors[] = {"Red", "Green", "Blue", "Yellow"};
string values[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Draw Two", "Skip", "Reverse"};
for (const string &color : colors) {
for (const string &value : values) {
deck.push_back({color, value});
if (value != "0") {
deck.push_back({color, value});
}
}
}
for (int i = 0; i < 4; i++) {
deck.push_back({"Wild", "Wild"});
deck.push_back({"Wild", "Draw Four"});
}
random_shuffle(deck.begin(), deck.end());
}

hey, i have a class assignment where i have to code a game and i chose uno, this part of the code keeps giving me errors, can someone please help me out with this?
undone rose
#

I'll assume you also put using namespace std; somewhere as well

craggy mango
#

this is whats before that section

#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <string>
#include <algorithm>

using namespace std;

struct Card {
    string color;
    string value;
};

class UNOGame {
private:
    vector<Card> deck;
    vector<Card> player1Hand, player2Hand, player3Hand, player4Hand;
    Card topCard;
    int currentPlayer;
    int totalPlayers;
    bool reverseOrder;
lunar mothBOT
#

@craggy mango has reached level 1. GG!

undone rose
#

It looks like void initializeDeck needs to be made a method of UNOGame

#

the general structure of a class that is declared in source code is as follows

#include <iostream>

class Dog {
public:
Dog(const std::string &name) { // The constructor. Sets member variables to arguments passed to the constructor function, and performs any other necessary functions
  setName(name);
} 

void Bark() {
  std::cout << "Bark!\n";
}

private:
void setName(const std::string &name) {
  this->name = name;
};
#

You're going to want to create a public member void initializeDeck() inside of the UNOGame class that way it has access to the private members.

craggy mango
#

sorry to bother, but how do I do that

undone rose
#

No worries!

#

It would look like this:

class UNOGame {
public:
void initializeDeck() {
  // stuff here
}

private:
 // etc.
};```
craggy mango
#

so like this?

class UNOGame {
public:
    void initializeDeck() {
        string colors[] = {"Red", "Green", "Blue", "Yellow"};
        string values[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Draw Two", "Skip", "Reverse"};
        for (const string &color : colors) {
            for (const string &value : values) {
                deck.push_back({color, value});
                if (value != "0") {
                    deck.push_back({color, value});
                }
            }
        }
        for (int i = 0; i < 4; i++) {
            deck.push_back({"Wild", "Wild"});
            deck.push_back({"Wild", "Draw Four"});
        }
        random_shuffle(deck.begin(), deck.end());
    }
private:
    vector<Card> deck;
    vector<Card> player1Hand, player2Hand, player3Hand, player4Hand;
    Card topCard;
    int currentPlayer;
    int totalPlayers;
    bool reverseOrder;
    
    void dealCards() {
        while (!deck.empty()) {
            player1Hand.push_back(deck.back());
            deck.pop_back();
            player2Hand.push_back(deck.back());
            deck.pop_back();
            if (totalPlayers > 2) {
                player3Hand.push_back(deck.back());
                deck.pop_back();
            }
            if (totalPlayers > 3) {
                player4Hand.push_back(deck.back());
                deck.pop_back();
            }
        }
        topCard = deck.back();
        deck.pop_back();
    }
undone rose
#

Yes this looks good. Though you might wanna make dealCards() public, unless you only intend for it to be called by other methods in the class

craggy mango
#

I ran this code and it still gave me the errors though

undone rose
#

You've created your class but you still need a main function. Otherwise you've created a definition for a class without any instructions on what to do with it.

craggy mango
#

I have more code with this so it should be okay, i'm not sure why it's still having problems

undone rose
#

What are your errors?

craggy mango
#

main.cpp:20:34: warning: range-based for loop is a C++11 extension [-Wc++11-extensions]
for (const string &color : colors) {
^
main.cpp:21:38: warning: range-based for loop is a C++11 extension [-Wc++11-extensions]
for (const string &value : values) {
^
main.cpp:22:32: error: expected expression
deck.push_back({color, value});
^
main.cpp:24:36: error: expected expression
deck.push_back({color, value});
^
main.cpp:29:28: error: expected expression
deck.push_back({"Wild", "Wild"});
^
main.cpp:30:28: error: expected expression
deck.push_back({"Wild", "Draw Four"});
^
main.cpp:221:14: warning: 'auto' type specifier is a C++11 extension [-Wc++11-extensions]
for (auto& card : hand) {
^
main.cpp:221:25: warning: range-based for loop is a C++11 extension [-Wc++11-extensions]
for (auto& card : hand) {

undone rose
#

What compiler are you using? I don't have these errors.

#

Your compiler seems to be quite old

craggy mango
#

i'm using netbeans which i think is using java

#

that's what i'm required to use unfortunately

undone rose
#

I think what's happening is your compiler doesn't support initializer-list initialization of structs

#

try instead doing deck.push_back(Card(val1, val2))

#

with val1 and val2 being what is needed respectively for each line

craggy mango
#

do i just add it in like this

class UNOGame {
public:
    void initializeDeck() {
        string colors[] = {"Red", "Green", "Blue", "Yellow"};
        string values[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Draw Two", "Skip", "Reverse"};
        for (const string &color : colors) {
            for (const string &value : values) {
                deck.push_back(Card(val1, val2));
                deck.push_back({color, value});
                if (value != "0") {
                    deck.push_back({color, value});
                }
            }
        }
        for (int i = 0; i < 4; i++) {
            deck.push_back({"Wild", "Wild"});
            deck.push_back({"Wild", "Draw Four"});
        }
        random_shuffle(deck.begin(), deck.end());
    }
lunar mothBOT
#

@craggy mango has reached level 2. GG!

undone rose
#

No. the important part is replacing you're initializer lists ({color, value}) with a struct initializtion like this: Card(color, value)

#

So:

class UNOGame {
public:
    void initializeDeck() {
        string colors[] = {"Red", "Green", "Blue", "Yellow"};
        string values[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Draw Two", "Skip", "Reverse"};
        for (const string &color : colors) {
            for (const string &value : values) {
                deck.push_back(Card(color, value));
                deck.push_back(Card(color, value));
                if (value != "0") {
                    deck.push_back(Card(color, value));
                }
            }
        }
        for (int i = 0; i < 4; i++) {
            deck.push_back(Card("Wild", "Wild"));
            deck.push_back(Card("Wild", "Draw Four"));
        }
        random_shuffle(deck.begin(), deck.end());
    }```
craggy mango
#

this is what it's giving me now

undone rose
#

?

craggy mango
undone rose
#

can you paste your entire source code file

lunar mothBOT
#

@undone rose has reached level 4. GG!

craggy mango
#

yes

undone rose
#

the issue is (firstly that your compiler is archaic) and also that there isn't a constructor for the Card struct

#

becuase there isn't a constructor for the struct, when you call the initializer it just default initializes the values if possible

#

In C++, a struct is identical to a class except for the fact that a struct's members are public by default

#

generally you would be allowed to initialize like Card(name, color) but since your compiler is old it seems it won't let you without defining a constructor I'm wrong, you'd use Card{name, color}. this is because parenthesis does imply calling a constructor, which wouldn't ever work unless one is explicityl defined (or the default constructor is called withotu arguments)

#

instead try

struct Card {
  string color;
  string value;
    
   // Constructor to initialize color and value
   Card(const string& c, const string& v) : color(c), value(v) {}
};
#

You might be able to get around this by using curly braces like Card{color, value} as opposed to Card(color, value) but i don't really know if it'll work

craggy mango
#

and when I tried the curly braces, it made it worse

silent igloo
#

Hi. Usually when I add a struct object to a vector, I define a temporary local object and push that back. Like so:

Card newcard;
newcard.color = color;
newcard.value = value;
deck.push_back(newcard);

I'm not sure if this method is good for memory management or not but it works.

lunar mothBOT
#

@silent igloo has reached level 6. GG!

silent igloo
#

Also if you are still getting errors like "warning: range-based for loop is a C++11 extension" you might want to adjust whatever IDE you're using to use c++11 as the language standard. I don't mean get another compiler. I mean change the language standard in the IDE.

This command should be run when calling the compiler: "-std=c++11"

undone rose
#

They're using netbeans, they might not even be able to alter the arguments to the built in compiler

#

really frustrating becasue range based for loops are really great

silent igloo
#

You can set it in netbeans. I just checked. You go to Properties > Build > C++ Compiler and in the "Additional Options" field you place this "-std=c++11".

undone rose
#

That's cool

#

@craggy mango

craggy mango
silent igloo
#

Same errors?

#

You didn't change the "Card(color,value)" into something else. What you have won't work.

#

Unless if you have a constructor.

#

I think'

#

Could you show your code again please?

craggy mango
#

I thought I did, maybe I undid it. I'll send the code

silent igloo
#

In the struct Card, you have no constructor. Like what Kevin Goldstein said.
Maybe you should try going without the Card() constructor and do this:

Card newcard;
newcard.color = color;
newcard.value = value;
deck.push_back(newcard);

#

`
Instead of Card(color,value)

#

Whenever you have () after a name in c++ it treats that as a function and tries to call it. No such function exists in your Card struct.

craggy mango
#

so where in the code do I add that part?

silent igloo
#

How long have you been using c++?

craggy mango
#

not long, just this semeter for my class

silent igloo
#

Place this:

Card newcard;
newcard.color = color;
newcard.value = value;
deck.push_back(newcard);

With the necessary adjustments wherever you need to add to a vector of Card objects. For example: Where you initialize the deck you could place the code inside of your two for loops.


    void initializeDeck() {
        string colors[] = {"Red", "Green", "Blue", "Yellow"};
        string values[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "Draw Two", "Skip", "Reverse"};
        for (const string &color : colors) {
            for (const string &value : values) {
                Card newcard;
                newcard.color=color;
                newcard.value=value;
                
                deck.push_back(newcard));
                deck.push_back(newcard));
                if (value != "0") {
                    deck.push_back(newcard));
                }
            }
        }
        for (int i = 0; i < 4; i++) {
            Card newcard;
            newcard.color = "Wild";
            newcard.value = "Wild";
            deck.push_back(newcard);
            newcard.value = "Draw Four";
            deck.push_back(newcard);
        }
        random_shuffle(deck.begin(), deck.end());
    }

craggy mango
#

this is much better, these are the only errors now
"/Applications/Xcode.app/Contents/Developer/usr/bin/make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf
"/Applications/Xcode.app/Contents/Developer/usr/bin/make" -f nbproject/Makefile-Debug.mk dist/Debug/GNU-MacOSX/uno_project_2
mkdir -p build/Debug/GNU-MacOSX
rm -f "build/Debug/GNU-MacOSX/main.o.d"
g++ -c -g -std=c++11 -MMD -MP -MF "build/Debug/GNU-MacOSX/main.o.d" -o build/Debug/GNU-MacOSX/main.o main.cpp
main.cpp:26:40: error: extraneous ')' before ';'
deck.push_back(newcard));
^
main.cpp:27:40: error: extraneous ')' before ';'
deck.push_back(newcard));
^
main.cpp:29:44: error: extraneous ')' before ';'
deck.push_back(newcard));
^
3 errors generated.
make[2]: *** [build/Debug/GNU-MacOSX/main.o] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2

silent igloo
#

Ok. So I did a typo. Just remove the extra ")" from the end of deck.push_back(newcard));

craggy mango
#

okay perfect now it runs but now it gives each player 80 cards instead of just 7, I dont know if that was from my previous code, or if something changed while I was trying to fix the error

lunar mothBOT
#

@craggy mango has reached level 3. GG!

silent igloo
#

I didn't think the code looked right. Let me look at it again for a minute.

craggy mango
#

okay take your time

silent igloo
#

I don't understand why you are pushing back three same cards into the deck. Maybe I'm just forgetting how uno is played. Nevermind. I'll look at the player hand code now.

#

You have dealCards() continue to deal till the deck is empty. The deck is more than what the players should get. There has to be deck left for the players to draw from during the game. To fix this problem change the condition from "while(!deck.empty())" to a for loop.

int dealsize=?; //I forget how many cards should be dealed.
for(int a = 0; a < dealsize; a++)
{
   player1Hand.push_back(deck.back());
   deck.pop_back();
   player2Hand.push_back(deck.back());
   deck.pop_back();
   if (totalPlayers > 2) 
   {
        player3Hand.push_back(deck.back());
        deck.pop_back();
   }
   if (totalPlayers > 3) 
   {
                                  player4Hand.push_back(deck.back());
                deck.pop_back();
            } 
}
craggy mango
#

okay that worked and it's only dealing 7 cards per player, this is what the run is showing

#

nevermind i can't copy the output, but there's one more problem, it doesn't say what the top card is

silent igloo
#

What do you have for outputting the top card to the console?

craggy mango
silent igloo
#

I don't see anything outputting the top card to the console. I also see that your player cards will have to update and consequently be output to the console. If you don't want the player cards and the top card to be output after the old values in the console you can clear the console and output to it in a loop like so:

Something kinda like this:

    void playTurn() {

        bool validMove = false;
        while (!validMove) 
    {
    
    system("cls");
    cout << "======================================" << endl;
        cout << "Player " << currentPlayer + 1 << "'s Turn!" << endl;
        displayHand(currentPlayer);
        cout << "Top card: ";
        displayCard(topCard);
        cout << endl;

        
            cout << "Choose a card to play (1-" << getPlayerHandSize(currentPlayer) << ") or 0 to draw: ";
            int choice;
            cin >> choice;

            if (choice == 0) {
                drawCard(currentPlayer);
                return;
            } else if (choice > 0 && choice <= getPlayerHandSize(currentPlayer)) {
                Card chosenCard = getPlayerCard(currentPlayer, choice - 1);
                if (isValidMove(chosenCard)) {
                    validMove = true;
                    topCard = chosenCard;
                    removeCardFromHand(currentPlayer, choice - 1);
                    applySpecialCardEffect(chosenCard);
                } else {
                    cout << "Invalid move. Try again." << endl;
                }
            } else {
                cout << "Invalid choice. Try again." << endl;
            }
        }

        if (getPlayerHandSize(currentPlayer) == 0) {
            cout << "Player " << currentPlayer + 1 << " has UNO!" << endl;
        }
    }
craggy mango
#

still the same problem

silent igloo
#

Did you add something to output the topcard value?

silent igloo
#

@craggy mango

silent igloo
#

Oh. Nevermind. I can see now where you output the value. I just had a hard time finding it in your code.