也许从某个事件处理程序中,您想决定要施放什么咒语。也许你可以从这个施法者开始:
public class Caster
{
private readonly ICastable[] _spells;
private int _canCastAt;
public Caster(ICastable[] spells)
{
_spells = spells;
_canCastAt = -1;
}
public string GetNextSpellToCast(int currentTime)
{
if (currentTime < _canCastAt)
return null;
for (int i = 0; i < _spells.Length; i++)
{
int durationOfCast = _spells[i].AttemptCast(currentTime);
if (durationOfCast > 0)
{
_canCastAt = currentTime + durationOfCast;
return _spells[i].GetName();
}
}
return null;
}
}
施法者会施法:
public interface ICastable
{
string GetName();
int AttemptCast(int msCurrentTime);
}
你描述了一种特殊的咒语:
public class ChanneledSpell : ICastable
{
private readonly string _name;
private readonly int _castDuration;
private readonly int _castCooldown;
private int _lastCast;
public ChanneledSpell(string name, int castDuration, int castCooldown)
{
Debug.Assert(castDuration < castCooldown); // a reasonable assumption the tests makes
_name = name;
_castDuration = castDuration;
_castCooldown = castCooldown;
_lastCast = -_castCooldown;
}
public string GetName()
{
return _name;
}
public int AttemptCast(int msCurrentTime)
{
if (msCurrentTime > _lastCast + _castCooldown)
{
_lastCast = msCurrentTime;
return _castDuration;
}
return 0;
}
}
我看到这被标记为 C++,这个答案是 C#,虽然我只使用了 C++ 中可用的语言结构,所以它应该是一个简单的翻译。我不能这么容易翻译的是一些测试,
[TestFixture]
public class SpellTest
{
[Test]
public void TestCanCastOnStartup()
{
var sut = new ChanneledSpell(Some.String(), Some.PositiveNonzeroInteger(), Some.PositiveNonzeroInteger());
int result = sut.AttemptCast(Some.PositiveNonzeroInteger());
Assert.IsTrue(CastWasMade(result));
}
[Test]
public void TestCantCastUntilCooldown()
{
int firstCast = Some.PositiveNonzeroInteger();
int duration = Some.PositiveNonzeroInteger();
int cooldown = duration + Some.PositiveNonzeroInteger(); // assuming spell duration is less then cooldown
var sut = new ChanneledSpell(Some.String(), duration, cooldown);
int ignored = sut.AttemptCast(firstCast);
int secondCastAttempt = sut.AttemptCast(firstCast + cooldown - 1);
int thirdCastAttempt = sut.AttemptCast(firstCast + cooldown + 1);
Assert.IsFalse(CastWasMade(secondCastAttempt));
Assert.IsTrue(CastWasMade(thirdCastAttempt));
}
[Test]
public void TestReportsTimeOnCast()
{
int duration = Some.PositiveNonzeroInteger();
int firstCastTime = Some.PositiveNonzeroInteger();
var sut = new ChanneledSpell(Some.String(), duration, Some.PositiveNonzeroInteger());
int firstCastAttempt = sut.AttemptCast(firstCastTime);
Assert.AreEqual(duration, firstCastAttempt);
}
private bool CastWasMade(int result)
{
return result > 0;
}
}