static public bool MoveNext(this iBoard b, ref MoveType lastMove) { while (lastMove < MoveType.Stop) { lastMove = lastMove + 1; switch (lastMove) { case MoveType.Left: case MoveType.Up: case MoveType.Right: case MoveType.Down: if (b.Move(lastMove)) { return(true); } break; } } if (b.Steps.Any()) { UndoStep last = b.PeekStep(); lastMove = last._type; b.UndoMove(); return(b.MoveNext(ref lastMove)); } else { return(false); } }
static public bool IsInDeadLock(this iBoard b) { string boardInfo = b.GetBoardInfo(true); if (b.Steps.Any(us => us._boardInfo == boardInfo)) { return(true); } for (int y = 1; y < b.Height - 1; y++) { for (int x = 1; x < b.Width - 1; x++) { if (IsBoxNotInPlace(b[x, y])) { bool u = b.CanNotBeMoved(x, y, MoveType.Up); bool d = b.CanNotBeMoved(x, y, MoveType.Down); bool l = b.CanNotBeMoved(x, y, MoveType.Left); bool r = b.CanNotBeMoved(x, y, MoveType.Right); if ((u || d) && (l || r)) { return(true); } } } } return(false); }
static public void UndoMove(this iBoard b) { if (!b.Steps.Any()) { return; } UndoStep step = b.PopStep(); int dx = 0, dy = 0; step._type.Move(ref dx, ref dy); int bx = b.BuddyX, by = b.BuddyY; Debug.Assert(Is(b[bx, by], CellType.Buddy)); b[bx, by] &= ~CellType.Buddy; Debug.Assert(IsEmpty(b[bx - dx, by - dy])); b[bx - dx, by - dy] |= CellType.Buddy; if (step._boxMoved) { int obx = bx + dx, oby = by + dy; Debug.Assert(Is(b[obx, oby], CellType.Box)); b[obx, oby] &= ~CellType.Box; b[bx, by] |= CellType.Box; } b.BuddyX -= dx; b.BuddyY -= dy; }
public static string GetBoardInfo(this iBoard b, bool letters) { int width = b.Width, height = b.Height; if (width > 0 && height > 0) { int index = letters ? 1 : 0; StringBuilder sb = new StringBuilder((width + 1) * height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { var ct = b[x, y]; var ctl = _legendMap.FirstOrDefault(ctl_ => ctl_._type == ct); if (ctl == null) { throw new ApplicationException(string.Format("Incorrect cell '{0}' type encountered in board", ct)); } sb.Append(ctl._chars[index]); } sb.Append('\n'); } return(sb.ToString()); } return(string.Empty); }
static public bool Move(this iBoard b, MoveType moveType) { int dx = 0, dy = 0; moveType.Move(ref dx, ref dy); int bx = b.BuddyX, by = b.BuddyY; int nx = bx + dx, ny = by + dy; // on border check if (dx < 0 && nx <= 0 || dx > 0 && nx >= b.Width - 1) { return(false); } if (dy < 0 && ny <= 0 || dy > 0 && ny >= b.Height - 1) { return(false); } if (IsEmpty(b[nx, ny])) { string boardInfo = b.GetBoardInfo(true); b[bx, by] &= ~CellType.Buddy; b[nx, ny] |= CellType.Buddy; b.BuddyX = nx; b.BuddyY = ny; b.PushStep(new UndoStep(moveType, false, boardInfo)); return(true); } if (Is(b[nx, ny], CellType.Box)) { int nbx = nx + dx, nby = ny + dy; // on border check if (dx < 0 && nbx <= 0 || dx > 0 && nbx >= b.Width - 1) { return(false); } if (dy < 0 && nby <= 0 || dy > 0 && nby >= b.Height - 1) { return(false); } if (IsEmpty(b[nbx, nby])) { string boardInfo = b.GetBoardInfo(true); b[nx, ny] &= ~CellType.Box; b[nbx, nby] |= CellType.Box; b[bx, by] &= ~CellType.Buddy; b[nx, ny] |= CellType.Buddy; b.BuddyX = nx; b.BuddyY = ny; b.PushStep(new UndoStep(moveType, true, boardInfo)); return(true); } } return(false); }
static public void Solve(this iBoard b, Func <bool> canceler) { MoveType lastMove = MoveType.Start; while (!canceler() && !b.IsSolved() && b.MoveNext(ref lastMove)) { lastMove = b.IsInDeadLock() ? MoveType.Stop : MoveType.Start; Thread.Sleep(1000); } }
static public string Solution(this iBoard b) { StringBuilder sb = new StringBuilder(b.Steps.Count()); foreach (var step in b.Steps) { sb.Append(step.ToChar()); } return(sb.ToString()); }
static bool CanNotBeMoved(this iBoard b, int x, int y, MoveType mt) { mt.Move(ref x, ref y); CellType t = b[x, y]; if (t == CellType.Wall) { return(true); } if (Is(t, CellType.Box)) { bool u = mt == MoveType.Down || b.CanNotBeMoved(x, y, MoveType.Up); bool d = mt == MoveType.Up || b.CanNotBeMoved(x, y, MoveType.Down); bool l = mt == MoveType.Right || b.CanNotBeMoved(x, y, MoveType.Left); bool r = mt == MoveType.Left || b.CanNotBeMoved(x, y, MoveType.Right); if ((u || d) && (l || r)) { return(true); } } return(false); }
static public bool IsSolved(this iBoard b) { var ctm = CellType.Box | CellType.Place; return(b.Cells.All(ct => (ct & CellType.Place) != CellType.Place || (ct & ctm) == ctm)); }
static public void Init(this iBoard b, string boardInfo) { b.Init(null); b.BuddyX = b.BuddyY = 0; int boxes = 0; int places = 0; if (boardInfo == null) { throw new ArgumentNullException("board", "Null passed as board description"); } if (string.IsNullOrEmpty(boardInfo)) { throw new ArgumentException("Empty string passed as board description", "board"); } string[] lines = boardInfo.Split('\n', '|'); int height = lines.Length; if (height < 3) { throw new ArgumentException("Board description contains too few lines", "board"); } int width = lines.Max(l => l.Length); if (width < 3) { throw new ArgumentException("Board description contains too few columns", "board"); } var cells = new CellType[width, height]; for (int y = 0; y < height; y++) { string line = lines[y]; for (int x = 0; x < line.Length; x++) { CellType t = FromChar(line[x]); if (t != CellType.Empty && t != CellType.Wall && (x == 0 || x == width - 1 || y == 0 || y == height - 1)) { throw new ArgumentException("Buddy, box or place on border", "board"); } cells[x, y] = t; if (Is(t, CellType.Buddy)) { if (b.BuddyX > 0 && b.BuddyY > 0) { throw new ArgumentException("More than one buddy on board", "board"); } b.BuddyX = x; b.BuddyY = y; } if (Is(t, CellType.Box)) { boxes++; } if (Is(t, CellType.Place)) { places++; } } } if (boxes != places) { throw new ArgumentException("Number of boxes not equal to number of places", "board"); } if (boxes == 0) { throw new ArgumentException("No boxes on board", "board"); } if (b.BuddyX == 0 && b.BuddyY == 0) { throw new ArgumentException("No buddy on board", "board"); } b.Init(cells); }