UNO游戏卡功能

时间:2019-04-28 20:57:31

标签: c++

我在构建游戏的最后一块(卡片的功能)时遇到麻烦。如果您不熟悉UNO的规则,请https://www.unorules.com/

我的问题是我不确定如何构建“反向”和“跳过”功能。我有一个“玩家”对象向量,通过迭代来控制谁转弯。

在我的脑海中,这似乎很简单。跳过只会将索引增加一个,跳过先前的播放器对象,而反向将减少索引而不是增加索引,因此会向后移动。

我似乎无法将此想法应用到代码中。

这是我的第一个大型项目,我对所有代码感到有些不知所措。

我已经建立了一个跳过功能,但是实际上没有放任何东西,因为我不知道从哪里开始。我觉得自己在每个回合中迭代的方式效率低下,而且杂乱无章,因此我可能需要一些帮助来进行重构。

编辑: 这是我认为可以接受的反向代码

void Game::round(Player& player, Deck& deck)
{
    // 1 round has x turns

    for (int i = 0; i < amountOfPlayers; i++)
    {
        if (reverse = true) //reverse is not defined in below code
        {
            for (int i; i < amountOfPlayers; i--)
            {
                if (i < 0)
                {
                    i = playerVector.size()-1;
                }
                turns(player, deck, i);
            }
        }

        turns(player, deck, i);
    }
}

这是我的游戏代码

#pragma once
#include "Player.h"
#include "DevTest.h"

class Player;
class DevTest;
class Deck;
class Global;
#include <string>
#include <vector>


class Game
{
private:
    int amountOfPlayers;
    std::vector<Player*> playerVector;
    std::vector<Card> inPlay; //cards in play

public:
    Game();
    void createPlayerVector(Deck& deck);
    void menu(Deck &deck, Player &player, Game game, DevTest devtest);
    void round(Player& player, Deck& deck);
    void turns(Player &player, Deck &deck, int i);
    bool win(Player& player);
    void playGame(Player& player, Game game, Deck& deck);
    bool chooseCard(Player& player, Deck deck, int position);

    void drawTwo(Deck &deck, int drawAmount, int playerIndex);
    void drawWild(Deck& deck, int cardNum, int playerIndex, int toChoose);
    void skip(Player player, Deck& deck, int i);
    ~Game();
};



/*

#include "Game.h"
class DevTest;

Game::Game()
{
    Deck deck;
}

void Game::createPlayerVector(Deck &deck)
{

    std::string userName;
    std::cout << "Please enter the amount of players: ";
    std::cin >> amountOfPlayers;

    if (amountOfPlayers < 2 || amountOfPlayers>10)
    {
        if (amountOfPlayers < 2)
        {
            std::cout << "Sorry! Not enough players." << std::endl;
        }

        if (amountOfPlayers > 10)
        {
            std::cout << "Sorry! Too many players." << std::endl;
        }
    }

    else
    {
        std::cout << "Please enter the names of each player." << std::endl;

        for (int i = 0; i < amountOfPlayers; i++)
        {
            Player* player = new Player;
            playerVector.push_back(player);

            std::cout << "Player " << i+1 << ": ";

            std::cin.ignore();

            std::getline(std::cin, userName);

            this->playerVector[i]->setUserName(userName);
            this->playerVector[i]->setHand(deck, *player);
            player->printHand(deck);
        }
    }

    system("PAUSE");
    system("CLS");
return;
}

void Game::menu(Deck& deck, Player& player, Game game, DevTest devtest)
{
    int choice;

    std::cout << "UNO" << std::endl;
    std::cout << "1. Play Game" << std::endl;
    std::cout << "2. Read Rules" << std::endl;
    std::cout << "3. Developer Testing" << std::endl;
    std::cout << "4. Quit" << std::endl;

    do
    {
        std::cin >> choice;

        switch (choice)
        {
        case 1:
            std::cout << "Play Game" << std::endl;
            break;

        case 2:
            std::cout << "Read Rules" << std::endl;
            break;

        case 3:
            std::cout << "Developer Testing" << std::endl;
            devtest.testMenu(deck, player, game);
            break;

        case 4:
            exit(0);
            break;

        default:
            std::cout << "Invalid choice. Please choose again." << std::endl;
        }
        //clear screen
    } while (choice < 1 || choice >4);
}

void Game::round(Player& player, Deck& deck)
{
    // 1 round has x turns

    for (int i = 0; i < amountOfPlayers; i++)
    {
        turns(player, deck, i);
    }
}

void Game::turns(Player& player, Deck& deck, int playerIndex)
{   
    int option;
    bool proceed = false;

    do
    {

        std::cout << "It is currently " << playerVector[playerIndex]->getUserName() << "'s" << " turn." << std::endl << std::endl;
        std::cout << "The card you must match is: " << std::endl;

        deck.toString(inPlay.front().color);
        std::cout << " " << inPlay.front().value << std::endl << std::endl;

        std::cout << "[1] Draw Card " << std::endl;
        std::cout << "[2] Play Card" << std::endl;
        std::cout << "Pick an option. " << std::endl;
        std::cin >> option;

        if (option == 1)
        {
            //draw card
            deck.dealCard(*playerVector[playerIndex]);
            std::cout << "You have taken a card." << std::endl;
        }

        if (option == 2)
        {
            //use card, transfer hand to bottom of deck
            proceed = chooseCard(player, deck, playerIndex);
        }

        if (win(player) == true)
        {
            //end game, celebrate
            return;
        }

        system("PAUSE");
        system("CLS");

    } while (proceed == false);
}

bool Game::win(Player& player)
{

    if (player.isEmpty(player) == true)
    {
        //you win
        //std::cout << "Congratulations, " << player.getUserName() << " you win!" << std::endl;
        //return true;
    }

    else
    {
        //nobody has won yet
        return false;
    }

    return false;
}

void Game::playGame(Player& player, Game game, Deck& deck)
{
//cout intro();
    deck.createDeck();
    deck.shuffle();

    createPlayerVector(deck);

    //start off game by placing a single card down
    inPlay.push_back(deck.getCard());
    deck.pop();

    //remove choose card from hand
    //pop off deck to start game (starting card)
    while (win(player) == false)
    {
        round(player, deck);
    }

}

bool Game::chooseCard(Player& player, Deck deck, int playerIndex) //delete from hand, populate inPlay
{
    int toChoose;
    bool validate = false;
    std::cout << "Which card would you like to choose? Press 0 to draw a card." << std::endl;

    while (validate == false)
    {
        this->playerVector[playerIndex]->printHand(deck);
        std::cin >> toChoose;

        if (toChoose == 0)
        {
            //fix
            deck.dealCard(*playerVector[playerIndex]); //fix
            return false;
        }

        if (playerVector[playerIndex]->getHandCard(player, toChoose).value == 13 || playerVector[playerIndex]->getHandCard(player, toChoose).value == 14)
        {
            validate = true;
            int cardNum = playerVector[playerIndex]->getHandCard(player, toChoose).value;
            drawWild(deck, cardNum, playerIndex, toChoose);
        }




        else if (playerVector[playerIndex]->getHandCard(player, toChoose).value != inPlay.front().value && playerVector[playerIndex]->getHandCard(player, toChoose).color != inPlay.front().color)
        {
            //card doesn't match
            validate = false;
            std::cout << "You are not allowed to play this card!" << std::endl;
            return false;
        }
        validate = true;
    }



    if (validate == true)
    {
        if (playerVector[playerIndex]->getHandCard(player, toChoose).value == 10 || playerVector[playerIndex]->getHandCard(player, toChoose).value == 14)

        {
            int drawAmount = 0;

            //draw two
            if (playerVector[playerIndex]->getHandCard(player, toChoose).value == 10)
            {
                int drawAmount = 2;
                drawTwo(deck, drawAmount, playerIndex + 1);
            }
        }

        if(playerVector[playerIndex]->getHandCard(player, toChoose).value == 11 || playerVector[playerIndex]->getHandCard(player, toChoose).value == 12)
        {
            skip(player, deck, playerIndex);
        }

        inPlay.insert(inPlay.begin(), playerVector[playerIndex]->getHandCard(player, toChoose));
        playerVector[playerIndex]->deleteHand(toChoose);
        return true;
    }

    return true;
}


void Game::drawTwo(Deck &deck, int drawAmount, int playerIndex)
{
    if (playerIndex>playerVector.size()-1)
    {
        playerIndex = 0; //circular code
    }

    for (int j = 0; j < drawAmount; j++)
    {
        deck.dealCard(*playerVector[playerIndex]);
    }
}

void Game::drawWild(Deck& deck, int cardNum, int playerIndex, int toChoose) //fix
{
    if (cardNum == 13)
    {
        int choice;
        //wild
        std::cout << "What color would you like to choose?" << std::endl;
        std::cout << "[1] BLUE" << std::endl;
        std::cout << "[2] GREEN" << std::endl;
        std::cout << "[3] RED" << std::endl;
        std::cout << "[4] YELLOW" << std::endl;


        std::cin >> choice;


        //inPlay.front().color = static_cast<Card::Color>(choice - 1);
        //
    }

    if (cardNum == 14)
    {
        //draw 4
        //lets u pick a color AND next person draws 4
    }
}

void Game::skip(Player player, Deck& deck, int i)
{
    //turns(player, deck, i + 1);
}


Game::~Game()
{

}

玩家定义为

#pragma once

#include <vector>
#include <iostream>
#include "Deck.h"
#include "Card.h"

class Deck;
class Player
{
private:
    int length;
    std::string username; //can indicate whos turn / wins
    static const int HANDSIZE = 7;
    std::vector<Card> hand;

public:
    Player();
    void pushHand(Card deck); 
    void deleteHand(int position);
    void printHand(Deck deck);
    void setHand(Deck &deck, Player& player); 
    Card getHandCard(Player& player, int position);
    int getHANDSIZE();
    std::string getUserName();
    void setUserName(std::string name);
    bool isEmpty(Player& player); //hand is empty

    ~Player();
};


#include "Player.h"
class Player;

Player::Player()
{
    this->length = 0;
}

void Player::pushHand(Card deck)
{
    //push 1 deck object into hand

    this->hand.push_back(deck);
    length++;
}

void Player::deleteHand(int position)
{
    for (int i = 0; i < hand.size(); i++)
    {
        if (i == position-1)
        {
            hand.erase(hand.begin()+i);
        }
    }
}

void Player::printHand(Deck deck)
{
    for (int i = 0; i < hand.size(); i++)
    {
        std::cout << i+1 << ". ";
        std::cout << "Color: ";
        deck.toString(hand[i].color);
        std::cout << " | " << "Value: " << hand[i].value << std::endl;
    }
}

void Player::setHand(Deck &deck, Player& player) //used only for setting hand at beginning of game
{
    for (int i = 0; i < HANDSIZE; i++)
    {
        deck.dealCard(player);
    }
}

Card Player::getHandCard(Player& player, int position)
{
    return this->hand[position - 1];
    //return player.hand[position - 1];
}

int Player::getHANDSIZE()
{
    return HANDSIZE;
}

std::string Player::getUserName()
{
    return username;
}

void Player::setUserName(std::string name)
{
    username = name;
}

bool Player::isEmpty(Player& player)
{
    if (length == 0)
    {
        return true;
    }

    return false;
}


Player::~Player()
{
    //delete hand;
}

甲板是

  #pragma once
    #include "Card.h"
    #include "Player.h"
    #include <iostream>
    #include <ctime>

    class Player;
    class Deck 
    {
    private:

        static const int MAXSIZE = 108; //108 cards in UNO
        int length;

    public:
        Deck();

        void createDeck();
        void shuffle();
        void printDeck();
        //void push();
        void pop();
        int top();

        bool isEmpty();
        bool isFull();
        void toString(Card::Color color); //converts enum to string.
        void dealCard(Player &player);
        Card getCard();
        Card* deck;

        ~Deck();
    };


#include "Deck.h"



Deck::Deck()
{
    deck = new Card[MAXSIZE];
    length = 0;
}

void Deck::createDeck()
{
    //UNO has 4 zero cards
    int num = 0;

    for (int col = 0; col <= 3; col++)
    {
        deck[length].value = num; //sets each to zero
        deck[length].color = static_cast<Card::Color>(col); //sets each card to a color, iterates through enum
        length++;
    }

    //card value 1-9 , draw-two (10), skip (11), reverse (12)
    for (num = 1; num <= 12; num++)
    {
        for (int x = 0; x < 2; x++)
        {
            for (int col = 0; col <= 3; col++)
            {
                deck[length].value = num;
                deck[length].color = static_cast<Card::Color>(col);
                length++;
            }
        }
    }

    //wild(13) and draw four(14)
    for (num = 13; num <= 14; num++)
    {
        for (int x = 0; x < 4; x++)
        {
            deck[length].value = num;
            deck[length].color = Card::Color::WILD;
            length++;
        }
    }

}


void Deck::shuffle() //fisher-yates algorithm
{
    srand(time(NULL));
    for (int i = length - 1; i > 0; i--)
    {
        int j = (rand() % (i + 1));
        std::swap(deck[j], deck[i]);
    }

}

void Deck::printDeck()
{   
    for (int i = 0; i < length; i++)
    {
        std::cout << "Length: " << i << std::endl;
        std::cout << "Value: " << deck[i].value << std::endl;
        std::cout << "Color: ";
        toString(deck[i].color);
    }
}

void Deck::pop()
{
    if (isEmpty() == false)
    {
        length--;
    }
}

int Deck::top()
{
    if (isEmpty() == false)
    {
        return length - 1;
    }
    return 0;
}

bool Deck::isEmpty()
{
    if (length == 0)
    {
        return true;
    }

    return false;
}

bool Deck::isFull()
{
    if (length >= MAXSIZE)
    {
        return true;
    }
    return false;
}


void Deck::toString(Card::Color color)
{
    switch (color)
    {
    case Card::Color::BLUE:
        std::cout << "Blue";
        break;

    case Card::Color::GREEN:
        std::cout << "Green";
        break;

    case Card::Color::RED:
        std::cout << "Red";
        break;

    case Card::Color::YELLOW:
        std::cout << "Yellow";
        break;

    case Card::Color::WILD:
        std::cout << "Wild";
        break;
    }
    return;
}


void Deck::dealCard(Player &player) 
{
    player.pushHand(deck[top()]);
    pop();
    return;
}

Card Deck::getCard()
{
    return deck[length-1];
}


Deck::~Deck()
{
}

甲板中每张卡的位置

#pragma once

class Card
{
private:


public:
    enum Color { BLUE, GREEN, RED, YELLOW, WILD };
    Card();
    Color color;
    int value;
    Card(Color color, int value);

    ~Card();
};


   #include "Card.h"

Card::Card()
{
}

Card::Card(Color color, int value)
{
    color = this->color;
    value = this->value;
}

Card::~Card()
{
}

1 个答案:

答案 0 :(得分:0)

我认为您可以将迭代int放入Game的成员m_currentIterator中,并将迭代方向设置为bool m_isReversed(true = normal,false = reversed)。

当玩家使用“ Reverse”卡时,您只需将m_isReversed更改为!m_isReversed;并在相反的if(m_isReversed)i--否则i ++中进行迭代。

当播放器使用“跳过”时,您只需使用m_currentIterator ++;

我知道这不是最好的方法,也不是丑陋的代码(使用愚蠢的成员),但是效果很好:)