程序设计-魔兽世界系列大作业(一)
项目OJ提交:魔兽世界-备战
课程地址:程序设计与算法(三)-C++程序设计
思路与类架构
Warrior类
有五种武士,分别是dragon 、ninja、iceman、lion、wolf,那么就可以抽象出一个武士类,具体的再实例化出对应的武士对象。
每个武士类,都有几个属性:类别(姓名),所属阵营,在该阵营的编号,武力值。然后具备一个方法,就是出生,出生是每个武士必备的过程。而本题的出生,即播报一条武士出生的信息。请根据题目要求写好出生播报的打印语句,要注意:武力值和编号之间,仅一个逗号,没有空格!
类架构中,要注意的是:
- 武力值和类别(姓名)是和阵营无关的;
- 阵营和阵营内的编号是阵营有关的。
因此,要先实例化阵营,后实例化武士,要在阵营中实现出生武士的方法,并且调用武士的出生过程。
Headquarter类
阵营类能被实例化成红蓝两个阵营,每个阵营都有的属性是:类别(姓名),生命元,武士出生顺序。
但是,为了能够生成武士,以及得到武士在阵营内的信息,还需要的属性是:当前武士的编号ID,统计武士在该阵营的数量。然后,红蓝两个阵营的生命元都是相同的。
在类架构中,需要注意的是:
- 当生命元不足以生成当前武士时,要顺延,要么后面的武士中有能生成的,要么所有武士都无法生成,触发生成终止的播报,并不再生成武士;
- 阵营和武士,是从属关系,是has的关系,阵营拥有武士,但是本题并未涉及到武士的动态变化,例如战斗,死亡等事件,因此未设计;
- 如果要设计,则需要有武士相关的成员变量,例如武士列表等。
C++代码实现
#include <cstdio>
#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
static
std::unordered_map<std::string, int> warriorStrength;
class Warrior {
private:
std::string name, camp;
int id, strength;
public:
Warrior(
const std::string& name_,
const std::string& camp_,
int id_, int strength_
) : name(name_), camp(camp_), id(id_), strength(strength_) { }
void born(int timeStamp, int numsInCamp) {
printf("%03d %s %s %d born with strength %d,"
"%d %s in %s headquarter\n", timeStamp, camp.c_str(),
name.c_str(), id, strength, numsInCamp, name.c_str(),
camp.c_str());
}
};
class Headquarter {
private:
std::string name;
std::vector<std::string> order;
std::unordered_map<std::string, int> cntWarrior;
int healthMeta, curID;
size_t curIdx;
public:
Headquarter(
const std::string& name_,
const std::vector<std::string>& order_,
int healthMeta_, int curID_ = 1, size_t curIdx_ = 0
) : name(name_), order(order_),
healthMeta(healthMeta_), curID(curID_), curIdx(curIdx_) { }
std::string getNextWarriorName() {
size_t orderSize = order.size();
for (size_t i = 0; i < orderSize; ++i) {
std::string curName = order[curIdx];
if (healthMeta >= warriorStrength[curName]) {
return curName;
}
curIdx = (curIdx + 1) % orderSize;
}
return "NULL";
}
bool bornWarrior(int timeStamp) {
std::string curName = getNextWarriorName();
if ("NULL" == curName) {
printf("%03d %s headquarter stops making warriors\n",
timeStamp, name.c_str());
return false;
}
int curStrength = warriorStrength[curName];
healthMeta -= curStrength;
int curNumsInCamp = ++cntWarrior[curName];
std::make_shared<Warrior>(
curName, name, curID, curStrength
)->born(timeStamp, curNumsInCamp);
curID++;
curIdx = (curIdx + 1) % order.size();
return true;
}
};
int main() {
int caseNums;
scanf("%d", &caseNums);
for (int cs = 1; cs <= caseNums; ++cs) {
int meta, dragon, ninja, iceman, lion, wolf;
scanf("%d%d%d%d%d%d", &meta, &dragon, &ninja,
&iceman, &lion, &wolf);
warriorStrength = {
{"dragon", dragon}, {"ninja", ninja}, {"iceman", iceman},
{"lion", lion}, {"wolf", wolf}
};
Headquarter red(
"red", { "iceman", "lion", "wolf", "ninja", "dragon" }, meta);
Headquarter blue(
"blue", { "lion", "dragon", "ninja", "iceman","wolf" }, meta);
printf("Case:%d\n", cs);
bool redOK = true, blueOK = true;
for (int curTime = 0; ; ++curTime) {
if (redOK) {
redOK = red.bornWarrior(curTime);
}
if (blueOK) {
blueOK = blue.bornWarrior(curTime);
}
if (!redOK && !blueOK) {
break;
}
}
}
return 0;
}