mirror of https://github.com/string1995/eee102.git
parent
ff70b6f43c
commit
e83e9bb1b5
9 changed files with 566 additions and 3 deletions
@ -0,0 +1,50 @@ |
||||
//=======================
|
||||
// container.cpp
|
||||
//=======================
|
||||
|
||||
// default constructor initialise the inventory as empty
|
||||
container::container() |
||||
{ |
||||
set(0,0); |
||||
} |
||||
|
||||
// set the item numbers
|
||||
void container::set(int heal_n, int mw_n) |
||||
{ |
||||
numOfHeal=heal_n; |
||||
numOfMW=mw_n; |
||||
} |
||||
|
||||
// get the number of heal
|
||||
int container::nOfHeal() |
||||
{ |
||||
return numOfHeal; |
||||
} |
||||
|
||||
// get the number of magic water
|
||||
int container::nOfMW() |
||||
{ |
||||
return numOfMW; |
||||
} |
||||
|
||||
// display the items;
|
||||
void container::display() |
||||
{ |
||||
cout<<"Your bag contains: "<<endl; |
||||
cout<<"Heal(HP+100): "<<numOfHeal<<endl; |
||||
cout<<"Magic Water (MP+80): "<<numOfMW<<endl; |
||||
} |
||||
|
||||
//use heal
|
||||
bool container::useHeal() |
||||
{ |
||||
2_???????? |
||||
return 1; // use heal successfully
|
||||
} |
||||
|
||||
//use magic water
|
||||
bool container::useMW() |
||||
{ |
||||
numOfMW--; |
||||
return 1; // use magic water successfully
|
||||
} |
@ -0,0 +1,26 @@ |
||||
//=======================
|
||||
// container.h
|
||||
//=======================
|
||||
|
||||
// The so-called inventory of a player in RPG games
|
||||
// contains two items, heal and magic water
|
||||
|
||||
1_????????????? // Conditional compilation
|
||||
#define _CONTAINER |
||||
|
||||
class container // Inventory
|
||||
{ |
||||
protected: |
||||
int numOfHeal; // number of heal
|
||||
int numOfMW; // number of magic water
|
||||
public: |
||||
container(); // constuctor
|
||||
void set(int heal_n, int mw_n); // set the items numbers
|
||||
int nOfHeal(); // get the number of heal
|
||||
int nOfMW(); // get the number of magic water
|
||||
void display(); // display the items;
|
||||
bool useHeal(); // use heal
|
||||
bool useMW(); // use magic water
|
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,113 @@ |
||||
//=======================
|
||||
// main.cpp
|
||||
//=======================
|
||||
|
||||
// main function for the RPG style game
|
||||
|
||||
#include <iostream> |
||||
#include <string> |
||||
using namespace std; |
||||
|
||||
#include "swordsman.h" |
||||
|
||||
|
||||
int main() |
||||
{ |
||||
string tempName; |
||||
bool success=0; //flag for storing whether operation is successful
|
||||
cout <<"Please input player's name: "; |
||||
cin >>tempName; // get player's name from keyboard input
|
||||
player *human; // use pointer of base class, convenience for polymorphism
|
||||
int tempJob; // temp choice for job selection
|
||||
do |
||||
{ |
||||
cout <<"Please choose a job: 1 Swordsman, 2 Archer, 3 Mage"<<endl; |
||||
cin>>tempJob; |
||||
system("cls"); // clear the screen
|
||||
switch(tempJob) |
||||
{ |
||||
case 1: |
||||
human=new swordsman(1,tempName); // create the character with user inputted name and job
|
||||
success=1; // operation succeed
|
||||
break; |
||||
default: |
||||
break; // In this case, success=0, character creation failed
|
||||
} |
||||
}while(success!=1); // so the loop will ask user to re-create a character
|
||||
|
||||
int tempCom; // temp command inputted by user
|
||||
int nOpp=0; // the Nth opponent
|
||||
for(int i=1;nOpp<5;i+=2) // i is opponent's level
|
||||
{ |
||||
nOpp++; |
||||
system("cls"); |
||||
cout<<"STAGE" <<nOpp<<endl; |
||||
cout<<"Your opponent, a Level "<<i<<" Swordsman."<<endl; |
||||
system("pause"); |
||||
swordsman enemy(i, "Warrior"); // Initialise an opponent, level i, name "Junior"
|
||||
human->reFill(); // get HP/MP refill before start fight
|
||||
|
||||
while(!human->death() && !enemy.death()) // no died
|
||||
{ |
||||
success=0; |
||||
while (success!=1) |
||||
{ |
||||
showinfo(*human,enemy); // show fighter's information
|
||||
cout<<"Please give command: "<<endl; |
||||
cout<<"1 Attack; 2 Special Attack; 3 Use Heal; 4 Use Magic Water; 0 Exit Game"<<endl; |
||||
cin>>tempCom; |
||||
switch(tempCom) |
||||
{ |
||||
case 0: |
||||
cout<<"Are you sure to exit? Y/N"<<endl; |
||||
char temp; |
||||
cin>>temp; |
||||
if(temp=='Y'||temp=='y') |
||||
return 0; |
||||
else |
||||
break; |
||||
case 1: |
||||
success=human->attack(enemy); |
||||
human->isLevelUp(); |
||||
enemy.isDead(); |
||||
break; |
||||
case 2: |
||||
success=human->specialatt(enemy); |
||||
human->isLevelUp(); |
||||
enemy.isDead(); |
||||
break; |
||||
case 3: |
||||
success=human->useHeal(); |
||||
break; |
||||
case 4: |
||||
success=human->useMW(); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
if(!enemy.death()) // If AI still alive
|
||||
enemy.AI(*human); |
||||
else // AI died
|
||||
{ |
||||
cout<<"YOU WIN"<<endl; |
||||
human->transfer(enemy); // player got all AI's items
|
||||
} |
||||
if (human->death()) |
||||
{ |
||||
system("cls"); |
||||
cout<<endl<<setw(50)<<"GAME OVER"<<endl; |
||||
6_??????????? // player is dead, program is getting to its end, what should we do here?
|
||||
system("pause"); |
||||
return 0; |
||||
} |
||||
} |
||||
} |
||||
7_????????? // You win, program is getting to its end, what should we do here?
|
||||
system("cls"); |
||||
cout<<"Congratulations! You defeated all opponents!!"<<endl; |
||||
system("pause"); |
||||
return 0; |
||||
} |
||||
|
||||
|
@ -0,0 +1,127 @@ |
||||
//=======================
|
||||
// player.cpp
|
||||
//=======================
|
||||
|
||||
|
||||
// character's HP and MP resume
|
||||
void player::reFill() |
||||
{ |
||||
HP=HPmax; // HP and MP fully recovered
|
||||
MP=MPmax; |
||||
} |
||||
|
||||
// report whether character is dead
|
||||
bool player::death() |
||||
{ |
||||
return playerdeath; |
||||
} |
||||
|
||||
// check whether character is dead
|
||||
void player::isDead() |
||||
{ |
||||
if(HP<=0) // HP less than 0, character is dead
|
||||
{ |
||||
cout<<name<<" is Dead." <<endl; |
||||
system("pause"); |
||||
playerdeath=1; // give the label of death value 1
|
||||
} |
||||
} |
||||
|
||||
// consume heal, irrelevant to job
|
||||
bool player::useHeal() |
||||
{ |
||||
if(bag.nOfHeal()>0) |
||||
{ |
||||
HP=HP+100; |
||||
if(HP>HPmax) // HP cannot be larger than maximum value
|
||||
HP=HPmax; // so assign it to HPmax, if necessary
|
||||
cout<<name<<" used Heal, HP increased by 100."<<endl; |
||||
bag.useHeal(); // use heal
|
||||
system("pause"); |
||||
return 1; // usage of heal succeed
|
||||
} |
||||
else // If no more heal in bag, cannot use
|
||||
{ |
||||
cout<<"Sorry, you don't have heal to use."<<endl; |
||||
system("pause"); |
||||
return 0; // usage of heal failed
|
||||
} |
||||
} |
||||
|
||||
// consume magic water, irrelevant to job
|
||||
bool player::useMW() |
||||
{ |
||||
if(bag.nOfMW()>0) |
||||
{ |
||||
MP=MP+100; |
||||
if(MP>MPmax) |
||||
MP=MPmax; |
||||
cout<<name<<" used Magic Water, MP increased by 100."<<endl; |
||||
bag.useMW(); |
||||
system("pause"); |
||||
return 1; // usage of magic water succeed
|
||||
} |
||||
else |
||||
{ |
||||
cout<<"Sorry, you don't have magic water to use."<<endl; |
||||
system("pause"); |
||||
return 0; // usage of magic water failed
|
||||
} |
||||
} |
||||
|
||||
// possess opponent's items after victory
|
||||
void player::transfer(player &p) |
||||
{ |
||||
cout<<name<<" got"<<p.bag.nOfHeal()<<" Heal, and "<<p.bag.nOfMW()<<" Magic Water."<<endl; |
||||
system("pause"); |
||||
3_??????????? |
||||
// set the character's bag, get opponent's items
|
||||
} |
||||
|
||||
// display character's job
|
||||
void player::showRole() |
||||
{ |
||||
switch(role) |
||||
{ |
||||
case sw: |
||||
cout<<"Swordsman"; |
||||
break; |
||||
case ar: |
||||
cout<<"Archer"; |
||||
break; |
||||
case mg: |
||||
cout<<"Mage"; |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
|
||||
// display character's job
|
||||
4_??????????????
|
||||
{ |
||||
system("cls"); |
||||
cout<<"##############################################################"<<endl; |
||||
cout<<"# Player"<<setw(10)<<p1.name<<" LV. "<<setw(3) <<p1.LV |
||||
<<" # Opponent"<<setw(10)<<p2.name<<" LV. "<<setw(3) <<p2.LV<<" #"<<endl; |
||||
cout<<"# HP "<<setw(3)<<(p1.HP<=999?p1.HP:999)<<'/'<<setw(3)<<(p1.HPmax<=999?p1.HPmax:999) |
||||
<<" | MP "<<setw(3)<<(p1.MP<=999?p1.MP:999)<<'/'<<setw(3)<<(p1.MPmax<=999?p1.MPmax:999) |
||||
<<" # HP "<<setw(3)<<(p2.HP<=999?p2.HP:999)<<'/'<<setw(3)<<(p2.HPmax<=999?p2.HPmax:999) |
||||
<<" | MP "<<setw(3)<<(p2.MP<=999?p2.MP:999)<<'/'<<setw(3)<<(p2.MPmax<=999?p2.MPmax:999)<<" #"<<endl; |
||||
cout<<"# AP "<<setw(3)<<(p1.AP<=999?p1.AP:999) |
||||
<<" | DP "<<setw(3)<<(p1.DP<=999?p1.DP:999) |
||||
<<" | speed "<<setw(3)<<(p1.speed<=999?p1.speed:999) |
||||
<<" # AP "<<setw(3)<<(p2.AP<=999?p2.AP:999) |
||||
<<" | DP "<<setw(3)<<(p2.DP<=999?p2.DP:999) |
||||
<<" | speed "<<setw(3)<<(p2.speed<=999?p2.speed:999)<<" #"<<endl; |
||||
cout<<"# EXP"<<setw(7)<<p1.EXP<<" Job: "<<setw(7); |
||||
p1.showRole(); |
||||
cout<<" # EXP"<<setw(7)<<p2.EXP<<" Job: "<<setw(7); |
||||
p2.showRole(); |
||||
cout<<" #"<<endl; |
||||
cout<<"--------------------------------------------------------------"<<endl; |
||||
p1.bag.display(); |
||||
cout<<"##############################################################"<<endl; |
||||
} |
||||
|
@ -0,0 +1,52 @@ |
||||
//=======================
|
||||
// player.h
|
||||
//=======================
|
||||
|
||||
// The base class of player
|
||||
// including the general properties and methods related to a character
|
||||
|
||||
#ifndef _PLAYER |
||||
#define _PLAYER |
||||
|
||||
#include <iomanip> // use for setting field width |
||||
#include <time.h> // use for generating random factor |
||||
#include "container.h" |
||||
|
||||
enum job {sw, ar, mg}; /* define 3 jobs by enumerate type
|
||||
sword man, archer, mage */ |
||||
class player |
||||
{ |
||||
friend void showinfo(player &p1, player &p2); |
||||
friend class swordsman; |
||||
|
||||
protected: |
||||
int HP, HPmax, MP, MPmax, AP, DP, speed, EXP, LV; |
||||
// General properties of all characters
|
||||
string name; // character name
|
||||
job role; /* character's job, one of swordman, archer and mage,
|
||||
as defined by the enumerate type */ |
||||
container bag; // character's inventory
|
||||
|
||||
public: |
||||
virtual bool attack(player &p)=0; // normal attack
|
||||
virtual bool specialatt(player &p)=0; //special attack
|
||||
virtual void isLevelUp()=0; // level up judgement
|
||||
/* Attention!
|
||||
These three methods are called "Pure virtual functions". |
||||
They have only declaration, but no definition. |
||||
The class with pure virtual functions are called "Abstract class", which can only be used to inherited, but not to constructor objects.
|
||||
The detailed definition of these pure virtual functions will be given in subclasses. */ |
||||
|
||||
void reFill(); // character's HP and MP resume
|
||||
bool death(); // report whether character is dead
|
||||
void isDead(); // check whether character is dead
|
||||
bool useHeal(); // consume heal, irrelevant to job
|
||||
bool useMW(); // consume magic water, irrelevant to job
|
||||
void transfer(player &p); // possess opponent's items after victory
|
||||
void showRole(); // display character's job
|
||||
|
||||
private: |
||||
bool playerdeath; // whether character is dead, doesn't need to be accessed or inherited
|
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,155 @@ |
||||
//=======================
|
||||
// swordsman.cpp
|
||||
//=======================
|
||||
|
||||
// constructor. default values don't need to be repeated here
|
||||
swordsman::swordsman(int lv_in, string name_in) |
||||
{ |
||||
role=sw; // enumerate type of job
|
||||
LV=lv_in; |
||||
name=name_in; |
||||
|
||||
// Initialising the character's properties, based on his level
|
||||
HPmax=150+8*(LV-1); // HP increases 8 point2 per level
|
||||
HP=HPmax; |
||||
MPmax=75+2*(LV-1); // MP increases 2 points per level
|
||||
MP=MPmax; |
||||
AP=25+4*(LV-1); // AP increases 4 points per level
|
||||
DP=25+4*(LV-1); // DP increases 4 points per level
|
||||
speed=25+2*(LV-1); // speed increases 2 points per level
|
||||
|
||||
playerdeath=0; |
||||
EXP=LV*LV*75; |
||||
bag.set(lv_in, lv_in); |
||||
} |
||||
|
||||
void swordsman::isLevelUp() |
||||
{ |
||||
if(EXP>=LV*LV*75) |
||||
{ |
||||
LV++; |
||||
AP+=4; |
||||
DP+=4; |
||||
HPmax+=8; |
||||
MPmax+=2; |
||||
speed+=2; |
||||
cout<<name<<" Level UP!"<<endl; |
||||
cout<<"HP improved 8 points to "<<HPmax<<endl; |
||||
cout<<"MP improved 2 points to "<<MPmax<<endl; |
||||
cout<<"Speed improved 2 points to "<<speed<<endl; |
||||
cout<<"AP improved 4 points to "<<AP<<endl; |
||||
cout<<"DP improved 5 points to "<<DP<<endl; |
||||
system("pause"); |
||||
isLevelUp(); // recursively call this function, so the character can level up multiple times if got enough exp
|
||||
} |
||||
} |
||||
|
||||
bool swordsman::attack(player &p) |
||||
{ |
||||
double HPtemp=0; // opponent's HP decrement
|
||||
double EXPtemp=0; // player obtained exp
|
||||
double hit=1; // attach factor, probably give critical attack
|
||||
srand((unsigned)time(NULL)); // generating random seed based on system time
|
||||
|
||||
// If speed greater than opponent, you have some possibility to do double attack
|
||||
if ((speed>p.speed) && (rand()%100<(speed-p.speed))) // rand()%100 means generates a number no greater than 100
|
||||
{ |
||||
HPtemp=(int)((1.0*AP/p.DP)*AP*5/(rand()%4+10)); // opponent's HP decrement calculated based their AP/DP, and uncertain chance
|
||||
cout<<name<<"'s quick strike hit "<<p.name<<", "<<p.name<<"'s HP decreased "<<HPtemp<<endl; |
||||
p.HP=int(p.HP-HPtemp); |
||||
EXPtemp=(int)(HPtemp*1.2); |
||||
} |
||||
|
||||
// If speed smaller than opponent, the opponent has possibility to evade
|
||||
if ((speed<p.speed) && (rand()%50<1)) |
||||
{ |
||||
cout<<name<<"'s attack has been evaded by "<<p.name<<endl; |
||||
system("pause"); |
||||
return 1; |
||||
} |
||||
|
||||
// 10% chance give critical attack
|
||||
if (rand()%100<=10) |
||||
{ |
||||
hit=1.5; |
||||
cout<<"Critical attack: "; |
||||
} |
||||
|
||||
// Normal attack
|
||||
HPtemp=(int)((1.0*AP/p.DP)*AP*5/(rand()%4+10)); |
||||
cout<<name<<" uses bash, "<<p.name<<"'s HP decreases "<<HPtemp<<endl; |
||||
EXPtemp=(int)(EXPtemp+HPtemp*1.2); |
||||
p.HP=(int)(p.HP-HPtemp); |
||||
cout<<name<<" obtained "<<EXPtemp<<" experience."<<endl; |
||||
EXP=(int)(EXP+EXPtemp); |
||||
system("pause"); |
||||
return 1; // Attack success
|
||||
} |
||||
|
||||
bool swordsman::specialatt(player &p) |
||||
{ |
||||
if(MP<40) |
||||
{ |
||||
cout<<"You don't have enough magic points!"<<endl; |
||||
system("pause"); |
||||
return 0; // Attack failed
|
||||
} |
||||
else |
||||
{ |
||||
MP-=40; // consume 40 MP to do special attack
|
||||
|
||||
//10% chance opponent evades
|
||||
if(rand()%100<=10) |
||||
{ |
||||
cout<<name<<"'s leap attack has been evaded by "<<p.name<<endl; |
||||
system("pause"); |
||||
return 1; |
||||
} |
||||
|
||||
double HPtemp=0;
|
||||
double EXPtemp=0;
|
||||
//double hit=1;
|
||||
//srand(time(NULL));
|
||||
HPtemp=(int)(AP*1.2+20); // not related to opponent's DP
|
||||
EXPtemp=(int)(HPtemp*1.5); // special attack provides more experience
|
||||
cout<<name<<" uses leap attack, "<<p.name<<"'s HP decreases "<<HPtemp<<endl; |
||||
cout<<name<<" obtained "<<EXPtemp<<" experience."<<endl; |
||||
p.HP=(int)(p.HP-HPtemp); |
||||
EXP=(int)(EXP+EXPtemp); |
||||
system("pause"); |
||||
} |
||||
return 1; // special attack succeed
|
||||
} |
||||
|
||||
// Computer opponent
|
||||
void swordsman::AI(player &p) |
||||
{ |
||||
if ((HP<(int)((1.0*p.AP/DP)*p.AP*1.5))&&(HP+100<=1.1*HPmax)&&(bag.nOfHeal()>0)&&(HP>(int)((1.0*p.AP/DP)*p.AP*0.5))) |
||||
// AI's HP cannot sustain 3 rounds && not too lavish && still has heal && won't be killed in next round
|
||||
{ |
||||
useHeal(); |
||||
} |
||||
else |
||||
{ |
||||
if(MP>=40 && HP>0.5*HPmax && rand()%100<=30) |
||||
// AI has enough MP, it has 30% to make special attack
|
||||
{ |
||||
specialatt(p); |
||||
p.isDead(); // check whether player is dead
|
||||
} |
||||
else |
||||
{ |
||||
if (MP<40 && HP>0.5*HPmax && bag.nOfMW()) |
||||
// Not enough MP && HP is safe && still has magic water
|
||||
{ |
||||
useMW(); |
||||
} |
||||
else |
||||
{ |
||||
attack(p); // normal attack
|
||||
p.isDead(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,20 @@ |
||||
//=======================
|
||||
// swordsman.h
|
||||
//=======================
|
||||
|
||||
// Derived from base class player
|
||||
// For the job Swordsman
|
||||
|
||||
#include "player.h" |
||||
class swordsman : 5_????????? // subclass swordsman publicly inherited from base player
|
||||
{ |
||||
public: |
||||
swordsman(int lv_in=1, string name_in="Not Given");
|
||||
// constructor with default level of 1 and name of "Not given"
|
||||
void isLevelUp(); |
||||
bool attack (player &p); |
||||
bool specialatt(player &p); |
||||
/* These three are derived from the pure virtual functions of base class
|
||||
The definition of them will be given in this subclass. */ |
||||
void AI(player &p); // Computer opponent
|
||||
}; |
Loading…
Reference in new issue