P7610 题解
I_am_kunzi · · 题解
P7610 题解
前言
写大模拟的题解和写大模拟没啥区别。
本题解中关于代码的解释会直接说明是代码的第几行,所以建议将代码放入编辑器后对照着行数进行调试。代码链接:群星连结源代码。
为了方便大家对照着代码进行调试,先给出代码的各部分功能目录:群星连结代码目录。
另外需要注意的是,我代码中的
题目思路
那么接下来我们开始分析这道大模拟。
首先我们分析题面,把一些需要用的定义列出来,方便写代码和再次读题时查询和理解。
-
-
-
题面中的伤害是可以用防御力减少的,而真实伤害无法用防御力减少。为了方便起见,下文我们称伤害为普通伤害或普伤,称真实伤害为真实伤害或真伤;
-
当生命值
hp 大于最大生命值HP 时,hp 会变为HP ;能量值同样如此。为了与代码格式统一,下文我们称生命值为HP ,最大生命值为maxHP ,能量值为MP ,最大能量值为maxMP 。
那么定义差不多写完了,我们再看一遍题面,理一下怎么实现各模块的代码。
- 题面一开始就对角色参数做了定义。那么对于角色信息,我们需要开一个结构体来存储;
struct character // 角色信息结构体
{
long long HP , maxHP; // 当前生命 / 最大生命
long long MP , maxMP; // 当前能量 / 最大能量
long long atk , Datk; // 初始攻击 / 攻击加成
long long def , Ddef; // 初始防御 / 防御加成
long long talent , Xtalent , Ytalent; // 天赋代号 / 天赋参数 x / 天赋参数 y
long long skill , Xskill , Yskill , Zskill; // 技能代号 / 技能参数 x / 技能参数 y / 技能参数 z
long long ID , goal; // 角色代号 / 攻击目标
bool islive; // 是否存活
long long player; // 对应阵营(Alice = 1 / Bob = 2)
};
- 读到后面两段,我们还发现每个角色都有攻击优先级数组。这个我们可以建一个结构体来存攻击优先级;
struct attackgoal // 角色攻击优先级信息
{
bool islive; // 是否存活
long long ID; // 角色代号
};
-
再往后读到技能条目,我们发现有增益这种东西,所以我们针对攻击力、防御力、能量回复的增益,分别开三个时间线数组,每个数组开两维,第二维用于分辨这是双方中哪一方的增益;
-
回到上面的的死亡判定条目,我们需要据此写一个死亡判定的函数。如果角色死了,即
HP \le 0 ,也应该用这个函数设置一下他的状态:设置死亡状态islive = 0 ,生命值重置HP = 0 ,当前阵营角色减少一个,还需要在对方的优先级数组上标记当前角色死亡; -
依据死亡判定最后一段的说明,我们发现角色死亡可能会导致当前阵营角色变为
0 ,进而使得游戏结束,所以我们需要写一个判断游戏结束的函数。如果有一方角色数为0 ,那么对方胜利,将对方每一个角色的生命值重置(可能需要)后输出即可。当然为了代码美观也可以写上当双方角色都为0 时输出平局(任意表情); -
根据下一段的优先目标条目,我们可以写出一个寻找目标的函数,只需要对着这个角色的优先数组扫一遍,找到第一个活着的对方角色即可(由于当前游戏一定未结束,所以对方一定有活着的角色);
-
下一段是对普攻的说明,我们只需要算出当前角色的攻击力,然后分讨三种情况:天赋为超凡入圣,普攻变为真伤;天赋为星河力量投射,普攻附加真伤;天赋不属于这两个,正常造成普伤。我们可以写对于双方分别写两个普攻函数,表示当前角色对优先目标攻击,使其扣除生命值;
-
但我们当前还没有一个扣除生命值的函数,所以我们往后找到生命扣除条目,先增加能量值,然后分讨两种情况:天赋为血肉皮囊,易得真伤减免量为其一半并下取整,否则正常计算真伤。普伤的计算公式是固定的,我们可以和真伤计算写到一起,也可以分开写;
-
然后我们再次跳回去看,天赋的生效判定虽然简单,但触发次数多,所以我们把它穿插到代码中,而不是专门写一个函数(写函数也确实不好写);
-
然后是技能条目,这一部分我们先不管怎么指定角色为技能释放角色,而是实现一个技能函数即可。代码中我的能量清空是写到主函数的技能释放前面,也可以写到函数里。由于技能较多,而题面中已经描述十分清楚,这里不再描述(具体实现上的问题可见题解开头的代码目录和代码链接、文末的代码调试注意点);
-
最后我们看到游戏过程,己方行动期间的技能发动判断较简单,可以直接插到主函数中实现;而普攻还需要计算伤害,所以我们可以对于双方写两个计算当前角色普攻能造成的伤害(只用于计算,而非真的造成伤害),那么对应的,我们也需要写一个用于计算角色受到普伤和真伤而降低生命值量的函数。
这样的话我们处理好整个框架了,还有一些具体的细节需要处理:
-
受到伤害就一定会进入生命扣除函数,一定会使角色能量增加(如果能量值未满),当然这里的伤害可能为
0 (技能3 中当敌方maxHP < 10 时会造成0 点伤害),也是需要进入生命扣除阶段的; -
天赋科技至上会根据攻击方式的不同而触发生命回复或能量回复,这点需要穿插入普攻和技能发动后的判断部分;
-
天赋心胜于物的生命回复和能量回复是额外的,全队的能量加成仍然需要对这个角色处理;
-
技能发动后需要清空能量值,如果技能函数中没写这一步记得穿插入主函数中;
-
己方行动结束阶段需要给全员增加一点能量值,还需要处理能量值增益;
-
放技能后需要更新所有人的增益,因为技能会使增益变化;
-
需要用变量或另一个数组存下当前的增益,方便放技能后、每回合结束后的增益回溯。
这样的话,代码实现基本就没有问题了。当然如果你真的调不出来,或是感觉代码中有一些不好发现的小错误,可以参照:群星连结代码注意点。
后记
写这种大模拟,重要的是理清思路,看清需要写的具体内容;要认真写代码,及时检查,避免因为小错误去阅读整篇代码好几次;真的有错误应该输出足量的调试信息,找到错误原因,也可以找一篇题解也输出同样的格式对着调(但不要直接交题解)。
其实我第一遍写的时候只有两个错误,第一个是第
所以大家写题一定要仔细啊!