// This part does the work and is called link by link private static void PuzzleSolverInnerLoop(BlockPuzzle blockPuzzle, BlockLine.BlockLineOrientation nextOrientation) { // If you're not done, keep working! if (!blockPuzzle.IsFinished) { // Try to add the requested orientation if (blockPuzzle.AddBlockLine(nextOrientation)) { // If adding the requested block succeeds, try to add another block in each direction! PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Left); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Right); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Up); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Down); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Front); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Back); // Once all directions have been tried, unroll the block you just placed from the master list blockPuzzle.RemovePreviousBlockLine(); } } }
// Add the next blockline in the direction provided public bool AddBlockLine(BlockLine.BlockLineOrientation orientation) { // For fun, increment the number of total positions considered this.PositionCount++; BlockLine.BlockLineOrientation lastBlockOrientation; bool additionSuccess = false; int numBlocks = this.BlockLineOrder[this.BlockLineIndex]; BlockLine addedBlock = new BlockLine(numBlocks, orientation); if (this.ListOfBlocks.Count == 0) { // This is the first block, so we need to add one block addedBlock.NumBlocks++; addedBlock.StartPoint = new Point(0, 0, 0); addedBlock.EndPoint = new Point(0, 0, addedBlock.NumBlocks - 1); this.SpaceCheckAndReserve(addedBlock, new Point(0, 0, 1)); additionSuccess = true; } else { // Find out what direction the last block line went in order to determine where the next one can go // Block lines are always at 90 degress to the last line lastBlockOrientation = ListOfBlocks[ListOfBlocks.Count - 1].Orientation; switch (orientation) { case BlockLine.BlockLineOrientation.Back: if (lastBlockOrientation != BlockLine.BlockLineOrientation.Back && lastBlockOrientation != BlockLine.BlockLineOrientation.Front) { addedBlock.StartPoint = new Point(this.EndingPoint.XPos, this.EndingPoint.YPos + 1, this.EndingPoint.ZPos); addedBlock.EndPoint = new Point(this.EndingPoint.XPos, this.EndingPoint.YPos + numBlocks, this.EndingPoint.ZPos); // Will it fit in the 4x4 grid? And is there space? if (this.BoundsCheck(addedBlock)) { if (this.SpaceCheckAndReserve(addedBlock, new Point(0, 1, 0))) { additionSuccess = true; } } } break; case BlockLine.BlockLineOrientation.Front: if (lastBlockOrientation != BlockLine.BlockLineOrientation.Back && lastBlockOrientation != BlockLine.BlockLineOrientation.Front) { addedBlock.StartPoint = new Point(this.EndingPoint.XPos, this.EndingPoint.YPos - 1, this.EndingPoint.ZPos); addedBlock.EndPoint = new Point(this.EndingPoint.XPos, this.EndingPoint.YPos - numBlocks, this.EndingPoint.ZPos); // Will it fit in the 4x4 grid? And is there space? if (this.BoundsCheck(addedBlock)) { if (this.SpaceCheckAndReserve(addedBlock, new Point(0, -1, 0))) { additionSuccess = true; } } } break; case BlockLine.BlockLineOrientation.Left: if (lastBlockOrientation != BlockLine.BlockLineOrientation.Left && lastBlockOrientation != BlockLine.BlockLineOrientation.Right) { addedBlock.StartPoint = new Point(this.EndingPoint.XPos - 1, this.EndingPoint.YPos, this.EndingPoint.ZPos); addedBlock.EndPoint = new Point(this.EndingPoint.XPos - numBlocks, this.EndingPoint.YPos, this.EndingPoint.ZPos); // Will it fit in the 4x4 grid? And is there space? if (this.BoundsCheck(addedBlock)) { if (this.SpaceCheckAndReserve(addedBlock, new Point(-1, 0, 0))) { additionSuccess = true; } } } break; case BlockLine.BlockLineOrientation.Right: if (lastBlockOrientation != BlockLine.BlockLineOrientation.Left && lastBlockOrientation != BlockLine.BlockLineOrientation.Right) { addedBlock.StartPoint = new Point(this.EndingPoint.XPos + 1, this.EndingPoint.YPos, this.EndingPoint.ZPos); addedBlock.EndPoint = new Point(this.EndingPoint.XPos + numBlocks, this.EndingPoint.YPos, this.EndingPoint.ZPos); // Will it fit in the 4x4 grid? And is there space? if (this.BoundsCheck(addedBlock)) { if (this.SpaceCheckAndReserve(addedBlock, new Point(1, 0, 0))) { additionSuccess = true; } } } break; case BlockLine.BlockLineOrientation.Up: if (lastBlockOrientation != BlockLine.BlockLineOrientation.Up && lastBlockOrientation != BlockLine.BlockLineOrientation.Down) { addedBlock.StartPoint = new Point(this.EndingPoint.XPos, this.EndingPoint.YPos, this.EndingPoint.ZPos + 1); addedBlock.EndPoint = new Point(this.EndingPoint.XPos, this.EndingPoint.YPos, this.EndingPoint.ZPos + numBlocks); // Will it fit in the 4x4 grid? And is there space? if (this.BoundsCheck(addedBlock)) { if (this.SpaceCheckAndReserve(addedBlock, new Point(0, 0, 1))) { additionSuccess = true; } } } break; case BlockLine.BlockLineOrientation.Down: if (lastBlockOrientation != BlockLine.BlockLineOrientation.Up && lastBlockOrientation != BlockLine.BlockLineOrientation.Down) { addedBlock.StartPoint = new Point(this.EndingPoint.XPos, this.EndingPoint.YPos, this.EndingPoint.ZPos - 1); addedBlock.EndPoint = new Point(this.EndingPoint.XPos, this.EndingPoint.YPos, this.EndingPoint.ZPos - numBlocks); // Will it fit in the 4x4 grid? And is there space? if (this.BoundsCheck(addedBlock)) { if (this.SpaceCheckAndReserve(addedBlock, new Point(0, 0, -1))) { additionSuccess = true; } } } break; } } // Add the block to the list if (additionSuccess) { this.ListOfBlocks.Add(addedBlock); this.EndingPoint = addedBlock.EndPoint; this.BlockLineIndex++; // If you find the 0 termination at the end of the list, you're done! if (this.BlockLineOrder[this.BlockLineIndex] == 0) { this.IsFinished = true; Console.WriteLine("==Solution=================================================================================="); this.PrintPuzzle(); } } return(additionSuccess); }