Ejemplo n.º 1
0
 public Block(BlockData options)
 {
     BlockLength = options.length;
     BlockStart  = options.start;
     BlockColour = options.colour;
     _blockClues = new Clues();
 }
Ejemplo n.º 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);
                }
            }
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Sets each element of the permitted clues array to a new empty Clues object
        /// </summary>

        private void InitialisePermittedClues(Clues[] clueList)
        {
            for (int i = 0; i < clueList.Length; i++)
            {
                clueList[i] = new Clues();
            }
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 6
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);
        }
Ejemplo n.º 7
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);
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// The only public method. It iterates through each legal position of the clues and
        /// checks to see if that arrangement is legal
        /// </summary>

        public void IdentifyBlocks()
        {
            Clues[] permittedClues = new Clues[_blocks.GetBlockCount()]; //temporary array to hold clues
            InitialisePermittedClues(permittedClues);                    //the array initially has null values. This sets them to empty Clues
            bool positionsToTest = true;

            while (positionsToTest)
            {
                ClearPermittedClues(permittedClues);
                if (ArrangementIsLegal(permittedClues))
                {
                    UpdateBlocks(permittedClues);
                }
                positionsToTest = FindNextCluePosition();
            }
        }
Ejemplo n.º 9
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);
        }
Ejemplo n.º 10
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);
        }
Ejemplo n.º 11
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);
        }
Ejemplo n.º 12
0
 public Space(SpaceData options)
 {
     SpaceLength = options.length;
     SpaceStart  = options.start;
     _spaceClues = new Clues();
 }