#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
using namespace std;
int createZombie() {
if (rand() % 67 < 10)
return 11;
else
return rand() % 10 + 1;
}
int main() {
srand(time(NULL));
char enter;
// game starts
int playerAlive = true;
int playerSkill = 9;
int playerScore = 1;
string playerName = "";
int zombieCount = 0;
int zombiesKilled = 0;
// title
cout << "Welcome to Zombie War." << endl << "Press [ENTER] to start.";
cin.get();
// player name
cout << "Please enter your name: ";
cin >> playerName;
// ask how many zombies
cout << "How many zombies do you wish to fight? ";
cin >> zombieCount;
cout << "Get ready to fight for your life, " << playerName << "!" << endl;
// main game loop
while (playerAlive && zombiesKilled < zombieCount) {
// create a random zombie
int zombieSkill = createZombie();
// battle sequence
if (zombieSkill > 10) {
cout << endl << "Here comes a huge zombie!" << endl;
}
else {
cout << endl << "Here comes zombie " << zombiesKilled + 1 << endl;
}
cout << "Fighting..." << endl;
sleep(2);
// zombie killed the player
if (playerSkill < zombieSkill) {
playerAlive = false;
cout << "You have died." << endl;
}
// player killed the zombie
else {
if (playerSkill - zombieSkill > 7) {
cout << "You wasted the zombie!" << endl;
playerScore = playerScore * 2;
}
else if (playerSkill - zombieSkill > 5) {
cout << "You decapitated the zombie!" << endl;
playerScore = playerScore * 2;
}
else if (playerSkill - zombieSkill > 0) {
cout << "You killed the zombie!" << endl;
playerScore = playerScore * 2;
}
else {
cout << "You killed the zombie, but suffered injuries." << endl;
}
zombiesKilled++;
}
cout << endl;
sleep(1);
}
// end game
if (zombiesKilled == zombieCount) {
// victory
cout << "You have survived the onslaught!" << endl;
}
else {
// lost
cout << "You did not survive the zombie war." << endl;
}
cout << "Zombies killed: " << zombiesKilled << endl;
cout << "Final score: " << playerScore << endl << endl;
}
rubberman 1,355 Nearly a Posting Virtuoso Featured Poster
OOP - classes + member variables + methods. Look at your code. What things could be expressed in classes? Zombies are one. There may be others.
ddanbe 2,724 Professional Procrastinator Featured Poster
PLayer should be a decent second, as class. Find out what a player object has and what this object can do.
AssertNull 1,094 Practically a Posting Shark
Here's a semi-start, simply doing a few cut-pastes in your code. Player and Zombie seem like good classes. To start you off, I've changed the Player to a Plain-Old-Data structure. A structure is a class, except its default access is public, not private. Google "C++ struct vs. class" for more information.
So I've taken your lines 20 through 25 and incorporated them into a Player structure, and I've created a new Player called player...
struct Player
{
Player()
{
playerAlive = true;
playerSkill = 9;
playerScore = 1;
playerName = "";
zombieCount = 0;
zombiesKilled = 0;
}
int playerAlive;
int playerSkill;
int playerScore;
string playerName;
int zombieCount;
int zombiesKilled;
};
This goes above the main function. Compare it to your lines 20 through 25. Player has those 6 attributes listed OUTSIDE the constructor. Then the default values are set inside the constructor.
Now look at the main function before the while loop.
int main() {
srand(time(NULL));
char enter;
// game starts
Player player;
// title
cout << "Welcome to Zombie War." << endl << "Press [ENTER] to start.";
cin.get();
// player name
cout << "Please enter your name: ";
cin >> player.playerName;
// ask how many zombies
cout << "How many zombies do you wish to fight? ";
cin >> player.zombieCount;
cout << "Get ready to fight for your life, " << player.playerName << "!" << endl;
Same as your code (note lines 20 to 25 are gone), but note that I have a line near the top to replace lines 20 to 25 in main.
Player player;
This creates a new object of type Player (upper-case) called player (lower-case). The code below is the dame as yours except note that I've added player.
in a lot of places, like here...
cin >> player.playerName;
C++ does the following with this...
- The part BEFORE the dot specifies the object (player)
- The part AFTER the dot specifies the attribute (playerName)
- The
cin >>
part you already know. - End result is that if you type in "Bob", the
playerName
attribute of theplayer
object is assigned to equal "Bob".
The other lines are the same, as is the rest of the program. For fun, make the changes I made, but keep the rest of the program the same and compile. You'll get lots of errors. Everywhere you get an error, add player.
in front of the variable that is giving you the error (which will be one of the six Player attributes) and recompile. The errors will go away one-by-one and it'll eventually compile. It will run exactly the same as it did before the changes.
Next do the same thing with the zombies. Create a struct called Zombie. Look at your code. What is an attribute of a Zombie? Use Player as a guideline. Change createZombie into a constructor. Don't have it return anything. Instead, take the value that createZombie returns and assign its value as an attribute of Zombie.
So line 44 turns into...
Zombie zombie;
Which means you'll now get a bunch of errors everywhere you use zombieSkill
in main since C++ is looking for a variable called zombieSkill
declared in main, which no longer exists. See what I did with Person
to correct that.
Again, when you get it right, it will run exactly like your original program data. At this point, going back to rubberman's post,
OOP - classes + member variables + methods.
you have the "member variables" part (I used the word "attribute" instead of "variable". Same thing here). Then add the "methods" part. Finally, you can change the struct to a class if you want and write a few "get" and "set" methods if you want to make the attributes "private".
Hopefully that gets you started.
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
If you want to go fully OO then you will also need some kind of Game class that encapsulates the process of playing a game and reporting the results. zombie
and player
will be member variables of the Game class.
Because there's a lot of interaction with the human player, you may want to encapsulate that in a UserInterface class. Get that right and you would be able to replace the console I/O witha GUI or web server without changing any of the Game, Zombie or Player code.
If your main method has anything more than some configuration initialisation and a handful of object creation calls then you're not "fully" OO.
Edited by JamesCherrill
AssertNull 1,094 Practically a Posting Shark
If you want to go fully OO then you will also need some kind of Game class
Good point. And doing so might cause you to move zombieCount
and perhaps zombiesKilled
from Player to Game.
The art (and I believe it is more art than science, YMMV) of what classes to put what attributes in can be hotly debated. One also has to consider how far you might take this. If this is a one-time assignment or you'll always play exactly one game in the program, that's one thing. Just put everything somewhere that makes sense and don't worry about it too much. But if you might potentially use these classes for a while and in multiple different programs, and this is code that you need to keep updating for quite a while and which you use a lot, you'll want to think long and hard about what to put where. The effort expended up front can pay off later.
At the same time, if it's a one-time limited deal, I think there is a potential Object-Oriented trap that we need to be careful not to fall into, namely sometimes we (or maybe it's just me) find ourselves overthinking things and thinking too far ahead and, to take James' example of a user interface, anticipating problems in case people want to write a bunch of different user interfaces in different languages, some console, some graphical, etc., and none of that ever happens and it would have saved a lot of time to have simply hardcoded it in the main function.
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
I agree with the above, but re-use and future developments, while essential to good commercial practice, are not the only criteria for object definition.
Cohesion and Coupling, for me, is the most important way of thinking about what classes and what goes in which class. And that's all about clarity vs confusion in the code, So, for example, the player's state (skill, score etc) and the methods that change it are highly cohesive and belong in one class. Displaying menus etc to the user and getting input, and handling errors in that are also highly cohesive. But putting both those in the same class creates a load of low-level couplings where a few accessor methods are enough to separate them completely. The resulting code modules are more in number, but smaller and simpler to understand and get right.
In my mind that is the fundamental argument. Being able to plug different UIs is a consequence of it, not the reason for it.
The point about "Just put everything somewhere that makes sense and don't worry about it too much" is a valid opinion, but the original topic was to "change this program to fully OOP". In that context I think that putting everything into classes is what's called for. This is a learning exercise, not a real application development.
More generally, I think we always have a problem when people try to apply OO principles to tutorial applications that are only a couple of hundred lines anyway. They just are not sufficently complex for OO to be able to give any real advantage.
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.