Пример #1
0
        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);
            }
        }
Пример #2
0
        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);
        }
Пример #3
0
        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;
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
            }
        }
Пример #7
0
        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());
        }
Пример #8
0
        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);
        }
Пример #9
0
        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));
        }
Пример #10
0
        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);
        }