Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

Virtual Monopolium

5.00/5 (3 votes)
4 Sep 2013CPOL7 min read 15.2K  
A make-over of one of the most popular family games, Monopoly.

This article is an entry in our AppInnovation Contest. Articles in this sub-section are not required to be full articles so care should be taken when voting.

Introduction

Using the AIO Platform, Virtual Monopolium can be played with up to 6 players. Laying the AIO down on the table, as you would the original board game, using touch sensors players will be able to interact with the game. The idea is to keep as many of the hands-on experiences possible as one would have in the board game by allowing players to drag their own pieces the amount of spaces allowed, swiping their fingers to flip a card over, dragging their newly purchased properties into place, and interacting with your virtual banking system to make transactions.  The screen space on a 27" AIO Platform will allow comfortable and enjoyable viewing angles while providing enough space for each player to have a designated area around the game board (edge of screen) called the Users Corner to access statistical information during game play. Players will have the added option of managing their Users Corner from their smart phone. The high definition graphics will display a stunning visuals. This will be by far the most enjoyable and interactive Monopoly based board game. 

Background   

Virtual Monopolium is a complete remake of the classic game Monopoly.  The graphical theme of the game will follow a space-age format. Properties will be space stations and bases, game pieces will be space related objects such as a space shuttle, and the avenues will be replaced with planets, constellations, and galaxies. Mostly everyone is familiar with Monopoly, and if not, Wikipedia provides all its history information as well as how the original game is played. Game play instructions will come in a PDF format will Virtual Monopolium.  

This game will bring the fun of playing Monopoly into a new generation while being somewhat educational at the same time. While playing, players will learn of the universe with identifiable, realistic and attractive graphics. Galaxies expected to be seen are the Milky Way, Andromeda, Centaurus, and Omega galaxies among others as well. The railroads are replace with 4 stars known as Sirius, Epsilon, Arcturus, and the Sun. The jail will be a super-massive black hole.  

Using the Code 

The game will be created using Visual C++. By using the .NET language, it will pave an easier path to implement online gaming with friends. The standard Windows 8 API incorporates all of the touch capabilities I'll need to make this work. 

The visuals/graphics of this game will be created later after I get a solid code working using simpler bitmap graphics (as place holders).

One important function will be the dice rolling function. There will be an option of using either the eDices provided by the AIO or using virtual dices which will be rolled with a swipe of 2 fingers in a designated area. I will use 2 random number generators between 1-6 for each dice and will return each value in order to display the proper dice face and allow the player to move those number of spaces.

C++
int rolls = 0;
while(rolls <= 1) {
    faceValue = 1 + rand() % 6;
    if(rolls == 0) {
        dice.setValue1(faceValue);
    }
    else if(rolls == 1) {
        dice.setValue2(faceValue);
    }
    else {
        return;
    }
    rolls++;
}

As you can see, Classes are created to hold information. There will be a class for dice, board and players, as well as other game components such as the random cards. The Player class will hold values such as position, money, properties, cards, etc.. Using these classes will be important when dressing the game with graphics as the information will need to be retrieved in order to display its proper graphic.

C++
ref class Bank {
    private:
        double _500s;
        double _100s;
        double _50s;
        double _20s;
        double _10s;
        double _5s;
        double _1s;
    public:
        Bank() {
            Clear();
        }
    void set(double a, double b, double c, double d, double e, double f, double g) {
        _500s = a;
        _100s = b;
        _50s = c;
        _20s = d;
        _10s = e;
        _5s = f;
        _1s = g;
    }
    double get500s() {
        return _500s;
    }
    double get100s() {
        return _100s;
    }
    double get50s() {
        return _50s;
    }
    double get20s() {
        return _20s;
    }
    double get10s() {
        return _10s;
    }
    double get5s() {
        return _5s;
    }
    double get1s() {
        return _1s;
    }
    double getTotal() {
        return (_500s * 500) + 
            (_100s * 100) + 
            (_50s * 50) + 
            (_20s * 20) + 
            (_10s * 10) + 
            (_5s * 5) + _1s;
    }
    void Clear() {
        _500s = -1;
        _100s = -1;
        _50s = -1;
        _20s = -1;
        _10s = -1;
        _5s = -1;
        _1s = -1;
    }
};

An example of how the game board will be animated is as follows:

C++
void pictureBox1_Paint(Object ^obj, System::Windows::Forms::PaintEventArgs ^e) { 
    Graphics ^g = e->Graphics;
    g->PixelOffsetMode = PixelOffsetMode::HighSpeed;
    float by_x, by_y;
    by_x = gameBoard.getByX();
    by_y = gameBoard.getByY();
    Image ^BoardImg = Image::FromFile(L"graphics\\gameboard.png");
    g->DrawImageUnscaled(BoardImg,(int)(gameBoard.getByX()),(int)(gameBoard.getByY());
    int count = Players.getCount();
    if(count > 0) {
        for(int i = 0; i<count; i++) {
            int toy = Players.getToy(i);
            switch(toy) {
            case 1:
                Image ^pImg = Image::FromFile(L"img\\shuttle.png");
                break;
            case 2:
                Image ^pImg = Image::FromFile(L"img\\probe.png");
                break;
            case 3:
                // etc... insert all pieces
                break;
            }
            g->DrawImage(pImg,(int)((Players.getPosX(i)-1000)/by_x),
            (int)((Players.getPosY(i)-1000)/by_y),(int)(2000.0f/by_x),(int)(2000.0f/by_y));
        }
   } 

Next to be designed is the algorithm for the 16 Chance and 16 Community Chest cards. Within 2 classes, all the possible card values will be stored. At the beginning of each game, the cards are loaded into 2 arrays and shuffled so no game will ever have the same sequence of cards. Using the random number generator, values 1-16 will be assigned to each card in each deck. That will be the numerical order of each stack. The tricky part is making sure that no 2 cards in a single deck are assigned the same numerical value during shuffling. For that we use the Fisher-Yates Shuffle algorithm to ensure that doesn't happen. Example code of the algorithm:

C++
int arrayOrder[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16 };
Random rand = new Random();
for (int i = arrayOrder.Length - 1; i >= 0; i--) {
    int r = rand.Next(0, i+1);
    int temp = arrayOrder[i];
            arrayOrder[i] = array[r];
            arrayOrder[r] = temp;
}
for(int i = 0; i <= deck1->Count; i++) {
    static_cast<Decks^>(deck1[i])->setOrder(arrayOrder[i]); 
} 

When coding, its important to keep in mind of future implementations. This would be the best time to pave your path and leave open doors. By coding everything into classes, updating this game into a multiplayer networking game will be an easier implementation via JSON serialization after a stable first release of the game is created. 

The Objects class will be used to create every individual deck card. Using an ArrayList I can create 2 separate decks of 16 cards each. The Decks class stores the information of what type of card it is, its position in the deck, and the message it will display. The cards can be read, added back, or deleted from the deck. A count of remaining cards is kept. A removal of a card from the ArrayList most likely equals the card being moved to the possession of one of the players (like a "get out of prison free" card), in which case another Players class will hold that information along with all of that players properties/money. Here is an example of how the Decks class is being handled in code: 

ref class Decks {
    private:
        int card;
        int order;
        String ^msg;
    public:
        Decks() {
            Clear();
        }
        Decks(int _card, int _order, String ^_msg) {
            set(_card,_order,_msg);
        }
        void set(int _card, int _order, String ^_msg) {
            card = _card;
            order = _order;
            msg = _msg;
        }
        int getCard() {
            if(this == nullptr)
                return -1;
            return card;
        }
        int getOrder() {
            if(this == nullptr)
                return -1;
            return order;
        }
        String ^getMsg() {
            if(this == nullptr)
                return L"";
            return msg;
        }
        void setOrder(int x) {
            order = x;
        }
        void Clear() {
            if(this == nullptr)
                return;
            card = -1;
            order = -1;
            msg = gcnew String(L"");
        }
};

ref class Objects {
    private:
        ArrayList ^deck1;
        ArrayList ^deck2;
    public:
        Objects() {
            Clear();
        }
        void addToDeck1(int card, int order, String ^msg) {
            deck1->Add(gcnew Decks(card,order,msg));
        }
        void addToDeck2(int card, int order, String ^msg) {
            deck2->Add(gcnew Decks(card,order,msg));
        }
        void removeFromDeck1(String ^msg) {
            for(int i = 0; i<deck1->Count; i++) {
                if(msg->Equals(static_cast<String^>(static_cast<Decks^>(deck1[i])->getMsg()))) {
                    deck1->RemoveAt(i);
                    break;
                }
            }
        }
        void removeFromDeck2(String ^msg) {
            for(int i = 0; i<deck2->Count; i++) {
                if(msg->Equals(static_cast<String^>(static_cast<Decks^>(deck2[i])->getMsg()))) {
                    deck2->RemoveAt(i);
                    break;
                }
            }
        }
        int getDeck1Count() {
            return deck1->Count;
        }
        int getDeck2Count() {
            return deck2->Count;
        }
        Decks ^getCardFromDeck1(int index) {
            if(index+1 > deck1->Count)
                return nullptr;
            return static_cast<Decks^>(deck1[index]);
        }
        Decks ^getCardFromDeck2(int index) {
            if(index+1 > deck2->Count)
                return nullptr;
            return static_cast<Decks^>(deck2[index]);
        }
        void Clear() {
            deck1 = gcnew ArrayList();
            deck2 = gcnew ArrayList();
        }
}; 

 Windows touch input event handlers are used to link your desired affect to a tap or swipe. Players have the option of sliding their game pieces on the game board after rolling the dices. Windows 8 has a lot of the basics built in for you so mouse click events and such should work with a desktop app running in Windows 8, but to do precise functions, you will have to point the event to the touch input. In the following example I will demonstrate the angle of approach i took to use the "Pan" gesture to move your game pieces along the game board (keep in mind there is more than one way to do this using different input methods). 

GESTUREINFO  gi;
bool isHandled = false;
Point ^first = gcnew Point();
Point ^second = gcnew Point();

Players ^CurrentHero = Players.getActive();

switch(gi.dwID) {
    case GID_PAN:
        switch(gi.dwFlags) {
            case GF_BEGIN:
                first.X = gi.ptsLocation.x;
                first.Y = gi.ptsLocation.y;
                CurrentHero.highlight(first.X, first.Y);
                Players.CurrentHero = PointToClient(gcnew Point(first.X, first.Y) );
                isHandled = true;
                break;
            case GF_END:
                PlayLoop(false);
                isHandled = true; 
            case default:
                second.X = gi.ptsLocation.x;
                second.Y = gi.ptsLocation.y;
                CurrentHero.move(second.X,second.Y);
                Players.CurrentHero = PointToClient(gcnew Point(second.X, second.Y) );
                isHandled = true;
                Invalidate();
                first = second;
                break;
        }
    case default:
        isHandled = false;
}

 The Users Corner App will be developed to target both iOS and Android devices using the OpenFL Framework. Intel's Common Connectivity Framework middleware makes it possible for smart phones to communicate with Windows OS. Wifi connectivity will be possible in both the smart phone and the computer are on the same network. Bluetooth connectivity will be possible by simply pairing the devices. 

Points Of Interest 

  • Targeted for the All-In-One Platform, Games category of the 2013 Intel App Innovation Contest
  • The usage of threads to draw and run the games logic
  • Using object classes, serializing classes for multi-player networking will be easier to implement 
  • Using Windows 8 API to integrate touch capabilities and mouse click events for back-wards compatibility 
  • The size of the AIO platform is a good size for a game board. In the past, playing classic game boards on a PC with multi-players was frustrating due to just the size of PCs (not to mention it's all displayed on an upright monitor). Laying the AIO down allows for multiple users to comfortably sit around the game board 
  • The new eDice technology adds to the user experience of playing a classic board game 
  • Multi-user multi-touch technology allows for the designated banker to perform banking transactions even while another player is playing his/her turn. Individual users will have a designated area on either edge of the screen to view their banking, properties, and other such statistical information in what will be called Users Corner (the Banker will have banking privileges in their Users Corner) 
  • Users Corner will take advantage of Intel's CCF middleware for multi-gadget capabilities to make it reachable from a smart phone. Connectivity to your smart phone will be possible via either Wifi or Bluetooth   
  • Online Multi-player mode will be possible so not all players have to be physically present (Users Corner will only display for users at their local machine) 

History

  • 9/1/2013: This is the first draft of the article and any code created. 
  • 9/2/2013: Added a continuation of the class code to handle the two decks and algorithm used to shuffle the decks.  
  • 9/3/2013: Added example of how touch input is linked to the movement of the game pieces, more background info on the theme of the game, and what to expect from the user experience  
  • 9/4/2013: Added information on the Users Corner App to be used with smart phones 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)