CCF认证2016093-炉石传说

本人初学,水平有限,若有不足,恳请赐教!

这道题应该是到目前为止我做过的最简单的第三题。本题没有什么复杂的算法和数据结构的设计,只需要根据要求自定义数据结构即可。我的思路是先设计随从类型,其属性包括攻击力和生命值。然后再设计英雄类型,其属性包括生命值和随从链表。召唤随从和攻击的操作进而变成了链表的操作。操作格式的判断可以使用正则表达式。

具体代码如下:

#include <iostream>
#include <list>
#include <vector>
#include <regex>

using namespace std;

typedef struct SUMMON //随从
{
	int attack;
	int health;
	SUMMON(int a, int h) :attack(a), health(h) {}
}SUMMON;

typedef struct HERO //英雄
{
	int health = 30;
	list<SUMMON> summons;
}HERO;

int main()
{
	//FILE *stream;
	//freopen_s(&stream, "data.txt", "r", stdin);

	int n;
	cin >> n;
	getchar();
	vector<HERO> h(2); //双方玩家,h[0]和h[1]分别代表先手和后手
	h[0].summons.push_back(SUMMON(INT_MAX, INT_MAX)); //插入一个无关的结点方便后续的定位
	h[1].summons.push_back(SUMMON(INT_MAX, INT_MAX));
	int cur = 0; //当前下达命令的玩家编号,从先手开始
	regex pa("attack ([\\d]+) ([\\d]+)");
	regex ps("summon ([\\d]+) ([\\d]+) ([\\d]+)");
	regex pe("end");
	smatch result;
	while(n--)
	{
		string cmd;
		getline(cin, cmd);
		if(regex_match(cmd, result, pe)) cur = (cur + 1) % 2; //回合结束
		else if(regex_match(cmd, result, ps)) //召唤随从
		{
			int pos = stoi(result[1]), attack = stoi(result[2]), health = stoi(result[3]);
			SUMMON s(attack, health);
			auto point = h[cur].summons.begin();
			for(; pos > 0; pos--)
				point++;
			h[cur].summons.insert(point, s);
		}
		else if(regex_match(cmd, result, pa)) //攻击
		{
			int enemy = (cur + 1) % 2;
			int poscur = stoi(result[1]), posenemy = stoi(result[2]); //攻防位置
			if(posenemy != 0) //攻击随从
			{
				auto pointa = h[cur].summons.begin();
				auto pointb = h[enemy].summons.begin();
				for(; poscur > 0; poscur--) pointa++;
				for(; posenemy > 0; posenemy--) pointb++;
				(*pointa).health -= (*pointb).attack;
				(*pointb).health -= (*pointa).attack;
				if((*pointa).health <= 0) h[cur].summons.erase(pointa);
				if((*pointb).health <= 0) h[enemy].summons.erase(pointb);
			}
			else //攻击英雄
			{
				auto pointa = h[cur].summons.begin();
				for(; poscur > 0; poscur--) pointa++;
				h[enemy].health -= (*pointa).attack;
			}
		}
	}
	if(h[0].health > 0 && h[1].health > 0) cout << 0 << endl;
	else if(h[0].health > 0) cout << 1 << endl;
	else if(h[1].health > 0) cout << -1 << endl;
	for(auto e : h)
	{
		cout << e.health << endl;
		cout << e.summons.size() - 1 << ' ';
		auto iter = e.summons.begin();
		iter++;
		while(iter != e.summons.end())
		{
			cout << (*iter).health << ' ';
			iter++;
		}
		cout << endl;
	}

	//fclose(stream);

	return 0;
}

实际上代码还可以进一步优化,那就是将英雄和随从统一看待,用一个vector<pair<int,int>>来存放英雄和该英雄的随从。这样英雄的位置自然就成了哨兵,不必再像代码中那样再插入一个无关结点。而且在攻击操作时也可以将对随从和对英雄的攻击操作统一。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值