I implement the "Prisoner's Dilemma" task.
In the "iterative" version (i.e. in which there is more than one crime in which prisoners are accused), their actions depend or do not depend (depending on the chosen strategy) from the previous decision of the opponent and the year are summed up.
I created an abstract class for strategy:
public abstract class StrategyBase { public string StrategyName { get; set; } public abstract Action Init(); public abstract Action Next(Action previousActionOfAnotherPrisoner); } public enum Action { Tie = 0, Informer = 1 } prisoner class:
public class Prisoner { public string PrisonerName { get; private set; } public StrategyBase Strategy { get; private set; } public Action? LastAction { get; private set; } public int TotalYears { get; private set; } public Prisoner(string name, StrategyBase strategy) { if (strategy == null) throw new ArgumentNullException("strategy"); PrisonerName = name; Strategy = strategy; } public void Do(Action? previousActionOfAnotherPrisoner) { if (previousActionOfAnotherPrisoner == null) LastAction = Strategy.Init(); else LastAction = Strategy.Next(previousActionOfAnotherPrisoner.Value); } public void AddYears(ConvictionYears years) { TotalYears += (int)years; } } Further the class Dilemma causes all this:
public class Dilemma { private Prisoner prisoner1; private Prisoner prisoner2; public Dilemma(Prisoner prisoner1, Prisoner prisoner2) { if (prisoner1 == null) throw new ArgumentNullException("prisoner1"); if (prisoner2 == null) throw new ArgumentNullException("prisoner2"); this.prisoner1 = prisoner1; this.prisoner2 = prisoner2; } public IterationInfo Iteration() { Action? previousAction1 = prisoner1.LastAction; Action? previousAction2 = prisoner2.LastAction; prisoner1.Do(previousAction2); prisoner2.Do(previousAction1); Utils.AddYears(prisoner1, prisoner2); return new IterationInfo(prisoner1.LastAction.Value, prisoner2.LastAction.Value, prisoner1.TotalYears, prisoner2.TotalYears); } } This all works wonderfully. But I do not like one moment - the accrual of years. Because their accrual for each depends on the decision of the second prisoner, I can not stick this logic into Do, and I have to spread them by 2 methods. and call them from the calling class Dilemma sequentially (in this case, the logic of how many years one or another will be encapsulated in Utils.AddYears ()). I do not like that the client should "remember" to call AddYears. In fact, it should all be in one action. How to implement this correctly? In the Do method to set a temporary variable and to fence the logic of checks?
Dilemmarefers to thePrisonerclass? Maybe it is necessary to transfer the dilemma not to prisoners, but to their strategies, and to make the prisoners themselves completely internal classes? - Pavel Mayorov