这是使用抽象类数组(C++)的正确方法吗?

发布于 2024-12-20 14:28:36 字数 3475 浏览 3 评论 0原文

忽略我使用原始指针/数组的事实。

我正在用 C++ 制作一个纸牌游戏,它有一个由其他类扩展的 Player 抽象类。我需要创建一个指向这些派生类的指针数组。这可行,但是有更好的方法吗?

class Player{
   public:
        Player();
        Player(const Player&);
        Player & operator=(const Player &);

        virtual void sort() = 0;
        virtual Card play(Pile*) = 0;

        void confirmPlay();

        void giveHand(Hand&);
        void giveCard(Card);
        bool hasCards();

        void won();
        void resetWins();
        int getWins();

        virtual ~Player();
    protected:
        int cardsLeft;
        Hand hand;
        int cardPlayed;
        int wins;
    private:
};

class DumbPlayer : public Player
{
    public:
        DumbPlayer();
        Card play(Pile*);
        void sort();
        virtual ~DumbPlayer();
        DumbPlayer & operator=(const DumbPlayer &);
        DumbPlayer(const DumbPlayer&);
    protected:
    private:
};

class Game{
    public:
        Game(int,  Player**&);
        void playX(int);
        void playOne();
        virtual ~Game();
    protected:
    private:
        bool done();
        Game & operator=(const Game &);
        Game(const Game&);
        Pile * piles;
        Deck deck;
        int playerCount;
        Player ** players;
};

//implementation not shown to save space, tell me if you would like to see anything.
//I think that all of the other class/function names should be good enough to not show.

Game::Game(const int pplayerCount, Player**& pplayers) : 
                                   piles(new Pile[4]), 
                                   playerCount(pplayerCount), 
                                   deck(), 
                                   players(new Player*[playerCount]){
    for(int i = 0; i < 4; i++){
        piles[i].setSuit(i);
    }

    for(int i = 0; i < playerCount; i++){
        players[i] = pplayers[i];
    }
}

void Game::playOne(){
    deck.shuffle();  //shuffle deck
    for(int i = 0; i < 4; i++){
        piles[i].reset();  //reset piles
    }
    Hand hands[playerCount];  //create hands
    Hand leftovers;
    deck.dealAll(playerCount, hands, leftovers); //deal the deck
    int cardsLeftover = leftovers.getSize();     //there are leftover cards, 
                                                 //52/3 has a remainder
    for(int playerIdx = 0; playerIdx < playerCount; playerIdx++){
        (*players[playerIdx]).giveHand(hands[playerIdx]); //this is what 
                                                          //i am unsure about.
        (*players[playerIdx]).sort();
    }
    int winner = -1;
    while(!done()){
        for(int playerIdx = 0; playerIdx < playerCount; playerIdx++){
            Card play = (*players[playerIdx]).play(piles);
            if(piles[play.getSuit()].canPut(play)){
                (*players[playerIdx]).confirmPlay();
                piles[play.getSuit()].put(play);
                if(!(*players[playerIdx]).hasCards()){
                    winner = playerIdx;
                    break;
                }
            } else {
                if(cardsLeftover > 0){
                    (*players[playerIdx]).giveCard(leftovers.popCard(--cardsLeftover));
                }
            }
        }
        if(winner != -1){
            (*players[winner]).won();
            break;
        }
    }
}

我知道(对于这个网站)有大量代码...我不确定游戏构造函数/类以及包括 (*players[i]).x() 的行

Ignore the fact that I using raw pointers/arrays.

I am making a card game in C++ that has a Player abstract class that is extended by other classes. I need to make an array of pointers to these derived classes. This works, but is there a better way?

class Player{
   public:
        Player();
        Player(const Player&);
        Player & operator=(const Player &);

        virtual void sort() = 0;
        virtual Card play(Pile*) = 0;

        void confirmPlay();

        void giveHand(Hand&);
        void giveCard(Card);
        bool hasCards();

        void won();
        void resetWins();
        int getWins();

        virtual ~Player();
    protected:
        int cardsLeft;
        Hand hand;
        int cardPlayed;
        int wins;
    private:
};

class DumbPlayer : public Player
{
    public:
        DumbPlayer();
        Card play(Pile*);
        void sort();
        virtual ~DumbPlayer();
        DumbPlayer & operator=(const DumbPlayer &);
        DumbPlayer(const DumbPlayer&);
    protected:
    private:
};

class Game{
    public:
        Game(int,  Player**&);
        void playX(int);
        void playOne();
        virtual ~Game();
    protected:
    private:
        bool done();
        Game & operator=(const Game &);
        Game(const Game&);
        Pile * piles;
        Deck deck;
        int playerCount;
        Player ** players;
};

//implementation not shown to save space, tell me if you would like to see anything.
//I think that all of the other class/function names should be good enough to not show.

Game::Game(const int pplayerCount, Player**& pplayers) : 
                                   piles(new Pile[4]), 
                                   playerCount(pplayerCount), 
                                   deck(), 
                                   players(new Player*[playerCount]){
    for(int i = 0; i < 4; i++){
        piles[i].setSuit(i);
    }

    for(int i = 0; i < playerCount; i++){
        players[i] = pplayers[i];
    }
}

void Game::playOne(){
    deck.shuffle();  //shuffle deck
    for(int i = 0; i < 4; i++){
        piles[i].reset();  //reset piles
    }
    Hand hands[playerCount];  //create hands
    Hand leftovers;
    deck.dealAll(playerCount, hands, leftovers); //deal the deck
    int cardsLeftover = leftovers.getSize();     //there are leftover cards, 
                                                 //52/3 has a remainder
    for(int playerIdx = 0; playerIdx < playerCount; playerIdx++){
        (*players[playerIdx]).giveHand(hands[playerIdx]); //this is what 
                                                          //i am unsure about.
        (*players[playerIdx]).sort();
    }
    int winner = -1;
    while(!done()){
        for(int playerIdx = 0; playerIdx < playerCount; playerIdx++){
            Card play = (*players[playerIdx]).play(piles);
            if(piles[play.getSuit()].canPut(play)){
                (*players[playerIdx]).confirmPlay();
                piles[play.getSuit()].put(play);
                if(!(*players[playerIdx]).hasCards()){
                    winner = playerIdx;
                    break;
                }
            } else {
                if(cardsLeftover > 0){
                    (*players[playerIdx]).giveCard(leftovers.popCard(--cardsLeftover));
                }
            }
        }
        if(winner != -1){
            (*players[winner]).won();
            break;
        }
    }
}

I know that it is a ton of code (for this site)... i am unsure about the game constructor/class and the lines including (*players[i]).x()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

深居我梦 2024-12-27 14:28:36

如今,指针数组被拼写为:

std::vector<boost::shared_ptr<Player> > players;

这完全符合资源获取即初始化 (RAII) 习惯用法 确保在遇到异常和不可预见的代码路径时正确调用析构函数并回收内存。

Nowadays, an array of pointers is spelled:

std::vector<boost::shared_ptr<Player> > players;

This takes full of the Resource Acquisition Is Initialization (RAII) idiom to ensure destructors are called properly and memory is reclaimed in the face of exceptions and unforeseen code paths.

段念尘 2024-12-27 14:28:36

使用 std::vector、列表、地图等。

Use std::vector, list, map etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文