示例#1
0
 /// <summary>
 /// Color the puzzle according to the "Test" value of the cell
 /// </summary>
 /// <param name="mode">Solve mode colors the whole puzzle, while hint mode colors only one cell</param>
 private void ColorTest(SolvingMode mode)
 {
     for (int i = 0; i < SizeX; i++)
     {
         for (int j = 0; j < SizeY; j++)
         {
             if (this[i, j].Test && this[i, j].State != CellState.filled)
             {
                 this[i, j].State = CellState.filled;
                 if (mode == SolvingMode.hint)
                 {
                     return;
                 }
             }
             if (!this[i, j].Test && this[i, j].State != CellState.empty)
             {
                 this[i, j].State = CellState.empty;
                 if (mode == SolvingMode.hint)
                 {
                     return;
                 }
             }
         }
     }
 }
示例#2
0
        /// <summary>
        /// Solve for the last unfinished value in checksum
        /// </summary>
        /// <param name="mode">Solve mode colors the whole puzzle, while hint mode colors only one cell</param>
        /// <returns>True if change occured, null if error occured</returns>
        private bool?SolveLast(SolvingMode mode)
        {
            bool change     = false;
            int  position   = (int)PutOneFromEnd(_lastUnfinished, _unfinishedRangeEnd);
            var  lastFilled = LastFilled();

            // position now marks where the put end is

            // we can now possibly shrink unfinished range
            change |= Color(position + _checksum[_lastUnfinished], _unfinishedRangeEnd, CellState.empty, mode);
            if (change && mode == SolvingMode.hint)
            {
                return(true);
            }
            // unfinished range begins after last colored cell
            _unfinishedRangeEnd = position + _checksum[_lastUnfinished] - 1;


            //coloring
            if (lastFilled - position >= _checksum[_lastUnfinished])
            {
                // when this happens, error occured (something is wrong with the puzzle)
                return(null);
            }

            if (lastFilled - position >= 0)
            {
                change |= Color(position, lastFilled, CellState.filled, mode);
                if (mode == SolvingMode.hint && change)
                {
                    return(true);
                }
                // if the whole value is finished, put an empty cell before it, decrease end of an unfinished range and change last unfinished value to the next one
                if (lastFilled - position + 1 == _checksum[_lastUnfinished])
                {
                    if (position - 1 > 0 && this[position - 1].State != CellState.empty)
                    {
                        this[position - 1].State = CellState.empty;
                        if (mode == SolvingMode.hint)
                        {
                            return(true);
                        }
                    }
                    // position marks the end of first value, position - 1 is an empty space and position - 2 is a new beginning of an unfinished range
                    _unfinishedRangeEnd = position - 2;
                    _lastUnfinished--;
                }
            }

            return(change);
        }
示例#3
0
        /// <summary>
        /// Solve for the first unfinished value in checksum
        /// </summary>
        /// <param name="mode">Solve mode colors the whole puzzle, while hint mode colors only one cell</param>
        /// <returns></returns>
        private bool?SolveFirst(SolvingMode mode)
        {
            bool change      = false;
            int  position    = (int)PutOneFromBeginning(_firstUnfinished, _unfinishedRangeBeginning);
            var  firstFilled = FirstFilled();


            // position now marks where the put end is

            // we can now possibly shrink unfinished range
            change |= Color(_unfinishedRangeBeginning, position - _checksum[_firstUnfinished], CellState.empty, mode);
            if (change && mode == SolvingMode.hint)
            {
                return(true);
            }
            // unfinished range begins after last colored cell
            _unfinishedRangeBeginning = position - _checksum[_firstUnfinished] + 1;

            //coloring
            if (position - firstFilled >= _checksum[_firstUnfinished])
            {
                // when this happens, error occured (something is wrong with the puzzle)
                return(null);
            }
            else if (position - firstFilled >= 0)
            {
                change |= Color(firstFilled, position, CellState.filled, mode);
                if (change && mode == SolvingMode.hint)
                {
                    return(true);
                }

                // if the whole value is finished, put an empty cell after it, increase beginning of an unfinished range and change first unfinished value to the next one
                if (position - firstFilled + 1 == _checksum[_firstUnfinished])
                {
                    if (position + 1 < _size && this[position + 1].State != CellState.empty)
                    {
                        this[position + 1].State = CellState.empty;
                        if (mode == SolvingMode.hint)
                        {
                            return(true);
                        }
                        change = true;
                    }
                    // position marks the end of first value, position + 1 is an empty space and position + 2 is a new beginning of an unfinished range
                    _unfinishedRangeBeginning = position + 2;
                    _firstUnfinished++;
                }
            }
            return(change);
        }
示例#4
0
        /// <summary>
        /// Solves a single line (row or column) of a puzzle using only one iteration and several methods of solving puzzle
        /// </summary>
        /// <param name="mode">Solving mode fills all of them, hint mode only fills one</param>
        /// <returns>True if a change occured, null if puzzle doesn't have a solution</returns>
        public bool?Solve(SolvingMode mode = SolvingMode.solve)
        {
            if (Check())
            {
                return(FinishLine(mode));
            }
            bool?change = false;

            if (_firstUnfinished > _lastUnfinished)
            {
                return(FillWithEmpty(mode));
            }
            var newChange = SolveRowIntersect(mode);

            if (mode == SolvingMode.hint && newChange == true)
            {
                return(true);
            }
            if (newChange == null)
            {
                return(null);
            }
            change   |= newChange;
            newChange = SolveFirst(mode);
            if (mode == SolvingMode.hint && newChange == true)
            {
                return(true);
            }
            if (newChange == null)
            {
                return(null);
            }
            change |= newChange;
            if (_firstUnfinished >= _checksum.Count)
            {
                return(change);
            }
            newChange = SolveLast(mode);
            if (mode == SolvingMode.hint && newChange == true)
            {
                return(true);
            }
            if (newChange == null)
            {
                return(null);
            }
            change |= newChange;
            return(change);
        }
示例#5
0
        /// <summary>
        /// Set state of cells in a given range to a given state
        /// </summary>
        /// <param name="start">Beginning of a range to color</param>
        /// <param name="finish">End of a range to color</param>
        /// <param name="state">State to which cells will be set</param>
        /// <param name="mode">Solve mode colors the whole range, while hint mode only colors the first cell</param>
        /// <returns>True if something changed</returns>
        private bool Color(int start, int finish, CellState state, SolvingMode mode)
        {
            bool change = false;

            for (int i = start; i <= finish; i++)
            {
                if (this[i].State != state)
                {
                    this[i].State = state;
                    if (mode == SolvingMode.hint)
                    {
                        return(true);
                    }
                    change = true;
                }
            }
            return(change);
        }
示例#6
0
        /// <summary>
        /// This function is called after the line is properly colored and only fills unknown spaces with empty values
        /// </summary>
        /// <param name="mode">Solving mode fills all of them, hint mode only fills one</param>
        /// <returns>True if change occured</returns>
        private bool FinishLine(SolvingMode mode)
        {
            bool change = false;

            for (int i = 0; i < _size; i++)
            {
                if (this[i].State == CellState.unknown)
                {
                    this[i].State = CellState.empty;
                    change        = true;
                    if (mode == SolvingMode.hint)
                    {
                        return(change);
                    }
                }
            }
            return(change);
        }
示例#7
0
        /// <summary>
        /// Solve the puzzle using state space search
        /// </summary>
        /// <param name="mode">Solve mode colors the whole puzzle, while hint mode colors only one cell</param>
        private bool SolveStateSpace(SolvingMode mode)
        {
            StateSpaceSearchLine[] lines;
            Func <bool>            check;
            Orientation            offsetsOrientation;

            // choose to solve in an orientation that has less lines
            if (SizeX > SizeY)
            {
                lines = new StateSpaceSearchLine[SizeY];
                offsetsOrientation = Orientation.Horizontal;
                check = CheckVerticalTest;
            }
            else
            {
                lines = new StateSpaceSearchLine[SizeX];
                offsetsOrientation = Orientation.Vertical;
                check = CheckHorizontalTest;
            }
            for (int i = 0; i < SizeY; i++)
            {
                lines[i] = new StateSpaceSearchLine(this, i, offsetsOrientation);
            }
            while (true)
            {
                if (check())
                {
                    break;
                }
                int lastIncreased = 0;
                while (!lines[lastIncreased].IncreaseOffsets())
                {
                    lines[lastIncreased].ResetOffsets();
                    lastIncreased++;
                    if (lastIncreased >= SizeX)
                    {
                        return(false);
                    }
                }
            }
            ColorTest(mode);
            return(true);
        }
示例#8
0
        /// <summary>
        /// Solve the puzzle
        /// </summary>
        /// <param name="mode">Solve mode colors the whole puzzle, while hint mode colors only one cell</param>
        /// <returns>Returns false if the puzzle in its current state doesn't have a solution</returns>
        public bool Solve(SolvingMode mode = SolvingMode.solve)
        {
            bool?change = false;
            var  lines  = new DirectSolveLine[SizeX + SizeY];

            for (int i = 0; i < SizeY; i++)
            {
                lines[i] = new DirectSolveLine(this, Orientation.Horizontal, i);
            }
            for (int i = SizeY; i < SizeX + SizeY; i++)
            {
                lines[i] = new DirectSolveLine(this, Orientation.Vertical, i - SizeY);
            }
            // Iterate through all rows and collumns and solve them as long as change occurs
            do
            {
                change = false;
                for (int i = 0; i < SizeX + SizeY; i++)
                {
                    var newChange = lines[i].Solve(mode);
                    if (mode == SolvingMode.hint && newChange == true)
                    {
                        return(true);
                    }
                    if (newChange == null)
                    {
                        return(false);
                    }
                    change |= newChange;
                }
            } while ((bool)change);

            // After the direct solving method fails, solve with state space search
            if (!IsSolved())
            {
                return(SolveStateSpace(mode));
            }
            return(true);
        }
示例#9
0
        /// <summary>
        /// Solves the line using intersection method
        /// </summary>
        /// <param name="mode">Can be either solveall which solves the whole puzzle, or hint, which only finds a single tile</param>
        /// <returns></returns>
        private bool?SolveRowIntersect(SolvingMode mode)
        {
            bool change = false;
            var  putBeg = PutFromBeginning();

            if (putBeg == null)
            {
                // this means puzzle doesn't have a solution
                return(null);
            }
            var putEnd = PutFromEnd();

            if (putEnd == null)
            {
                return(null);
            }
            // coloring
            for (int i = _firstUnfinished; i <= _lastUnfinished; i++)
            {
                if (putBeg[i - _firstUnfinished] >= putEnd[i - _firstUnfinished])
                {
                    for (int j = putEnd[i - _firstUnfinished]; j <= putBeg[i - _firstUnfinished]; j++)
                    {
                        if (this[j].State != CellState.filled)
                        {
                            this[j].State = CellState.filled;
                            if (mode == SolvingMode.hint)
                            {
                                return(true);
                            }
                            change = true;
                        }
                    }
                }
            }

            return(change);
        }
示例#10
0
        /// <summary>
        /// Sets the state of every cell in line to empty
        /// </summary>
        /// <returns></returns>
        private bool?FillWithEmpty(SolvingMode mode = SolvingMode.solve)
        {
            bool change = false;

            for (int i = _unfinishedRangeBeginning; i <= _unfinishedRangeEnd; i++)
            {
                if (this[i].State == CellState.unknown)
                {
                    this[i].State = CellState.empty;
                    change        = true;
                    if (mode == SolvingMode.hint)
                    {
                        return(change);
                    }
                }
                // preasummably empty line shouldn't contain filled cell
                if (this[i].State == CellState.filled)
                {
                    return(null);
                }
            }
            return(change);
        }
 /// <summary>
 /// Constructor for testing purpose.
 /// </summary>
 /// <param name="maxNumberOfAdditionalSantas"></param>
 /// <param name="mode"></param>
 public GoogleRoutingConfig(int maxNumberOfAdditionalSantas, SolvingMode mode)
 {
     MaxNumberOfAdditionalSantas = maxNumberOfAdditionalSantas;
     Mode = mode;
 }
示例#12
0
 public WrongSolverChoosenException(
     SolvingMode typeInUse) :
     base(String.Format("{0}{1}{2}",
                        defaultMessage[0], typeNames[(int)typeInUse], defaultMessage[1]))
 {
 }