1. 程式人生 > >【open judge】【程設】魔獸世界三開戰!

【open judge】【程設】魔獸世界三開戰!

#程設 魔獸世界三---開戰!

--------

原以為會很容易ac,沒想到寫了好久,看來自己的水平還是亟待提高啊!

有幾個比較有趣的點:

1. typeid(#include<typeinfo>)還是比較好用的,特別是本題當戰士為wolf,iceman, dragon, ninja時有特殊技能,那麼用typeid判斷一下就很方便了。

2. 對於這種輸出很複雜的問題,往往通過使用檔案的輸入輸出再進行比較的做法debug。我在網上下了一個Beyond Compare進行比較,還是蠻好用的。

3. printf()在大多數情況下都比cout好用,我基本上都用cout處理的,感覺寫的有點複雜。

程式碼如下,僅供參考

#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<typeinfo>
using namespace std;

int soldier_HP[5];
char soldier_name[5][20] = {"iceman", "lion", "wolf", "ninja", "dragon"};
char weapon_name[3][20] = {"sword", "bomb", "arrow"};
int soldier_force[5];
int city_number, time_limited;

//different soldier class
//model class
class csoldier
{
public:
    int HP, force, locate, id;
	int weapon[4];
	int weapen_amount;
	csoldier() { memset(weapon, 0, sizeof(weapon)); }
    virtual ~csoldier(){}

//第n次交手應該使用的武器,n已經考慮過經過迴圈處理
	int getweapon(int &n)
	{
	    bool flag = false;
	    if (weapen_amount <= n) flag = true;
		if (n <= weapon[0])
		{
			++n;
			if(flag) n = 1;
			return 0;
		}
		else if (n <= weapon[0] + weapon[1])
		{
			weapon[1]--;
			weapen_amount--;
			if(flag) n = 1;
			return 1;
		}
		else if (n <= weapon[3] + weapon[0] + weapon[1])
		{
			weapon[3]--;
			weapen_amount--;
			if(flag) n = 1;
			return 2;
		}
		else if (n <= weapen_amount)
		{

			weapon[2]--;
			weapon[3]++;
			++n;
			if(flag) n = 1;
			return 2;
		}
		cout << "wrong!" << endl;
	}
	virtual void out_name() = 0;
    friend class battlefield;
};

class dragon:public csoldier
{
private:
    friend class battlefield;
    //constructor
    dragon(int n, int color):csoldier()
    {
        weapon[n % 3] = 1;
		weapen_amount = 1;
		force = soldier_force[4];
		locate = ((color == 0)? 0 : city_number + 1);
		HP = soldier_HP[4];
		id = n;
    }
    //destructor
    ~dragon(){}
	virtual void out_name()
	{
		cout << "dragon " << id;
	}
};

class ninja:public csoldier
{
private:
    friend class battlefield;
	ninja(int n, int color) :csoldier()
	{
		weapon[n % 3] = 1;
		weapon[(n + 1) % 3] = 1;
		weapen_amount = 2;
		force = soldier_force[3];
		locate = ((color == 0) ? 0 : city_number + 1);
		HP = soldier_HP[3];
		id = n;
	}
    ~ninja(){}
	virtual void out_name()
	{
		cout << "ninja " << id;
	}
};

class iceman:public csoldier
{
private:
    friend class battlefield;
	iceman(int n, int color) :csoldier()
	{
		weapon[(n % 3)] = 1;
		weapen_amount = 1;
		force = soldier_force[0];
		locate = ((color == 0) ? 0 : city_number + 1);
		HP = soldier_HP[0];
		id = n;
	}
	virtual void out_name()
	{
		cout << "iceman " << id;
	}
};

class lion:public csoldier
{
private:
    friend class battlefield;
    int loyalty;
	lion(int n, int color, int hp) :csoldier(), loyalty(hp)
	{
		weapon[n % 3] = 1;
		weapen_amount = 1;
		force = soldier_force[1];
		locate = ((color == 0) ? 0 : city_number + 1);
		HP = soldier_HP[1];
		id = n;
		cout << "Its loyalty is " << loyalty << endl;
	}
	virtual void out_name()
	{
		cout << "lion " << id;
	}
public:
	static int K;
};
int lion::K = 0;

class wolf:public csoldier
{
	wolf(int n, int color) :csoldier()
	{
		weapen_amount = 0;
		force = soldier_force[2];
		locate = ((color == 0) ? 0 : city_number + 1);
		HP = soldier_HP[2];
		id = n;
	}
	virtual void out_name()
	{
		cout << "wolf " << id;
	}
private:
    friend class battlefield;
};

class battlefield
{
private:
    int hour, minute, soldier_total[2], cur[2];
    int HP[2];
    char name[2][20];
    bool produce_end[2];//if production is carrying on, it is false, if else it is true
    csoldier ***head;
    int soldier[5];//in the order of iceman¡¢lion¡¢wolf¡¢ninja¡¢dragon
public:
	int arr[2][5] = { {0, 1, 2, 3, 4} ,{1, 4, 3, 0, 2} };
    //int arr[5] = {1, 4, 3, 0, 2};
	battlefield(int n) :HP{ n, n}, hour(0), minute(0), produce_end{ true,true }
    {
		soldier_total[0] = soldier_total[1] = 0;
		cur[0] = cur[1] = -1;
		strcpy(name[0], "red");
		strcpy(name[1], "blue");
        memset(soldier, 0, sizeof(soldier));
		head = new csoldier** [city_number + 2];
		for (int i = 0; i < city_number + 2; ++i)
		{
			head[i] = new csoldier*[4];
			memset(head[i], NULL, sizeof(csoldier*) * 4);
		}
    }
	//輸出當前時間
    void out_time()
    {
        cout << setfill('0') << setw(3) << hour << ':' << setfill('0') << setw(2) << minute;
		return;
    }

	//base produce soldiers. if base produce soldier sucessfully, return true;if else return false;
    bool produce(int color)
    {
        if(produce_end[color] == false)
            return false;
        cur[color] = (cur[color] + 1) % 5;
        int t = arr[color][cur[color]];
        if(HP[color] >= soldier_HP[t])
        {
            HP[color] -= soldier_HP[t];
            soldier[t]++;
            soldier_total[color]++;
			out_time();
			cout << ' ' << name[color] << ' ' << soldier_name[t] << ' ' << soldier_total[color] << " born"<< endl;
			int pos = ((color == 0) ? 0 : city_number + 1);
            switch(t)
            {
                case 0: head[pos][color] = new iceman(soldier_total[color], color);break;
                case 1: head[pos][color] = new lion(soldier_total[color], color, HP[color]);break;
                case 2: head[pos][color] = new wolf(soldier_total[color], color);break;
                case 3: head[pos][color] = new ninja(soldier_total[color], color);break;
                case 4: head[pos][color] = new dragon(soldier_total[color], color);break;
            }
            return true;
        }
        else
        {
			produce_end[color] = false;
			return false;
        }
    }
	//renew location
	void clear()
	{
		for (int i = 0; i <= city_number + 1; ++i)
		{
			head[i][0] = head[i][2];
			head[i][1] = head[i][3];
			head[i][2] = head[i][3] = NULL;
		}
		return;
	}

	//soldiers start moving
	bool march()
	{
		bool flag = true;

		if (head[1][1] != NULL)
		{
			if (typeid(*head[1][1]) == typeid(iceman))
				head[1][1]->HP -= head[1][1]->HP / 10;
			out_time();
			cout << " blue "; head[1][1]->out_name();
			printf(" reached red headquarter with %d elements and force %d\n", head[1][1]->HP, head[1][1]->force);
			head[0][3] = head[1][1];
			out_time();
			cout << " red headquarter was taken" << endl;
			flag = false;
		}
		for (int i = 1; i <= city_number; ++i)
		{
			if (head[i - 1][0] != NULL)
			{
				if (typeid(*head[i - 1][0]) == typeid(iceman))
					head[i - 1][0]->HP -= head[i - 1][0]->HP / 10;
				out_time();
				cout << " red "; head[i - 1][0]->out_name();
				printf(" marched to city %d with %d elements and force %d\n",i, head[i-1][0]->HP, head[i-1][0]->force);
				head[i][2] = head[i - 1][0];
			}
			if (head[i + 1][1] != NULL)
			{
				if (typeid(*head[i + 1][1]) == typeid(iceman))
					head[i + 1][1]->HP -= head[i + 1][1]->HP / 10;
				out_time();
				cout << " blue "; head[i + 1][1]->out_name();
				printf(" marched to city %d with %d elements and force %d\n", i, head[i + 1][1]->HP, head[i + 1][1]->force);
				head[i][3] = head[i + 1][1];
			}
		}
		if (head[city_number][0] != NULL)
		{
			if (typeid(*head[city_number][0]) == typeid(iceman))
				head[city_number][0]->HP -= head[city_number][0]->HP / 10;
			out_time();
			cout << " red "; head[city_number][0]->out_name();
			printf(" reached blue headquarter with %d elements and force %d\n", head[city_number][0]->HP, head[city_number][0]->force);
			head[city_number + 1][2] = head[city_number][0];
			out_time();
			cout << " blue headquarter was taken" << endl;
			flag = false;
		}
		clear();
		return flag;
	}

	//judge whether lion run away
	void run_away()
	{
		for (int i = 0; i <= city_number + 1; ++i)
		{
			for (int t = 0; t < 2; ++t)
			{
				if (head[i][t] != NULL && typeid(*head[i][t]) == typeid(lion))
				{
					auto p = (lion *)head[i][t];
					if (p->loyalty <= 0)
					{
						out_time();
						cout << ' ' << name[t];
						cout << " lion " << head[i][t]->id << " ran away" << endl;
						delete head[i][t];
						head[i][t] = NULL;
						continue;
					}
					p->loyalty -= lion::K;
				}
			}

		}
		return;
	}

	//winner snatch loser's weapon
	void snatch_weapon(csoldier *p, csoldier *q)
	{
		for (int i = 0; i < 4; ++i)
		{
			while (q->weapon[i] > 0 && p->weapen_amount < 10)
			{
				p->weapon[i]++;
				q->weapon[i]--;
				p->weapen_amount++;
			}
		}
		return;
	}
    void out_weapen(int t)
    {
        switch(t)
        {
            case 0: cout << weapon_name[0];break;
            case 1: cout << weapon_name[1];break;
            case 2: cout << weapon_name[2];break;
            case 3: cout << weapon_name[2];break;
        }
        return;
    }
	//wolf snatch enemy's weapon
	void w_snatch_weapon(csoldier *p, csoldier *q)
	{
		//bool flag = true;

		int t = 0, s = 0;
		while (q->weapon[t] == 0)++t;
		if (10 - p->weapen_amount <= q->weapon[t])
		{
			p->weapon[t] += 10 - p->weapen_amount;
			s += 10 - p->weapen_amount;
			p->weapen_amount = 10;
			q->weapen_amount -= s;
			q->weapon[t] -= s;
			return;
		}
		else
		{
			p->weapon[t] += q->weapon[t];
			s += q->weapon[t];
			p->weapen_amount += q->weapon[t];
			q->weapon[t] -= s;
			q->weapen_amount -= s;
			if (t == 2 && q->weapon[3] > 0)
			{
				t = 3;
				if (10 - p->weapen_amount <= q->weapon[t])
				{
					p->weapon[t] += 10 - p->weapen_amount;
					s += 10 - p->weapen_amount;
					p->weapon[t] -= 10 - p->weapen_amount;
					p->weapen_amount -= 10 - p->weapen_amount;
					p->weapen_amount = 10;
				}
				else
				{
					p->weapon[t] += q->weapon[t];
					s += q->weapon[t];
					q->weapen_amount -= q->weapon[t];
					p->weapen_amount += q->weapon[t];
					q->weapon[t] = 0;
				}
			}
			cout << s << ' ';
            out_weapen(t);
			return;
		}
	}

	//wolf snatch enemy's weapon
	void snatch()
	{
		for (int i = 1; i <= city_number; ++i)
		{
			csoldier *p[2] = { head[i][0], head[i][1] };
			if (p[0] != NULL && p[1] != NULL)
			{

				if (typeid(*p[0]) != typeid(wolf) && typeid(*p[1]) != typeid(wolf))
					continue;
				else if (typeid(*p[0]) != typeid(wolf))
				{
				    if(p[0]->weapen_amount == 0 || p[1]->weapen_amount == 10)
                        continue;
					out_time(); cout << " blue ";p[1]->out_name();
					cout << " took ";
					w_snatch_weapon(p[1], p[0]);
					cout << " from red ";
					p[0]->out_name();cout << " in city " << i << endl;
				}
				else if (typeid(*p[1]) != typeid(wolf))
				{
				    if(p[1]->weapen_amount == 0 || p[0]->weapen_amount == 10)
                        continue;
					out_time(); cout << " red ";p[0]->out_name();
					cout << " took ";
					w_snatch_weapon(p[0], p[1]);
					cout << " from blue ";
					p[1]->out_name();cout << " in city " << i << endl;
				}
				else
					continue;

			}
		}
	}

	//fight
	void fight()
	{
		for (int i = 1; i <= city_number; ++i)
		{
			if (head[i][0] == NULL || head[i][1] == NULL)
				continue;
			int r = i % 2, L = r ^ 1, n[2] = {1, 1}, w, flag = 5, check[4] = {0}, cnt = 0;
			while (true)
			{
				//判斷是否局勢改變,若不改變則為平局
				r = r ^ 1;
				L = L ^ 1;
				if (cnt == 0)
				{
					if (check[0] == head[i][0]->HP && check[1] == head[i][1]->HP && check[2] == head[i][0]->weapen_amount && check[3] == head[i][1]->weapen_amount)
					{
						flag = 0;//all alive
						break;
					}
					check[0] = head[i][0]->HP;
					check[1] = head[i][1]->HP;
					check[2] = head[i][0]->weapen_amount;
					check[3] = head[i][1]->weapen_amount;
					cnt = 10;
				}
				cnt--;

				if (head[i][L]->weapen_amount == 0 && head[i][r]->weapen_amount == 0)
				{
					flag = 0;//alive
					break;
				}
				if(head[i][r]->weapen_amount == 0)
                    continue;
				w = head[i][r]->getweapon(n[r]);
//				if(head[i][1]->id == 10)
//				cout << r << ' ' << "use weapen " << w << " in city " << i <<n[r] << endl;
				int h;
				switch (w)
				{
				case 0:
					head[i][L]->HP -= head[i][r]->force / 5; break;
				case 1:
					h = head[i][r]->force * 2 / 5;
					head[i][L]->HP -= h;
					if(typeid(*head[i][r]) != typeid(ninja))
                        head[i][r]->HP -= h / 2;
					break;
				case 2:
					head[i][L]->HP -= head[i][r]->force * 3 / 10; break;
				default:
					break;
				}
				if (head[i][L]->HP <= 0 && head[i][r]->HP <= 0)
				{
					flag = 3;//all died
					break;
				}
				else if (head[i][L]->HP <= 0)
				{
					if (L == 0)
					{
						flag = 2; //blue win
						break;
					}
					else
					{
						flag = 1; //red win
						break;
					}
				}
				else if (head[i][r]->HP <= 0)
				{
					if (r == 0)
					{
						flag = 2; //blue win
						break;
					}
					else
					{
						flag = 1; //red win
						break;
					}
				}
			}
			out_time();
			switch (flag)
			{
			case 0:
				cout << " both red ";
				head[i][0]->out_name();
				cout << " and blue ";
				head[i][1]->out_name();
				cout << " were alive in city " << i << endl;
				break;
			case 3:
				cout << " both red ";
				head[i][0]->out_name();
				cout << " and blue ";
				head[i][1]->out_name();
				cout << " died in city " << i << endl;
				delete head[i][0];
				delete head[i][1];
				head[i][0] = NULL;
				head[i][1] = NULL;
				break;
			case 1:
				cout << " red ";
				head[i][0]->out_name();
				cout << " killed blue ";
				head[i][1]->out_name();
				printf(" in city %d remaining %d elements\n", i, head[i][0]->HP);
				snatch_weapon(head[i][0], head[i][1]);
				delete head[i][1];
				head[i][1] = NULL;
				break;
			case 2:
				cout << " blue ";
				head[i][1]->out_name();
				cout << " killed red ";
				head[i][0]->out_name();
				printf(" in city %d remaining %d elements\n", i, head[i][1]->HP);
				snatch_weapon(head[i][1], head[i][0]);
				delete head[i][0];
				head[i][0] = NULL;
				break;
			default:
				break;
			}
			for (int t = 0; t < 2; ++t)
			{
				if (head[i][t] != NULL && typeid(*head[i][t]) == typeid(dragon))
				{
					out_time(); cout << ' ' << name[t] << ' ';
					head[i][t]->out_name();
					cout << " yelled in city " << i << endl;
				}
			}

		}

	}

	//base report condition
	void base_report()
	{
		out_time();
		printf(" %d elements in red headquarter\n", HP[0]);
		out_time();
		printf(" %d elements in blue headquarter\n", HP[1]);
		return;
	}

	//soldier report
	void soldier_report()
	{
		for (int i = 0; i < city_number + 1; ++i)
		{
			for(int t = 0; t < 2; ++t)
				if (head[i][t] != NULL)
				{
					out_time();
					cout << ' ' << name[t] << ' ';
					head[i][t]->out_name();
					cout << " has " << head[i][t]->weapon[0] << " sword " << head[i][t]->weapon[1] << " bomb "
						<< head[i][t]->weapon[2] + head[i][t]->weapon[3] << " arrow and " << head[i][t]->HP << " elements" << endl;
				}
		}
		return;
	}

	//check whether time is legal
	bool check_time()
	{
		if (hour * 60 + minute > time_limited)
			return false;
		else
			return true;
	}

	bool run()
	{
		minute = 0;
		if (!check_time()) return false;

		produce(0);
		produce(1);

		minute = 5;
		if (!check_time()) return false;

		run_away();

		minute = 10;
		if (!check_time()) return false;

		if(!march())
			return false;

		minute = 35;
		if (!check_time()) return false;

		snatch();

		minute = 40;
		if (!check_time()) return false;

		fight();

		minute = 50;
		if (!check_time()) return false;
		base_report();

		minute = 55;
		if (!check_time()) return false;
		soldier_report();

		hour++;
		return true;
	}
};
int main()
{
    int n, hp, cnt = 0;
    cin >> n;
    while(n--)
    {
		cout << "Case " << ++cnt <<':'<< endl;
                cin >> hp >> city_number >> lion::K >> time_limited;
                battlefield Battle(hp);
                cin >> soldier_HP[4] >> soldier_HP[3] >> soldier_HP[0] >> soldier_HP[1] >> soldier_HP[2];
		cin >> soldier_force[4] >> soldier_force[3] >> soldier_force[0] >> soldier_force[1] >> soldier_force[2];
		while (Battle.run());

    }
    return 0;
}