Java方法中传递信息的复杂难题

时间:2016-03-02 04:25:01

标签: java methods return-type

我遇到了问题。这是:

当一个"技能"在游戏中使用。在这种情况下,技能将人们联系起来。成功是通过滚动一些骰子来确定的。然后,那个卷的结果就变成了被捆绑的人必须击败才能打破他们的债券。

然而,如果被捆绑的人可以反击,那么他们也可能会在那时使用不同的技能防止自己被束缚。这些卷是相反的,做捆绑的人必须打败另一个人的卷。

但是,每当有反对的掷骰时,无论哪个人失败都可以花一个运气点来重做他们的掷骰并试图再次击败它。参与反对滚动的人都可以继续这样做,直到他们用完点数。

这一切都很好而且花花公子,但是反对掷骰的方法只能让谁赢了。它确实返回原始卷,我们需要知道它以确定被捆绑的人是否可以在以后解除它。

    boolean success = false;
    Ability C = target.reallyFindAbility("Skill_Cleverness");
    final int fettRoll = roll(mob); //Cannot use opposedCheck because we need the raw roll.
    if((ez)||(fettRoll>C.roll(target)))
    {
            fetteringDC = fettRoll;

这是一个解决方案:我们首先进行滚动,保存,然后将其传递给方法以确定它们是否成功。但问题是:如果它们失败并开始重新滚动,则该滚动不再有效。它需要更新,但它不可能;该方法只返回他们是否赢了。

幸运点系统使用递归。它不能在首先使用技能的方法中重新创建,因为它只有一种方法,并且它做了很多其他的事情;如果程序的任何其他部分计算使用该技能的次数,那么递归它将是浪费并且可能会产生意想不到的后果。

/**
 * Returns whether the given mob passes their proficiency check in this skill
 * at this time, by rolling a 3d6 plus their ranks in the skill (proficiency)
 * against the Difficulty Check provided. 0 or lower is a failure.
 * @see com.planet_ink.coffee_mud.Abilities.interfaces.Ability#proficiency()
 * @see com.planet_ink.coffee_mud.Abilities.interfaces.Ability#proficiencyCheck(MOB, int)
 * @param mob the mob whose proficiency to check
 * @param target the mob opposing
 * @param ID the name of the skill opposing
 * @return the amount by which the mob passed or failed
 */
@Override
public int opposedCheck(MOB mob, MOB target, String ID)
{
    if((mob!=null)&&(target!=null)&&CMSecurity.isAllowed(mob,mob.location(),CMSecurity.SecFlag.SUPERSKILL)&&!CMSecurity.isAllowed(target,target.location(),CMSecurity.SecFlag.SUPERSKILL))
       return 10;
    else if((mob!=null)&&(target!=null)&&!CMSecurity.isAllowed(mob,mob.location(),CMSecurity.SecFlag.SUPERSKILL)&&CMSecurity.isAllowed(target,target.location(),CMSecurity.SecFlag.SUPERSKILL))
       return -10;

    Ability O = target.fetchAbility(ID);
    if(O==null)
        O = CMClass.findAbility(ID);
    if(O==null)
        return 10;
    final int skillRoll = roll(mob);
    final int oppRoll = O.roll(target);
    final boolean success = (skillRoll>oppRoll);
    if((!success)&&(mob!=null)&&(!mob.isMonster())&&(mob.playerStats().luckPoints()>0)&&(mob.playerStats().getAutoLuck(PlayerStats.LUCK_SKILLREROLL)>=CMLib.dice().rollPercentage()))
    {
        mob.playerStats().setLuck(mob.playerStats().luckPoints()-1);
        return opposedCheck(mob, target, ID);
    }
    if((success)&&(target!=null)&&(!target.isMonster())&&(target.playerStats().luckPoints()>0)&&(target.playerStats().getAutoLuck(PlayerStats.LUCK_SKILLREROLL)>=CMLib.dice().rollPercentage()))
    {
        target.playerStats().setLuck(target.playerStats().luckPoints()-1);
        return opposedCheck(mob, target, ID);
    }
    return skillRoll-oppRoll;
}

我无法想到解决这个问题的任何优雅方案。满足每个要求的唯一解决方案是让相对的滚动传回一个包含滚动的无类型Vector,无论它们是否赢了等等,这不仅看起来很邋but而且还会造成问题,因为这是一个非常具体的使用场景,我将不得不返回并为我使用该方法的每个其他实例更改它,并且不需要太多详细信息。

有什么建议吗?

2 个答案:

答案 0 :(得分:2)

发回一对或类似的东西,它既包含一个布尔值,也包含两个整数,以指示滚动。

你说“我必须回去为我使用该方法的其他每个实例更改它,而不需要那些细节。”这可以通过创建一个新方法来轻松解决,以便处理这个特定的用例。

此外,如果两个玩家都有很多运气点,那么基于运气的系统应该使用Stack而不是递归来防止溢出。

答案 1 :(得分:1)

我相信你想要做的事情可以通过一些抽象来完成。将您当前的“技能”方法重构为满足这些一般过程的几种方法:

  • 获取/生成攻击检定
  • 获取/生成防御卷
  • 攻击滚动胜利(给定滚动攻击,防守防守)

而且重要的是,

  • 确定攻击是否会使用运气点重新打印
  • 确定防御是否会使用运气点重新打印

因此,你有一种方法只能生成攻击检定,一种方法只能生成一个防御卷,而一种方法只能计算哪一卷获胜。中间数据如何存储并不重要,只要它按预期工作即可。

现在重要的部分是重构,你可以有一个循环,它可以做类似下面的伪代码:

int attack = getAttackRoll();
int defense = getDefenseRoll();
boolean success;
while(true) {
    success = attackWins(attack, defense);
    if (success) {
        if (repeatDefense()) { // if defense wants to use a luck point
            defense = getDefenseRoll(); // regenerate defense roll
        } else break; // otherwise exit as success=true
    } else {
        if (repeatAttack()) { // if attack wants to use a luck point
            attack = getAttackRoll(); // regenerate attack roll
        } else break; // otherwise exit as success=false
    }
}
return success;

(我不一定建议实现这样的循环。这只是一个例子。)

这里的关键点是我们可以分别检查影响结果的每个条件而没有副作用。 repeatDefense()询问防守者是否想要使用运气点重新进行辩护(当然,如果他们有幸运点)。您还可以将防御卷和/或攻击卷传递给它以向他们展示滚动的内容。同样适用于repeatAttack(),但问题的另一方面。

另一个关键是这里概述的这种方法(称之为getResultAfterLuck())调用单级运气决定者。 repeatDefense() repeatAttack()仅处理单次运气使用,允许结果计算器处理剩余的事情,包括如果滚动没有再次成功则再次查询。如果你想永远是我们最高的而不是最近的,只需引入一个临时变量并使用类似Math.max(int,int)的东西。

此处的目标是让Pure Functions查询给定的滚动状态,以便您可以自由重新滚动。

然后,这可以用一个很好的getResultAfterLuck方法包装,以方便使用。此外,唯一需要重复的部分是需要的。

如果您需要监控技能的使用次数,请确保在处理循环之外触发事件,您应该没事。

澄清:既然你实际上需要滚动和成功,那么以兄弟方法返回一对是最好的选择,正如q& a首先建议的那样。