/// <summary> /// Input a PossibleBlock if its valid it is returned. Else return NULL /// </summary> /// <param name="pBlock"></param> /// <returns></returns> private bool IsPBlockValid(PossibleBlock pBlock, MainBlock MBlock) { // Does the Possible Block contian all the Cells int MainBlock.CertainCells? if (MBlock.CertainCells.IsSubsetOf(pBlock.Cells)) { //All the Cells in a possible block are looped through. Keeps track to check if all Cells are valid members of the Possible Block. bool isValid = true; // Loop through each cell in this Possible Block foreach (Cell cell in pBlock.Cells) { //Is the Cell owned by a different MainBlock? if (cell.IsOwnedByBlockOtherThan(MBlock)) { //If Cell is owned by other block then this Possible Block is no longer valid. isValid = false; break; } } //If the Possible Block is valid return it. Possible block must be superset of MainBlock.CertainCells && not contain a Cell owned by a different MainBlock if (isValid) { return(true); } else { return(false); } } else { return(false); } }
/// <summary> /// Clones a MainBlock in the original Grid. Each PossibleBlock in the MainBlock.PossibleBlocks is also Cloned /// Cells are not dealth with at this stage. /// </summary> /// <param name="originalMBlock"></param> /// <returns></returns> private MainBlock DeepCloneMainBlock(MainBlock originalMBlock) { ///sets new main bl MainBlock newMainBlock = new MainBlock(originalMBlock.Index, originalMBlock.Area, originalMBlock.DefinedCell, NewGrid); newMainBlock.PossibleBlocks = ClonePossibleBlocksList(originalMBlock); return(newMainBlock); }
/// <summary> /// Does this cell have certain ownership by any block other that the one given. Returns true if the cell has ownership by a different block. /// </summary> /// <param name="MBlock"></param> /// <returns></returns> public bool IsOwnedByBlockOtherThan(MainBlock MBlock) { if (MBlock.Index != OwnedBy && IsOwned) { return(true); } else { return(false); } }
/// <summary> /// Loops through each PossibleBlock for the input original block. Each PossibleBlock is deep cloned and added to a list. This list is returned /// The new PossibleBlocks reference the newGrid. Cells are not added at this stage. /// </summary> /// <param name="originalMainBlock"></param> /// <returns></returns> private List <PossibleBlock> ClonePossibleBlocksList(MainBlock originalMainBlock) { //This list will hold the new PossibleBlocks for a new MainBlock List <PossibleBlock> newPossibleBlocks = new List <PossibleBlock>(); foreach (PossibleBlock originalPossibleBlock in originalMainBlock.PossibleBlocks) { //Deep clone each original PossibeBlock and add to the new PossibleBlock list newPossibleBlocks.Add(DeepClonePossibleBlock(originalPossibleBlock)); } return(newPossibleBlocks); }
/// <summary> /// Finds the Largest Unsolved MainBlock. For each PossibleBlock in the MainBlock.PossibleBlock, Clones the Grid and sets the relevant PossibleBlock to be the Mainblock. /// Adds all the copied grids to a list and returns the list. /// </summary> /// <returns></returns> public List <Grid> GetGridsWithSetBlocks() { MainBlock largestUnsolved = GetLargestUnsolvedMainBlock(); GridPlusSetBlocks = new List <Grid>(); foreach (PossibleBlock possibleBlock in largestUnsolved.PossibleBlocks) { Grid newGrid = _cloneGrid.CloneGrid(); PossibleBlock toTry = GetEquivalentPossibleBlock(possibleBlock, newGrid); toTry.SetAsMainBlock(); GridPlusSetBlocks.Add(newGrid); } return(GridPlusSetBlocks); }
/// <summary> /// This cell now belongs to the block of input index /// </summary> /// <param name="index"></param> public void SetOwnership(MainBlock MBlock) { this.IsOwned = true; this.OwnedBy = MBlock.Index; MBlock.CertainCells.Add(this); Grid.SolvedCellCount++; if (Grid.Blocks[MBlock.Index].PossibleBlocks.Count == 1) { this.PossibleIndexs.Clear(); this.PossibleIndexs.Add(MBlock.Index, Grid.Blocks[MBlock.Index].PossibleBlocks); } }
/// <summary> /// Gather all possible dimension pairs based on the this.Area in the form of int[2]. Adds all the arrays to a list. /// Considers rotations of a rectangle as different dimensions. /// </summary> private List <int[]> FillPossibleDimensions(MainBlock MBlock) { List <int[]> PossibleDimensions = new List <int[]>(); { for (int i = 1; i <= MBlock.Area; i++) { if (MBlock.Area % i == 0 && MBlock.Area / i <= 7 && i <= 7) { PossibleDimensions.Add(new int[2] { i, MBlock.Area / i }); } } } return(PossibleDimensions); }
private void CreatePossibleBlocks(MainBlock MBlock) { List <int[]> PossibleDimensions = FillPossibleDimensions(MBlock); foreach (int[] dimension in PossibleDimensions) { int xOffset = dimension[0] - 1, yOffset = dimension[1] - 1; for (int i = -xOffset; i <= 0; i++) { for (int j = -yOffset; j <= 0; j++) { CreatePossibleBlock(i, j, dimension[0], dimension[1], MBlock); } } } }
/// <summary> /// Finds the MainBlock with the largest area that has not been finalised /// </summary> /// <returns></returns> private MainBlock GetLargestUnsolvedMainBlock() { //create dummy block with area = 0. Will keep track of largest un finalised MainBlock. MainBlock largestUnsolved = new MainBlock() { Area = 0 }; foreach (MainBlock MBlock in OriginalGrid.Blocks) { //If PossibleBlocks.counts != 0 then the Mainblock has not been finalised. if (MBlock.PossibleBlocks.Count != 1 && MBlock.Area > largestUnsolved.Area) { largestUnsolved = MBlock; } } return(largestUnsolved); }
/// <summary> /// Creates a possible block by adding cells to a collection. If all the cells are lie within the grid and are not owned by another block, the possible block is valid. /// If the possible block is valid it is created and added to the relevant Block.PossibleBlocks /// </summary> /// <param name="i"></param> /// <param name="j"></param> /// <param name="xDim"></param> /// <param name="yDim"></param> private void CreatePossibleBlock(int i, int j, int xDim, int yDim, MainBlock block) { //xPos and yPos represent coordinates of the TopLefTCell of the PossibleBlock. int xPos = block.DefinedCell.XPos + i, yPos = block.DefinedCell.YPos + j; HashSet <Cell> tempHash = new HashSet <Cell>(); for (int k = 0; k < xDim; k++) { for (int l = 0; l < yDim; l++) { if (Grid.AreValidCoordinates(xPos + k, yPos + l)) { Cell tempCell = Grid.Cells[xPos + k, yPos + l]; if (!tempCell.IsOwnedByBlockOtherThan(block)) { tempHash.Add(tempCell); } else { return; } } else { return; } } } PossibleBlock tempBlock = new PossibleBlock(block.Index, block.Area, block.DefinedCell, Grid) { Cells = tempHash, TopLeftCell = Grid.Cells[xPos, yPos] }; tempBlock.Dimensions[0] = xDim; tempBlock.Dimensions[1] = yDim; block.PossibleBlocks.Add(tempBlock); }
/// <summary> /// For the input MainBlock. Loops through all PossibleBlocks, removes invalid PossibleBlocks based if they do not contain Block's MustContainCells or if the PossibleBlocks /// containa cell owned by a different block. /// If a PossibleBlokc is removed the changed has occured property is marked as true. /// </summary> /// <param name="MBlock"></param> private void RemoveImpossibleBlocks(MainBlock MBlock) { //All valid Possible Blocks will be added to templist. The MainBlock.PossibleBlocks will be replaced with tempList at the end of the method. List <PossibleBlock> newPBlockList = new List <PossibleBlock>(); //If the PossibleBlock is valid it is added to the new list. foreach (PossibleBlock pBlock in MBlock.PossibleBlocks) { if (IsPBlockValid(pBlock, MBlock)) { newPBlockList.Add(pBlock); } } // if newPBock.count is different to the orignal MainBlock.PossibleBlocks.count then a change has occured and atleast 1 PossibleBlock has been removed if (newPBlockList.Count != MBlock.PossibleBlocks.Count) { ChangeHasOccured = true; } //Set PossibleBlocks List to the newly refined list MBlock.PossibleBlocks = newPBlockList; }