Background: In C++, enumerated values represent a fixed set of values that you c
ID: 3771749 • Letter: B
Question
Background:
In C++, enumerated values represent a fixed set of values that you can define up-front and do not change over time. The most typical example of an enumeration is a set of playing cards, broken up into well-known Suit and Face card values.
In C++, arrays represent a set of values that grow and shrink at run-time and lead to many loops. It is always the programmer's responsibility to not walk off the edge of their declared array. Like in C, array index values start counting from 0. Arrays are not objects and provide no methods so you can't ask them any questions at run-time. An array declared with five items ( [ 5 ] ) will means spots 0 through 4, that is, 5 in total.
The purpose of this programming assignment is to get some practice working with both these language features as well as use inheritance and aggregation.
Project 1: CardGame
I have prepared some starter code that you can acquire by clicking on the development environment you are working with: XCode7 VS 2012
As I discussed in class, this code is described below:
First, please make note of the enumerations that are part of the class named Card. A Card represents one of the fifty-two different cards in a regular deck of playing card.
Second, please make note of the following class diagram:
This diagram is trying to tell you a number of different things:
With respect to the class Card, instances of Card can be printed and queried for their Face and Suit value. You can also compare two Cards together, testing for equality and which card is more than the other.
With respect to the class Dealer, create a Dealer when you want to interact with the class Card. From the Dealer, you can request a single card. The Dealer will return one of the available playing cards randomly. Shuffling the deck allows the Dealer once again make any card available.
With respect to the class Hand, it holds a set of Card provided by its Dealer. The size of the Hand is set at constructor-time. buildHand populates the set of Card at run-time. You can query the Cards in a Hand by calling getCard( int ). getCard( int ) will throw an exception if you ask for a index that is out of range.
Your assignment is to create the class Game. The game I am asking you to build is one based on a three-card hand provided by a Dealer. You win the game if the three cards in your hand do not have a matching Suit value. My class modeling advice is shown in the diagram below.
Please use inheritance to create a ThreeCardHand. A ThreeCardHand IS-A kind-of Hand. It is a Hand with a size of 3. Once created, you should make a Game have a ThreeCardHand pointer member variable. When the Game is played, if the Hand member variable is not NULL, you should delete and then new it for your use. Then you should build your Hand and then loop thru the Hand's array of Card to determine whether you have won or lost. Store that boolean answer in the member variable myDidIWin so it can be queried after the Game has been played for the results. There are various // TODO comments you should review to see what I mean.Here is some driver code for you to run. It runs right out of the box, but of course, the game is not implemented so you will always have a lost game when played. I am hoping sometimes that you will win the game...
Explanation / Answer
Features that you want your library to have:
Some game libraries include:
Step 2: Define the Concept
All games start here, merely ideas in someone's head.
First, come up with an idea for a game. Once you have a simple idea, expand on it. For example, if it is a board game, what is the objective/How do you win? What will the rules be like? etc. If your game will have characters or a story, create them. Make sure you have a pretty well-defined concept of what your game will be when it's finished. The more complex the game, the better you should plan it out in the beginning so you don't have to worry about the game itself while your coding. Keep in mind that your game WILL evolve as you create it.
Step 3: Plan Your Engine
If you're making a board game or basic arcade equivalent you can skip this entirely and simply program your game. For more complex games, however, you may want to look into using a pre-made engine, or writing your own "engine". What even is a game engine you ask? While they vary widely in structure and overall functionality, you can think of a game engine as a super-powered library that provides higher level functionality such as physics, resource handling and game entity management. Whether you choose to use an existng engine or create your own, so to speak, is up to you and depends on how much programming you actually want to do. Using a pre-made engine will simplify your job as a programmer to scripting gameplay/events more than anything else.
Why did I say plan rather than choose? Well, odds are you're not making the next Elder Scrolls, and therefor, can create your own "engine" of sorts. Keep in mind that you will not be creating the next Unreal Engine, and most of the code you write and intend to be reusable (as is the point of an engine) will end up being so intertwined with your game logic that it is impossible to reuse easily. With this in mind, don't worry if parts of your "engine" rely on code specific to the game, this is just going to happen. Instead of focusing on making a completely reusable, super robust framework, focus on making sure the code is readable, organized and functional. Focus first on making the game, then try to create portable modules. If you absolutely must write something useful and reusable, resource managers and other various utility classes are good starting points.
Step 4: Write Your Engine (if you're making your own)
Now its time to actually start writing your engine, provided this is the route you chose. This doesn't necessarily mean the game itself, but rather, core rendering, physics, and file handling; essentially the functions and classes that will be used to construct your game. Simple games won't really require much of a framework, and can just be programmed using your game library directly. One of the most important, and most neglected, components of larger games is the resource manager. The resource manager is (presumably) a class that is responsible for loading resources (think graphics and sound), ensuring that resources are loaded only once, and unloading resources when they are no longer needed. RAM isn't infinite, so if your game is loading a separate copy of the same image for every piece of grass in the universe, you're going to have a bad time. See an excellent resource manager below by Xander314.
Resource Manager by Xander314
Another important aspect of your engine/framework is the interface. When you're writing the logic of the game itself it shouldn't take you 4 hours to write the main game loop as you search through the hundreds of update functions trying to figure out which ones you actually need. Keep it simple and concise. If you're able to update all game logic with one or two function calls and render the scene with one or two more you're on the right track. Taking advantage of object oriented principles, such as inheritance and pure virtual base classes (think interfaces) is a great way to create a framework with a sound structure.
For example, a base class of all game objects could be defined as such:
With all subclasses now being held to this interface it is possible to have one holding entity that can easily store and manage any and every object you define regardless of what the object actually is. As you learn and program more and more you'll find more ways of using the various features of your language of choice to your advantage.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
/* ResourceManagerB.hpp - Generic template resource manager (C) Alexander Thorne (SFML Coder) 2011 <a href="http://sfmlcoder.wordpress.com/">http://sfmlcoder.wordpress.com/</a> Manages loading and unloading of a resource type specified by a template argument. ****************************************************************/ #include <map> #include <string> #include <exception> typedef const std::string URI; // exceptions namespace Exceptions { // thrown if user requests a resource URI not present in the manager's list class URINotFound : public std::runtime_error { public: URINotFound(const std::string& Message = "The specified URI was not found in the resource index.") : runtime_error(Message) { } }; // thrown if a resource allocation fails class BadResourceAllocation : public std::runtime_error { public: BadResourceAllocation(const std::string& Message = "Failed to allocate memory for resource.") : runtime_error(Message) {} }; } template <class Resource> class ResourceManagerB { typedef std::pair<URI, Resource*> ResourcePair; typedef std::map<URI, Resource*> ResourceList; // the list of the manager's resources ResourceList Resources; public: ~ResourceManagerB() { UnloadAll(); } // Load a resource with the specified URI // the URI could represent, e.g, a filename URI& Load(URI& Uri); // unload a resource with the specified URI void Unload(URI& Uri); // unload all resources void UnloadAll(); // get a pointer to a resource Resource* GetPtr(URI& Uri); // get a reference to a resource Resource& Get(URI& Uri); }; template <class Resource> URI& ResourceManagerB<Resource>::Load(URI& Uri) { // check if resource URI is already in list // and if it is, we do no more if (Resources.find(Uri) == Resources.end()) { // try to allocate the resource // NB: if the Resource template argument does not have a // constructor accepting a const std::std::string, then this // line will cause a compiler error Resource* temp = new (std::nothrow) Resource(Uri); // check if the resource failed to be allocated // std::nothrow means that if allocation failed // temp will be 0 if (!temp) throw Exceptions::BadResourceAllocation(); // add the resource and it's URI to the manager's list Resources.insert(ResourcePair(Uri, temp)); } return Uri; } template <class Resource> void ResourceManagerB<Resource>::Unload(URI& Uri) { // try to find the specified URI in the list ResourceList::const_iterator itr = Resources.find(Uri); // if it is found... if (itr != Resources.end()) { // ... deallocate it delete itr->second; // then remove it from the list Resources.erase(Uri); } } template <class Resource> void ResourceManagerB<Resource>::UnloadAll() { // iterate through every element of the resource list ResourceList::iterator itr; for (itr = Resources.begin(); itr != Resources.end(); itr++) // delete each resource delete itr->second; // finally, clear the list Resources.clear(); } template <class Resource> Resource* ResourceManagerB<Resource>::GetPtr(URI& Uri) { // find the specified URI in the list ResourceList::const_iterator itr; // if it is there... if ((itr = Resources.find(Uri)) != Resources.end()) // ... return a pointer to the corresponding resource return itr->second; // ... else return 0 return 0; } template <class Resource> Resource& ResourceManagerB<Resource>::Get(URI& Uri) { // get a pointer to the resource Resource* temp = GetPtr(Uri); // if the resource was found... if (temp) // ... dereference the pointer to return a reference // to the resource return *temp; else // ... else throw an exception to notify the caller that // the resource was not found throw Exceptions::URINotFound(); } Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.