Exemple #1
0
        /// <summary>
        /// A pretty simple method to check if there are certain cells that must be filled in regardless of clue position
        /// </summary>
        /// <remarks>
        /// If the clues are positioned as far left as they can go and then as far right as they can go there may be
        /// certain cells that will always be covered.
        /// For example, in an element of 15 cells a clue of length 10 will always cover cells 5 to 9
        /// </remarks>

        private static int Overlap(Grid grid, Clues clues, Blocks blocks, Spaces spaces, int element, int elementLength, bool isRow)
        {
            int filled    = 0;
            int firstFree = grid.GetFirstFreeCell(element, isRow);
            int lastFree  = grid.GetLastFreeCell(element, isRow);
            int rowToUpdate;
            int colToUpdate;

            //For a given space, find the clues that HAVE to be in that space and check limits
            for (int spaceNo = 0; spaceNo < spaces.getSpaceCount(); spaceNo++)
            {
                Clues cluesToTest = FindFewestClues(spaces, clues, spaceNo);
            }

            for (int clueNo = 0; clueNo < clues.GetClueCount(); clueNo++)
            {
                //this needs adapted to take account of filled cells
                int endClueLeft    = firstFree - 1 + clues.GetClueLength(0, clueNo);
                int startClueRight = lastFree + 1 - clues.GetClueLength(clueNo, clues.GetClueCount() - 1);
                if (startClueRight <= endClueLeft)
                {
                    for (int cellNo = startClueRight; cellNo <= endClueLeft; cellNo++)
                    {
                        rowToUpdate = (isRow) ? element : cellNo;
                        colToUpdate = (isRow) ? cellNo : element;
                        if (Update(grid, colToUpdate, rowToUpdate, clues.getClue(clueNo).Colour))
                        {
                            filled += 1;
                        }
                    }
                }
            }
            return(filled);
        }
Exemple #2
0
        /// <summary>
        /// Determines which clues can be which blocks
        /// </summary>
        /// <remarks>
        /// Given a collection of blocks and a collection of clues, it is possible to determine that certain clues
        /// simply cannot be certain blocks (because they're too long or in the wrong place)
        /// This is all now done by the BlockIdentifier class.
        /// </remarks>

        public static void IdentifyBlocks(Grid grid, Clues clues, Blocks blocks, Spaces spaces, int element, int elementLength, bool isRow)
        {
            if (blocks.GetBlockCount() > 0 && clues.GetClueCount() > 0 && !clues.AllCluesSolved())
            {
                BlockIdentifier bId = new BlockIdentifier(clues, blocks, spaces, elementLength);
                bId.IdentifyBlocks();

                //now print the clues permitted for each block - this is for checking
                string outputstring;
                if (isRow)
                {
                    Console.WriteLine("Row {0}, {1} clues and {2} blocks", element, clues.GetClueCount(), blocks.GetBlockCount());
                }
                else
                {
                    Console.WriteLine("Col {0}, {1} clues and {2} blocks", element, clues.GetClueCount(), blocks.GetBlockCount());
                }
                for (int blockNo = 0; blockNo < blocks.GetBlockCount(); blockNo++)
                {
                    outputstring = "Block : " + blockNo + ": ";

                    for (int clueNo = 0; clueNo < clues.GetClueCount(); clueNo++)
                    {
                        if (blocks.GetBlock(blockNo).AllClues().ClueExists(clues.getClue(clueNo)))
                        {
                            outputstring += clueNo + ", ";
                        }
                    }
                    Console.WriteLine(outputstring);
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Checks that the clue is entirely within a space (i.e. not opposite a cross square)
        /// </summary>

        private bool CluesFitInSpaces(Clues clues, Spaces spaces, int[] cluePositions)
        {
            for (int clueNo = 0; clueNo < clues.GetClueCount(); clueNo++)
            {
                if (!ClueFitsInSpace(clues.getClue(clueNo), spaces, cluePositions[clueNo]))
                {
                    return(false);
                }
            }
            return(true);
        }
Exemple #4
0
        public static Clues FindFewestClues(Spaces spaces, Clues clues, int clueNo)
        {
            Clues resultClues = new Clues();

            Spaces spacesBefore = new Spaces();
            Space  spaceToTest;
            Spaces spacesAfter = new Spaces();

            //now we want to add the clues one by one to spacesAfter. If they won't fit in SpacesAfter then
            //we move them to spaceToTest and if they won't fit there we move them to spacesBefore

            return(resultClues);
        }
Exemple #5
0
 private bool ClueFitsInSpace(Clue clue, Spaces spaces, int clueStart)
 {
     //is this clue completely within a space?
     foreach (Space space in spaces)
     {
         //we just need one to be true
         if (clueStart >= space.SpaceStart && clueStart + clue.Number <= space.SpaceStart + space.SpaceLength)
         {
             return(true);
         }
     }
     return(false);
 }
Exemple #6
0
        /// <summary>
        /// This class takes a Clues object, a Spaces object and a Blocks object and
        /// for each block determines which clues that block could legally be
        /// </summary>

        public BlockIdentifier(Clues clues, Blocks blocks, Spaces spaces, int elementLength)
        {
            _blocks = blocks;
            _clues  = clues;
            _spaces = spaces;
            int clueCount = _clues.GetClueCount();

            _cluePositions = new int[clueCount];
            for (int i = 0; i < clueCount; i++)
            {
                _cluePositions[i] = elementLength - _clues.GetClueLength(i);
            }
        }
Exemple #7
0
        public static bool CluesWillFitInSpaces(Clues clues, Spaces spaces, Blocks blocks)
        {
            List <Space> spaceList = new List <Space>();
            List <Clue>  clueList  = new List <Clue>();

            //first put all the spaces into spacelist
            //and all the clues into clueList
            foreach (Space space in spaces)
            {
                spaceList.Add(space);
            }
            foreach (Clue clue in clues)
            {
                clueList.Add(clue);
            }

            bool finished = false;

            while (!finished)

            {
                //move the next clue into the last space
                if (clueList.Count > 0)
                {
                    spaceList[spaceList.Count - 1].AddClue(clueList[0]);
                    clueList.RemoveAt(0);
                }

                for (int i = spaceList.Count - 1; i >= 0; i--)
                {
                    // for each space, if the clues are too long to fit, move the first one out
                    while (!CluesWillFitInSpace(spaceList[i], blocks))
                    {
                        //we need to move the first clue to the next space. If we're in space0 we can't and the test fails
                        if (i == 0)
                        {
                            return(false);
                        }
                        spaceList[i - 1].AddClue(spaceList[i].RemoveClue(0));
                    }
                }
                finished = clueList.Count == 0;
            }

            return(true);
        }
Exemple #8
0
        /// <summary>
        /// Deals with clues that are close to the edge of a spaces
        /// </summary>
        /// <remarks>
        /// Example: if we have a clue of length 3 as the first clue and cell 3 is filled in then cell 0 cannot be filled.
        /// Same can be done at the end of the element.
        /// </remarks>
        public static int EdgeProximity(Grid grid, Clues clues, Blocks blocks, Spaces spaces, int element, int elementLength, bool isRow)
        {
            int  filled = 0;
            int  rowToUpdate;
            int  colToUpdate;
            bool atStart  = true;
            int  fillFrom = -1;
            int  fillTo   = -1;

            //Cross out cells which logically cannot be filled because there's too big a gap between the first block and the edge of the element.
            if (blocks.GetBlockCount() > 0 && clues.GetClueCount() > 0)
            {
                for (int loopCount = 0; loopCount < 2; loopCount++)
                {
                    if (atStart && blocks.GetBlock(0).BlockColour == clues.getClue(0).Colour)
                    {
                        fillFrom = blocks.GetBlock(0).BlockStart - clues.getClue(0).Number;
                        fillTo   = fillFrom + blocks.GetBlock(0).BlockLength - 1;
                        fillFrom = (fillFrom < 0) ? 0 : fillFrom;
                    }
                    else if (!atStart && blocks.GetBlock(blocks.GetBlockCount() - 1).BlockColour == clues.getClue(clues.GetClueCount() - 1).Colour)
                    {
                        fillFrom = blocks.GetBlock(blocks.GetBlockCount() - 1).BlockStart + clues.getClue(clues.GetClueCount() - 1).Number;
                        fillTo   = fillFrom + blocks.GetBlock(blocks.GetBlockCount() - 1).BlockLength;
                        fillTo   = (fillTo > elementLength - 1) ? elementLength - 1 : fillTo;
                    }

                    if ((fillFrom == 0 && fillTo >= 0) || (fillTo == elementLength && fillFrom <= elementLength))
                    {
                        for (int cellNo = fillFrom; cellNo <= fillTo; cellNo++)
                        {
                            rowToUpdate = (isRow) ? element : cellNo;
                            colToUpdate = (isRow) ? cellNo : element;
                            if (Update(grid, colToUpdate, rowToUpdate, "cross"))
                            {
                                filled += 1;
                            }
                        }
                    }
                    atStart = false;
                }
            }
            return(filled);
        }
Exemple #9
0
        /// <summary>
        /// deals with the special case where there is only one clue.
        /// </summary>
        /// <remarks>
        /// This feels as though it should be able to be part of a different method. We'll see.
        /// </remarks>
        ///
        private static int SingleClue(Grid grid, Clues clues, Blocks blocks, Spaces spaces, int element, int elementLength, bool isRow)
        {
            int  filled = 0;
            int  blocksStart;
            int  blocksEnd;
            int  rowToUpdate;
            int  colToUpdate;
            Clue clue;

            //we know there is only one clue. If there is more than one block then the space between them must be filled in.
            if (blocks.GetBlockCount() > 0 && clues.GetClueCount() == 1)
            {
                blocksStart = blocks.GetBlock(0).BlockStart;
                blocksEnd   = blocks.GetBlock(blocks.GetBlockCount() - 1).BlockStart + blocks.GetBlock(blocks.GetBlockCount() - 1).BlockLength - 1;
                clue        = clues.getClue(0);
                for (int cellNo = grid.GetFirstFreeCell(element, isRow); cellNo <= grid.GetLastFreeCell(element, isRow); cellNo++)
                {
                    rowToUpdate = (isRow) ? element : cellNo;
                    colToUpdate = (isRow) ? cellNo : element;

                    if (cellNo >= blocksStart && cellNo <= blocksEnd)
                    {
                        if (Update(grid, colToUpdate, rowToUpdate, clue.Colour))
                        {
                            filled += 1;
                        }
                    }
                    else if (cellNo < blocksEnd - clue.Number + 1 || cellNo > blocksStart + clue.Number - 1)
                    {
                        if (Update(grid, colToUpdate, rowToUpdate, "cross"))
                        {
                            filled += 1;
                        }
                    }
                }
            }
            return(filled);
        }