task2
題目要求
源碼
main.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include "Person.hpp"
int main()
{
using namespace std;
vector<Person> phone_book;
Person p;
while(cin>>p)
phone_book.push_back(p);
for(auto &i: phone_book)
cout << i << endl;
cout << boolalpha << (phone_book.at(0) == phone_book.at(1)) << endl;
phone_book.at(0).changeEmail();
phone_book.at(0).changeTel();
for(auto &i: phone_book)
cout << i << endl;
ofstream fout;
fout.open("phone_book.txt");
if(!fout.is_open())
{
cerr << "fail to open file phone_book.txt\n";
return 1;
}
for(auto &i: phone_book)
fout << i << endl;
fout.close();
}
Person.hpp
#include <iostream>
#include <string>
#include <istream>
#include <ostream>
using namespace std;
class Person{
private:
string name, telephone, email;
public:
Person(){}
Person(string name, string telephone, string email=""){
this->name = name;
this->telephone = telephone;
this->email = email;
}
void changeEmail(){
cin.clear();
cout << "請輸入修改後的郵箱号碼:";
cin >> email;
}
void changeTel(){
cin.clear();
cout << "請輸入修改後的電話号碼:";
cin >> telephone;
}
friend ostream& operator<<(ostream& os, const Person &p){
os << p.name << "\t" << p.telephone << "\t" << p.email;
return os;
}
friend istream& operator>>(istream& os, Person &p){
os >> p.name >> p.telephone >> p.email;
return os;
}
friend bool operator==(const Person &p1, const Person &p2){
return (p1.name == p2.name && p1.telephone == p2.telephone);
}
};
運作截圖
總結
- 測試了兩個修改接口
task3
說明
- 進行填補和進一步的改進的基礎建立在需要從宏觀上了解整個項目的構成和邏輯關系,基本思路是通過
頭檔案中類提供的接口來判斷有哪些功能和互相調用的邏輯關系。.h
- 本來想進行漢化工作,但由于我的測試平台是在macOS,等寬字型的問題和win不能很好地适配
- 在基本的代碼填補後的測試中發現,遊戲存在部分平衡性問題和bug。在此基礎上進行了如下平衡性修改:
- 增加了單次特殊攻擊魔力值消耗設定的接口
- 增加每次玩家和enemy操作後魔力值自動回複的功能(enemy恢複能力為玩家的一半)
- 删除了AI生命小于百分之五十情況下無法發動特殊攻擊的情況
- 修複了enemy發動特殊攻擊條件中的機率錯誤的bug,并調整為60%
- 改善了enemy的AI,能在等待一回合的自動恢複法力和使用法力藥水之間平衡
- 調整玩家每次更新後的生命、法力上限提升和速度提升幅度
- 增加了每次玩家更新後血量和法力值部分恢複的功能
- 調整AI使用物品的邏輯,防止擊敗enemy後大機率無法獲得獎勵物品
由于代碼過長,僅展示部分,其餘請右擊下列檔案儲存
main.cpp |player.h |player.cpp |container.h |container.cpp |swordsman.h |swordsman.cpp
//=======================
// main.cpp
//=======================
// main function for the RPG style game
#include <iostream>
#include <string>
using namespace std;
#include "swordsman.h"
int specialatt_consume = 40; // 單次發動特殊攻擊消耗的魔法值
int MP_autoResume = 10; // 每回合法力值自動回複點數
int main()
{
string tempName;
bool success=0; //flag for storing whether operation is successful
cout <<"Please input player's name: ";
************
************
player.h
//=======================
// 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"
#include <string>
#include <iostream>
using namespace std;
enum job {sw, ar, mg}; /* define 3 jobs by enumerate type
sword man, archer, mage */
class player
************
************
player.cpp
//=======================
// player.cpp
//=======================
extern int MP_autoResume;
// character's HP and MP resume
#include "player.h"
#include <iostream>
using namespace std;
void player::MPResume()
{
MP += MP_autoResume;
}
void player::reFill()
{
HP=HPmax; // HP and MP fully recovered
MP=MPmax;
}
************
************
container.h
//=======================
// container.h
//=======================
// The so-called inventory of a player in RPG games
// contains two items, heal and magic water
#ifndef _CONTAINER // 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
************
************
container.cpp
//=======================
// player.cpp
//=======================
extern int MP_autoResume;
// character's HP and MP resume
#include "player.h"
#include <iostream>
using namespace std;
void player::MPResume()
{
MP += MP_autoResume;
}
void player::reFill()
{
HP=HPmax; // HP and MP fully recovered
MP=MPmax;
}
************
************
swordsman.h
//=======================
// swordsman.h
//=======================
// Derived from base class player
// For the job Swordsman
#include "player.h"
#include <iostream>
using namespace std;
class swordsman : public player // 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
};
swordsman.cpp
//=======================
// swordsman.cpp
//=======================
// constructor. default values don't need to be repeated here
extern int specialatt_consume;
extern int MP_autoResume;
#include "swordsman.h"
#include <iostream>
using namespace std;
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
************
************
運作結果
- 請自行build測試或直接下載下傳打封包件
macOS環境需将main.cpp中所有cls替換為clear
- 依舊是對于基類與派生類的邏輯關系需要厘清