private bool ApplyChangesAndRunNonTrialRules(IGame game, bool isFirstCall, FieldsToChange <BimaruValue> changes) { bool hasChangedFieldValues = false; var unhandledChangedEvents = new Queue <FieldValueChangedEventArgs <BimaruValue> >(); void ChangedEventHandler(object sender, FieldValueChangedEventArgs <BimaruValue> e) { CheckIsChangeValid(game, e); unhandledChangedEvents.Enqueue(e); hasChangedFieldValues = true; } if (isFirstCall) { FireInitialChangedEvents(game.Grid, ChangedEventHandler); } game.Grid.FieldValueChanged += ChangedEventHandler; try { game.Grid.ApplyFieldChanges(changes); HandleChangedEvents(game, unhandledChangedEvents); RunSolverRules(game, isFirstCall); HandleChangedEvents(game, unhandledChangedEvents); } finally { game.Grid.FieldValueChanged -= ChangedEventHandler; } return(hasChangedFieldValues); }
public void TestOneMissingWater() { var game = (new GameFactory()).GenerateEmptyGame(3, 4); game.Grid[new GridPoint(2, 3)] = BimaruValue.SHIP_UNDETERMINED; game.TargetNumberOfShipFieldsPerRow[0] = 2; game.TargetNumberOfShipFieldsPerRow[1] = 2; game.TargetNumberOfShipFieldsPerRow[2] = 3; game.TargetNumberOfShipFieldsPerColumn[0] = 0; game.TargetNumberOfShipFieldsPerColumn[1] = 3; game.TargetNumberOfShipFieldsPerColumn[2] = 3; game.TargetNumberOfShipFieldsPerColumn[3] = 1; // 0331 // ---- // 3|???S // 2|???? // 2|???? // => The only row or column with one missing WATER or ship // is row 2 with one missing WATER. var rule = new OneMissingShipOrWater(null); var changesExpected = new FieldsToChange <BimaruValue>() { { new GridPoint(2, 0), BimaruValue.WATER }, { new GridPoint(2, 1), BimaruValue.WATER }, { new GridPoint(2, 2), BimaruValue.WATER }, }; AssertEqualTrialChanges(changesExpected, rule.GetChangeTrials(game)); }
private static void AssertEqualChanges(FieldsToChange <BimaruValue> first, FieldsToChange <BimaruValue> second) { Assert.AreEqual(first.Count(), second.Count()); // FieldsToChange contains by design no duplicate field // => Same count + first contained in second is enough for equality foreach (var c in first) { Assert.IsTrue(second.Contains(c)); } }
private IEnumerable <FieldsToChange <BimaruValue> > GetUndeterminedToWaterTrial(IGame game) { var changes = new FieldsToChange <BimaruValue>(); foreach (GridPoint p in game.Grid.AllPoints().Where(p => !game.Grid[p].IsFullyDetermined())) { changes.Add(p, BimaruValue.WATER); } if (changes.Count() > 0) { yield return(changes); } }
private int ApplyChangesAndRunRules(IGame game, bool isFirstCall, FieldsToChange <BimaruValue> changes) { bool hasChangedFieldValues = ApplyChangesAndRunNonTrialRules(game, isFirstCall, changes); if (!isFirstCall && !hasChangedFieldValues) { throw new InvalidOperationException(@"No field value has changed, which could lead to an infinite recursion"); } if (game.IsSolved) { GridBackup.CloneToClipboard(game.Grid); return(1); } return(RunTrialRule(game)); }
private int SolveToClipboard(IGame game, bool isFirstCall, FieldsToChange <BimaruValue> changes = null) { int numSolutions = 0; GridBackup.SetSavePoint(game.Grid); try { numSolutions = ApplyChangesAndRunRules(game, isFirstCall, changes); } catch (InvalidBimaruGame) { } finally { GridBackup.RestoreAndDeleteLastSavepoint(game.Grid); } return(numSolutions); }
public ShipLocation(GridPoint startPoint, Direction direction, int shipLength) { var shipFields = BimaruValues.FieldValuesOfShip(direction, shipLength); Changes = new FieldsToChange <BimaruValue>(startPoint, direction, shipFields); }