In: Computer Science
In C++, please include main
Goals
Identify requirements for a program using polymorphism
Create a program to demonstrate your class hierarchy
Requirements
|
In this project, you will create a simple class hierarchy as the basis for a fantasy combat game. Your ‘universe’ contains Vampires, Barbarians, Blue Men, Medusa and Harry Potter. Each has characteristics for attack, defense, armor, and strength points as follows. Type |
Attack |
Defense |
Armor |
Strength Points |
|
Vampire1 |
1d12 |
1d6* Charm |
1 |
18 |
|
Barbarian2 |
2d6 |
2d6 |
0 |
12 |
1. Suave, debonair, but vicious and surprisingly resilient!
2. Think Conan or Hercules from the movies. Big sword, big muscles, bare torso.
“3d6” is rolling three 6-sided dice, “2d10” is rolling two 10-sided dice, etc.
NOTE: The sample creatures are unbalanced intentionally. This will help you in debugging your program! Some will win a lot, and others will lose a lot.
To resolve an attack, you will need to generate 2 dice rolls. The attacker rolls the appropriate number and type of dice under Attack. The defender rolls the appropriate number and type of dice under Defense. You will subtract the Defense roll from the Attack roll. That is the damage to the defender.
Each class only has its own information or data. When O1 is fighting O2, your program should call O1’s attack function. It will return the damage inflicted. Then O2’s defense function will take the damage inflicted, roll the specified dice and subtract the damage points from the defense. To apply the damage, you subtract the Armor value. The result is then subtracted from the Strength Points. That value becomes the new Strength Points for the next round. If Strength Points goes to 0 or less, then the character is out of the combat. For example, if one object receives 9 points of damage and rolls 3 for its defense, and has an armor of 4 and strength point of 8, it would take 9 subtract 3, and then 4 for the armor, to receive 2 points of damage, and its new strength point will be 8-2=6.
Start with the base and Barbarian classes.
You need to create a Creature base class. Then you will have a subclass for each of these characters. Note that the Creature class will be an abstract class. For our purposes right now, each subclass will vary only in the values in the table. It is part of your design task to determine what functions you will need.
To play the game, write a menu. Display two fighters by their names and prompt the user to select two fighters to fight one another. Students must account for two fighters of the same type. Randomly select one fighter to attack first. The fighters will take turns fighting each other until one's Strength point is zero or negative. (You do not have to display results of each round of fighting, but you can do that for the purpose of debugging.) Then display the winning fighter to the screen. Ask users to play again or exit the game. This is the first stage of a larger project. Please do not add any creatures of your own.
main.cpp
#include "Functions.h"
#include "Creature.h" // base class
#include "Vampire.h"
#include "Barbarian.h"
#include "BlueMen.h"
#include "Medusa.h"
#include "HarryPotter.h"
#include <iostream>
#include <time.h> // for rand
#include <cstdlib> // used for the rand() function
using namespace std;
int main()
{
srand(time(0)); //seed the random number with
clock time to get a different set of random numbers each time
int choice;
cout << "\n\t~*~ Fantasy Combat Game ~*~" << endl;
// This is the main loop to display the menu
and run the specific parts of the program based on user input
do {
showMenu(); // display
menu to user
choice = getChoice(); //
get the input choice of the user from the menu
cin.ignore();
switch (choice) {
case 1: // Case 1 is just an output of the game rules and
description of each creature
showRules();
break;
case 2: // Case 2 is the actual game play where two players can
select their creatures and attack each other
{
int player1, player2;
int damage;
Creature *creature1;
Creature *creature2;
player1 = getCreature1();
player2 = getCreature2();
// create the creature for player 1
if (player1 == 1){
creature1 = new Vampire;
//cout << "creature1 is now a Vampire" << endl;
}else if (player1 == 2){
creature1 = new Barbarian;
//cout << "creature1 is now a Barbarian" << endl;
}else if (player1 == 3) {
creature1 = new BlueMen;
//cout << "creature1 is now Blue Men" << endl;
}else if (player1 == 4) {
creature1 = new Medusa;
//cout << "creature1 is now a Medusa" << endl;
}else if (player1 == 5) {
creature1 = new HarryPotter;
//cout << "creature1 is now Harry Potter" <<
endl;
}
// create the creature for player 2
if (player2 == 1) {
creature2 = new Vampire;
//cout << "creature2 is now a Vampire" << endl;
}else if (player2 == 2){
creature2 = new Barbarian;
//cout << "creature2 is now a Barbarian" << endl;
}else if (player2 == 3) {
creature2 = new BlueMen;
//cout << "creature2 is now Blue Men" << endl;
}else if (player2 == 4) {
creature2 = new Medusa;
//cout << "creature2 is now a Medusa" << endl;
}else if (player2 == 5) {
creature2 = new HarryPotter;
//cout << "creature2 is now Harry Potter" <<
endl;
}
// initialize the data members for the creatures...could have used
constructor instead? These functions do the same thing...
creature1->setData();
creature2->setData();
// confirm each players creature
cout << "Player 1 is: " << creature1->getName()
<< endl;
cout << "Starting armor: " << creature1->getArmor()
<< endl;
cout << "Starting strength: " <<
creature1->getStrength() << endl;
cout << endl;
cout << "Player 2 is: " << creature2->getName()
<< endl;
cout << "Starting armor: " << creature2->getArmor()
<< endl;
cout << "Starting strength: " <<
creature2->getStrength() << endl;
//Code here to Randomly pick and display which player will go
first
int x = rand() % 2 + 1;
if (x == 1)
cout << "\nPlayer 1 was randomly selected to start first!"
<< endl;
else
cout << "\nPlayer 2 was randomly selected to start first!"
<< endl;
// hit enter to continue
cout << "\nPress ENTER to begin the attacks...";
cin.ignore();
cin.get();
cin.sync();
// clear the screen
//cout <<"\033[2J\033[1;1H"; // clear the screen
FLIP
system("CLS");
// clear the screen WINDOWS
// bool variables used to determine if each creature died or
not
bool p1Dead = false;
bool p2Dead = false;
// PLAYER 1 GOES FIRST - main loop to simulate the attacks and
defense
if (x ==1){
while (p1Dead == false && p2Dead == false){
cout << "Player 1 attack:" << endl;
damage = creature1->attack(); // creature1 attack
cout << "\nPlayer 2 defense:" << endl;
creature2->defense(damage); // creature2 defend
p2Dead = creature2->isDead(); // check to see if creature2 died
if (p2Dead == false){
cout << "\nPlayer 2 attack:" << endl;
damage = creature2->attack(); // creature2 attack
cout << "\nPlayer 1 defense:" << endl;
creature1->defense(damage); // creature1 defend
cout << endl;
}
p1Dead = creature1->isDead(); // check to see if creature1
died
}
}else{ // PLAYER 2 GOES First
while (p1Dead == false && p2Dead == false){
cout << "Player 2 attack:" << endl;
damage = creature2->attack(); // creature 2 attack
cout << "\nPlayer 1 defense:" << endl;
creature1->defense(damage); // creature 1 defend
p1Dead = creature1->isDead(); // check to see if creature1 died
if (p1Dead == false){
cout << "\nPlayer 1 attack:" << endl;
damage = creature1->attack(); // creature2 attack
cout << "\nPlayer 2 defense:" << endl;
creature2->defense(damage); // creature1 defend
cout << endl;
}
p2Dead = creature2->isDead(); // check to see if creature1
died
}
}
// Game over, display winner/loser
if (p1Dead == true){
cout << "\n*** Battle over - Player 2 Wins with " <<
creature2->getName() << "!!! ***" << endl;
}else if(p2Dead == true){
cout << "\n*** Battle over - Player 1 Wins with " <<
creature1->getName() << "!!! ***" << endl;
}
// hit enter to return to main menu
cout << "\nPress ENTER to return to the main menu...";
//cin.ignore();
cin.get();
// clear the screen
//cout <<"\033[2J\033[1;1H"; // clear the screen
FLIP
system("CLS");
// clear the screen WINDOWS
// deallocate memory
delete creature1;
delete creature2;
}
break;
case 3: // Case 3 is a testing suite that the user can
automatically run test attacks with each creature match up
showTestMenu(); // show testing menu
int tChoice;
tChoice = getTestChoice(); // get choice of testing menu
cin.clear();
cin.ignore(1000, '\n');
// if statements here to run each test possibility
runTests(tChoice);
cout << "\nPress ENTER to return to the main menu...";
cin.get();
// clear the screen
//cout <<"\033[2J\033[1;1H"; // clear the screen
FLIP
system("CLS");
// clear the screen WINDOWS
break;
case 4: // Case 4 just exits the program
break;
}
} while (choice != 4); // if user enters 4 in
the main menu then the program exits
cout << "\nExiting Fantasy Combat Game, Goodbye! " << endl;
return 0;
}
//Barbarian.cpp
#include "Barbarian.h"
void Barbarian::setData(){
name = "Barbarian";
armor = 0;
strength = 12;
dead = false;
}
int Barbarian::attack(){
int damage = attackRoll();
cout << "Barbarian attacks! Barbarian
generated " << damage << " damage points to
opponent..." << endl;
return damage;
}
void Barbarian::defense(int d){
int defense = defenseRoll();
int damage;
if (d != 999){
cout << "Barbarian
attempts to defend! Barbarian generated " << defense <<
" defense points. " << endl;
damage = d -
defense;
}
else
damage = d;
if (damage <= 0){
cout << "Barbarian
defends! No change in armor and strength." << endl;
cout << "Remaining
armor points: " << armor << endl;
cout << "Remaining
strength points: " << strength << endl;
}else if (damage == 999){
cout << "Barbarian
Dies! Barbarian looked into Medusa's eyes and turned to stone!"
<< endl;
cout << "Armor
points: 0" << endl;
cout << "Strength
points: 0" << endl;
dead = true;
}else if (damage > armor){
damage = damage -
armor;
strength = strength -
damage;
armor = 0;
if (strength >
0){
cout << "Barbarian gets hurt but survives! " <<
endl;
cout << "Remaining armor points: " << armor <<
endl;
cout << "Remaining strength points: " << strength
<< endl;
}else if(strength <=
0){
cout << "Barbarian Dies! Defense not strong enough!" <<
endl;
cout << "Armor points: " << armor << endl;
cout << "Strength points: " << strength <<
endl;
dead = true; // barbarian dies!
}
}
}
string Barbarian::getName(){
return name;
}
bool Barbarian::isDead(){
return dead;
}
int Barbarian::attackRoll(){
int roll = rand() % 6 + 1; // generate random
number within 6
roll = roll + (rand() % 6 + 1); // 2nd dice
roll, add together
return roll;
}
int Barbarian::defenseRoll(){
int roll = rand() % 6 + 1; // generate random
number within 6
roll = roll + (rand() % 6 + 1); // 2nd dice
roll, add together
return roll;
}
int Barbarian::getArmor(){
return armor;
}
int Barbarian::getStrength(){
return strength;
}
//BlueMen.cpp
#include "BlueMen.h"
void BlueMen::setData(){
name = "Blue Men";
armor = 3;
strength = 12;
dead = false;
loseDie = 0; // SPECIAL ABLITY
}
int BlueMen::attack(){
int damage = attackRoll();
cout << "Blue Men attack! Blue Men
generated " << damage << " damage points to
opponent..." << endl;
return damage;
}
void BlueMen::defense(int d){
int defense = defenseRoll();
int damage;
if (d != 999){
cout << "Blue Men
attempt to defend! Blue Men generated " << defense << "
defense points. " << endl;
damage = d -
defense;
}
else
damage = d;
if (damage <= 0){
cout << "Blue Men
defend! No change in armor and strength." << endl;
cout << "Remaining
armor points: " << armor << endl;
cout << "Remaining
strength points: " << strength << endl;
}else if (damage > 0 && damage <=
armor){
armor = armor -
damage;
cout << "Blue
Men's armor absorbed the attack! " << endl;
cout << "Remaining
armor points: " << armor << endl;
cout << "Remaining
strength points: " << strength << endl;
}else if (damage == 999){
cout << "Blue Men
Die! Blue Men all looked into Medusa's eyes and all turned to
stone!" << endl;
cout << "Armor
points: 0" << endl;
cout << "Strength
points: 0" << endl;
dead = true; // vampire
dies!
}else if (damage > armor){
damage = damage -
armor;
strength = strength -
damage;
armor = 0;
if (strength >
0){
cout << "Blue Men get hurt but survive! " <<
endl;
cout << "Remaining armor points: " << armor <<
endl;
cout << "Remaining strength points: " << strength
<< endl;
}else if(strength <=
0){
cout << "Blue Men Die! Defense not strong enough!" <<
endl;
cout << "Armor points: " << armor << endl;
cout << "Strength points: " << strength <<
endl;
dead = true; // vampire dies!
}
}
// SPECIAL ABILITY - Mob - for every 4 points
of damage they lose one defense die
if (strength <= 8 && strength >
4)
loseDie = 1; // lose 1
die
else if (strength <= 4 && strength
> 0)
loseDie = 2; // lose 2
die
}
string BlueMen::getName(){
return name;
}
bool BlueMen::isDead(){
return dead;
}
int BlueMen::attackRoll(){
int roll = rand() % 10 + 1; // generate random
number within 10
roll = roll + (rand() % 10 + 1); // 2nd dice
roll, add together
return roll;
}
int BlueMen::defenseRoll(){
int roll;
if (loseDie == 0){
roll = rand() % 6 + 1;
// generate random number within 6
roll = roll + (rand() %
6 + 1); // 2nd dice roll, add together
roll = roll + (rand() %
6 + 1); // 3rd dice roll, add together
}else if (loseDie == 1){
roll = rand() % 6 + 1;
// generate random number within 6
roll = roll + (rand() %
6 + 1); // 2nd dice roll, add together
}else if (loseDie == 2){
roll = rand() % 6 + 1;
// generate random number within 6
}
return roll;
}
int BlueMen::getArmor(){
return armor;
}
int BlueMen::getStrength(){
return strength;
}
//Creature.h
#ifndef CREATURE_H
#define CREATURE_H
#include <iostream>
#include <string>
#include <time.h> // for rand
#include <cstdlib> // used for the rand() function
using namespace std;
class Creature
{
protected:
string name;
int armor;
int strength;
bool dead;
public:
// all virtual
functions
virtual void
setData()=0;
virtual int
attack()=0;
virtual void defense(int
d)=0;
virtual string
getName()=0;
virtual bool
isDead()=0;
virtual int
attackRoll()=0;
virtual int
defenseRoll()=0;
virtual int
getArmor()=0;
virtual int
getStrength()=0;
virtual ~Creature()
{}
};
#endif // CREATURE_H
//Functions.h
#include "Creature.h" // abstract base class
#include "Vampire.h"
#include "Barbarian.h"
#include "BlueMen.h"
#include "Medusa.h"
#include "HarryPotter.h"
#include <iostream>
#include <time.h> // for rand
#include <cstdlib> //Delete when compiling on FLIP? This is
used for clear screen in windows
using namespace std;
void showMenu(); // This function prints the opening menu to user
int getChoice(); // This function gets the input choice of the user from the menu
void showRules(); // This function displays the game rules and the descriptions of the creatures
int getCreature1(); // This function prompts user on which creature to use for player 1
int getCreature2(); // This function prompts user on which creature to use for player 2
void showTestMenu(); // This function prints out the menu for testing option
int getTestChoice(); // This function gets and verifies input for the testing suite menu
void runTests(int t); // This function runs test fights between characters
//HarryPotter.cpp
#include "HarryPotter.h"
void HarryPotter::setData(){
name = "Harry Potter";
armor = 0;
strength = 10;
dead = false;
hogwarts = 1; // hogwarts variable used for
SPECIAL ABILITY
}
int HarryPotter::attack(){
int damage = attackRoll(); // call attackRoll
function
cout << "Harry Potter attacks! Harry
Potter generated " << damage << " damage points to
opponent..." << endl;
return damage;
}
void HarryPotter::defense(int d){
int defense = defenseRoll(); // call defense
roll function
int damage;
if (d != 999){
cout << "Harry
Potter attempts to defend! Harry Potter generated " <<
defense << " defense points. " << endl;
damage = d -
defense;
}
else
damage = d;
if (damage <= 0){
cout << "Harry
Potter defends! No change in armor and strength." <<
endl;
cout << "Remaining
armor points: " << armor << endl;
cout << "Remaining
strength points: " << strength << endl;
}else if (damage == 999 && hogwarts ==
1){ // SPECIAL ABILITY
cout << "Harry
Potter Dies! Harry Potter looked into Medusa's eyes and turned to
stone!" << endl;
cout <<
"~Hogwarts~ Harry Potter immediately recovered and now has 20
strength points!" << endl;
hogwarts = 0;
strength = 20;
cout << "Armor
points: " << armor << endl;
cout << "Strength
points: " << strength << endl;
}else if (damage == 999 && hogwarts ==
0){
cout << "Harry
Potter Dies! Harry Potter looked into Medusa's eyes and turned to
stone!" << endl;
strength = 0;
cout << "Armor
points: " << armor << endl;
cout << "Strength
points: " << strength << endl;
dead = true; // Harry
dies!
}else if (damage > armor){
damage = damage -
armor;
strength = strength -
damage;
armor = 0;
if (strength >
0){
cout << "Harry Potter gets hurt but survives! " <<
endl;
cout << "Remaining armor points: " << armor <<
endl;
cout << "Remaining strength points: " << strength
<< endl;
}else if(strength <=
0 && hogwarts == 1){ // SPECIAL ABILITY
cout << "Harry Dies! Defense not strong enough!" <<
endl;
cout << "~Hogwarts~ Harry Potter immediately recovered and
now has 20 strength points!" << endl;
hogwarts = 0;
strength = 20;
cout << "Armor points: " << armor << endl;
cout << "Strength points: " << strength <<
endl;
}else if(strength <=
0 && hogwarts == 0){
cout << "Harry Dies! Defense not strong enough!" <<
endl;
cout << "Armor points: " << armor << endl;
cout << "Strength points: " << strength <<
endl;
dead = true; // Harry dies!
}
}
}
string HarryPotter::getName(){
return name;
}
bool HarryPotter::isDead(){
return dead;
}
int HarryPotter::attackRoll(){
int roll = rand() % 6 + 1; // generate random
number within 6
roll = roll + (rand() % 6 + 1); // 2nd dice
roll, add together
return roll;
}
int HarryPotter::defenseRoll(){
int roll = rand() % 6 + 1; // generate random
number within 6
roll = roll + (rand() % 6 + 1); // 2nd dice
roll, add together
return roll;
}
int HarryPotter::getArmor(){
return armor;
}
int HarryPotter::getStrength(){
return strength;
}
//HarryPotter.h
#ifndef HARRYPOTTER_H
#define HARRYPOTTER_H
#include "Creature.h"
class HarryPotter : public Creature
{
protected:
int hogwarts; // for
SPECIAL ABILITY
public:
void setData();
int attack();
void defense(int
d);
string getName();
bool isDead();
int attackRoll();
int defenseRoll();
int getArmor();
int getStrength();
~HarryPotter() {}
};
#endif // HARRYPOTTER_H
//Medusa.cpp
#include "Medusa.h"
void Medusa::setData(){
name = "Medusa";
armor = 3;
strength = 8;
dead = false;
}
int Medusa::attack(){
int damage = attackRoll();
if (damage == 12){ // SPECIAL ABLITY
cout << "Medusa
rolled a 12! Opponent has looked in Medusa's eyes and turned to
stone!" << endl;
damage = 999;
}else if(damage != 12){
cout << "Medusa
attacks! Medusa generated " << damage << " damage
points to opponent..." << endl;
}
return damage;
}
void Medusa::defense(int d){
int defense = defenseRoll();
int damage;
if (d != 999){
cout << "Medusa
attempts to defend! Medusa generated " << defense << "
defense points. " << endl;
damage = d -
defense;
}
else
damage = d;
if (damage <= 0){
cout << "Medusa
defends! No change in armor and strength." << endl;
cout << "Remaining
armor points: " << armor << endl;
cout << "Remaining
strength points: " << strength << endl;
}else if (damage > 0 && damage <=
armor){
armor = armor -
damage;
cout << "Medusa's
armor absorbed the attack! " << endl;
cout << "Remaining
armor points: " << armor << endl;
cout << "Remaining
strength points: " << strength << endl;
}else if (damage == 999){
cout << "Medusa
Dies! Medusa looked into other Medusa's eyes and turned to stone!"
<< endl;
cout << "Armor
points: 0" << endl;
cout << "Strength
points: 0" << endl;
dead = true;
}else if (damage > armor){
damage = damage -
armor;
strength = strength -
damage;
armor = 0;
if (strength >
0){
cout << "Medusa gets hurt but survives! " <<
endl;
cout << "Remaining armor points: " << armor <<
endl;
cout << "Remaining strength points: " << strength
<< endl;
}else if(strength <=
0){
cout << "Medusa Dies! Defense not strong enough!" <<
endl;
cout << "Armor points: " << armor << endl;
cout << "Strength points: " << strength <<
endl;
dead = true; // vampire dies!
}
}
}
string Medusa::getName(){
return name;
}
bool Medusa::isDead(){
return dead;
}
int Medusa::attackRoll(){
int roll = rand() % 6 + 1; // generate random
number within 6
roll = roll + (rand() % 6 + 1); // 2nd dice
roll, add together
return roll;
}
int Medusa::defenseRoll(){
int roll = rand() % 6 + 1; // generate random
number within 6
return roll;
}
int Medusa::getArmor(){
return armor;
}
int Medusa::getStrength(){
return strength;
}
//Medusa.h
#ifndef MEDUSA_H
#define MEDUSA_H
#include "Creature.h"
class Medusa : public Creature
{
protected:
public:
void setData();
int attack();
void defense(int
d);
string getName();
bool isDead();
int attackRoll();
int defenseRoll();
int getArmor();
int getStrength();
~Medusa() {}
};
#endif // MEDUSA_H
//Vampire.cpp
#include "Vampire.h"
void Vampire::setData(){
name = "Vampire";
armor = 1;
strength = 18;
dead = false;
}
int Vampire::attack(){
int damage = attackRoll();
cout << "Vampire attacks! Vampire
generated " << damage << " damage points to
opponent..." << endl;
return damage;
}
void Vampire::defense(int d){
int charm = rand() % 2 + 1; // determine if
vampire charmed opponent into not attacking, 50% chance opponent
does not attack
if (charm == 1){ // SPECIAL ABILITY
cout << "Vampire
charmed opponent into not attacking! Vampire takes no damage."
<< endl;
cout << "Remaining
armor points: " << armor << endl;
cout << "Remaining
strength points: " << strength << endl;
}else{
int defense =
defenseRoll();
int damage;
if (d != 999){
cout << "Vampire attempts to defend! Vampire generated "
<< defense << " defense points. " << endl;
damage = d - defense;
}
else
damage = d;
if (damage <=
0){
cout << "Vampire defends! No change in armor and strength."
<< endl;
cout << "Remaining armor points: " << armor <<
endl;
cout << "Remaining strength points: " << strength
<< endl;
}else if (damage ==
armor){
armor = armor - damage;
cout << "Vampire armor absorbed the attack! " <<
endl;
cout << "Remaining armor points: " << armor <<
endl;
cout << "Remaining strength points: " << strength
<< endl;
}else if (damage ==
999){
cout << "Vampire Dies! Vampire looked into Medusa's eyes and
turned to stone!" << endl;
cout << "Armor points: 0" << endl;
cout << "Strength points: 0" << endl;
dead = true; // vampire dies!
}else if (damage >
armor){
damage = damage - armor;
strength = strength - damage;
armor = 0;
if (strength > 0){
cout << "Vampire gets hurt but survives! " <<
endl;
cout << "Remaining armor points: " << armor <<
endl;
cout << "Remaining strength points: " << strength
<< endl;
}else if(strength <= 0){
cout << "Vampire Dies! Defense not strong enough!" <<
endl;
cout << "Armor points: " << armor << endl;
cout << "Strength points: " << strength <<
endl;
dead = true; // vampire dies!
}
}
}
}
string Vampire::getName(){
return name;
}
bool Vampire::isDead(){
return dead;
}
int Vampire::attackRoll(){
int roll = rand() % 12 + 1; // generate random
number within 12
return roll;
}
int Vampire::defenseRoll(){
int roll = rand() % 6 + 1; // generate random
number within 6
return roll;
}
int Vampire::getArmor(){
return armor;
}
int Vampire::getStrength(){
return strength;
}
note: due to limited character i cant able to include following
files
Vampire.h, Functions.cpp, BlueMen.h, Creature.cpp, Barbarian.h