internal virtual void Initialize(int width, int height) { this.width = width; this.height = height; for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { dancer.AddColumn(new Pentomino.Point(x, y)); } } int pieceBase = dancer.GetNumberColumns(); foreach (Pentomino.Piece p in pieces) { dancer.AddColumn(p); } bool[] row = new bool[dancer.GetNumberColumns()]; for (int idx = 0; idx < pieces.Count; ++idx) { Pentomino.Piece piece = pieces[idx]; row[idx + pieceBase] = true; GenerateRows(dancer, piece, width, height, false, row, idx == 0); if (piece.GetFlippable()) { GenerateRows(dancer, piece, width, height, true, row, idx == 0); } row[idx + pieceBase] = false; } printer = new Pentomino.SolutionPrinter(width, height); }
/// <summary> /// Convert a solution to the puzzle returned by the model into a string /// that represents the placement of the pieces onto the board. /// </summary> /// <param name="width">the width of the puzzle board</param> /// <param name="height">the height of the puzzle board</param> /// <param name="solution">the list of column names that were selected in the model</param> /// <returns>a string representation of completed puzzle board</returns> public static string StringifySolution(int width, int height, IList <IList <Pentomino.ColumnName > > solution) { //String[][] picture = new String[height][width]; //HM: Line above replaced with the one below due to the 2nd dim array string[][] picture = new string[height][]; StringBuilder result = new StringBuilder(); // for each piece placement... foreach (IList <Pentomino.ColumnName> row in solution) { // go through to find which piece was placed Pentomino.Piece piece = null; foreach (Pentomino.ColumnName item in row) { if (item is Pentomino.Piece) { piece = (Pentomino.Piece)item; break; } } // for each point where the piece was placed, mark it with the piece name foreach (Pentomino.ColumnName item_1 in row) { if (item_1 is Pentomino.Point) { Pentomino.Point p = (Pentomino.Point)item_1; picture[p.y][p.x] = piece.GetName(); } } } // put the string together for (int y = 0; y < picture.Length; ++y) { for (int x = 0; x < picture[y].Length; ++x) { result.Append(picture[y][x]); } result.Append("\n"); } return(result.ToString()); }
/// <summary> /// For a given piece, generate all of the potential placements and add them /// as rows to the model. /// </summary> /// <param name="dancer">the problem model</param> /// <param name="piece">the piece we are trying to place</param> /// <param name="width">the width of the board</param> /// <param name="height">the height of the board</param> /// <param name="flip">is the piece flipped over?</param> /// <param name="row">a workspace the length of the each row in the table</param> /// <param name="upperLeft"> /// is the piece constrained to the upper left of the board? /// this is used on a single piece to eliminate most of the trivial /// roations of the solution. /// </param> private static void GenerateRows(DancingLinks dancer, Pentomino.Piece piece, int width, int height, bool flip, bool[] row, bool upperLeft) { // for each rotation int[] rotations = piece.GetRotations(); for (int rotIndex = 0; rotIndex < rotations.Length; ++rotIndex) { // get the shape bool[][] shape = piece.GetShape(flip, rotations[rotIndex]); // find all of the valid offsets for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { if (y + shape.Length <= height && x + shape[0].Length <= width && (!upperLeft || (IsSide(x, shape[0].Length, width) && IsSide(y, shape.Length, height)))) { // clear the columns related to the points on the board for (int idx = 0; idx < width * height; ++idx) { row[idx] = false; } // mark the shape for (int subY = 0; subY < shape.Length; ++subY) { for (int subX = 0; subX < shape[0].Length; ++subX) { row[(y + subY) * width + x + subX] = shape[subY][subX]; } } dancer.AddRow(row); } } } } }
/// <summary> /// Find whether the solution has the x in the upper left quadrant, the /// x-midline, the y-midline or in the center. /// </summary> /// <param name="names">the solution to check</param> /// <returns>the catagory of the solution</returns> public virtual Pentomino.SolutionCategory GetCategory(IList <IList <Pentomino.ColumnName > > names) { Pentomino.Piece xPiece = null; // find the "x" piece foreach (Pentomino.Piece p in pieces) { if ("x".Equals(p.name)) { xPiece = p; break; } } // find the row containing the "x" foreach (IList <Pentomino.ColumnName> row in names) { if (row.Contains(xPiece)) { // figure out where the "x" is located int low_x = width; int high_x = 0; int low_y = height; int high_y = 0; foreach (Pentomino.ColumnName col in row) { if (col is Pentomino.Point) { int x = ((Pentomino.Point)col).x; int y = ((Pentomino.Point)col).y; if (x < low_x) { low_x = x; } if (x > high_x) { high_x = x; } if (y < low_y) { low_y = y; } if (y > high_y) { high_y = y; } } } bool mid_x = (low_x + high_x == width - 1); bool mid_y = (low_y + high_y == height - 1); if (mid_x && mid_y) { return(Pentomino.SolutionCategory.Center); } else { if (mid_x) { return(Pentomino.SolutionCategory.MidX); } else { if (mid_y) { return(Pentomino.SolutionCategory.MidY); } } } break; } } return(Pentomino.SolutionCategory.UpperLeft); }