private Letter[,] CopyArray(Letter[,] sourceArray) { int height = sourceArray.GetLength(0); int width = sourceArray.GetLength(1); Letter[,] copyOfArray = new Letter[height, width]; Array.Copy(sourceArray, copyOfArray, height * width); return copyOfArray; }
//Add a visible letter to the letters panel at the specified position private TransparentLetter AddLetter(Letter labelLetter, int x, int y) { char labelChar = labelLetter.PuzzleChar; bool isPartOfWord = labelLetter.IsPartOfWord; TransparentLetter newLabel = new TransparentLetter(isPartOfWord); newLabel.Font = new Font("Microsoft Sans Serif", 9F, FontStyle.Bold, GraphicsUnit.Point, ((byte)(0))); newLabel.Text = new string(labelChar, 1); newLabel.Location = new Point(x, y); newLabel.TextAlign = ContentAlignment.MiddleCenter; return newLabel; }
//Place the panels in the appropriate places on the form private void DisplayPuzzle(WordPuzzle wordPuzzle) { lettersPanel = new Panel(); WordGrid gridToParse = wordPuzzle.puzzleGrid; for (int i = 0; i < gridToParse.Height; i++) { for (int j = 0; j < gridToParse.Width; j++) { Letter letterAtGridLoc = gridToParse.puzzle[i, j]; char charAtGridLoc = letterAtGridLoc.PuzzleChar; bool isLetterInWord; isLetterInWord = letterAtGridLoc.IsPartOfWord; int charXLoc = j * 20 + 10; int charYloc = i * 20 + 5; Letter addThisLetter = new Letter(charAtGridLoc, isLetterInWord); TransparentLetter letterToAdd = AddLetter(letterAtGridLoc, charXLoc, charYloc); lettersPanel.Controls.Add(letterToAdd); } } puzzleHeight = gridToParse.Height * 20 + 10; puzzleWidth = gridToParse.Width * 20 + 15; lettersPanel.Size = new Size(puzzleWidth, puzzleHeight); lettersPanel.Location = new Point(20, 50); lettersPanel.BorderStyle = BorderStyle.FixedSingle; }
/*FillWords takes the list of words created in Form1, randomly chooses an orientation for each word, * and then inserts each word into the puzzle. */ private void FillWords(List<string> listOfWords, WordGrid grid, int difficulty) { wordLocs = new Dictionary<string, Point>(); Random random = new Random(); int puzzleHeight = grid.Height; int puzzleWidth = grid.Width; Array orientations = Enum.GetValues(typeof(orientation)); foreach (string word in listOfWords) { int startingRow; int startingCol; orientation randomOrientation = (orientation)orientations.GetValue(random.Next(difficulty)); char[] wordChars = word.ToCharArray(); /* In the following switch loop, we establish an orientation for the word. It can be one of eight possible * orientations. At the beginning of the while loop, a copy of the existing puzzle grid is created. If there * is a conflicting letter at a place where the algorithm is trying to write a letter, the loop will restart. * This allows for overlapping words without conflict. */ switch (randomOrientation) { case orientation.HorFor: { bool okay = false; while (!okay) { Letter[,] testGrid = CopyArray(grid.puzzle); okay = true; int maxStartCol = puzzleWidth - word.Length; startingRow = random.Next(puzzleHeight); startingCol = random.Next(maxStartCol); Point startPoint = new Point(startingRow, startingCol); int currentCol = startingCol; for (int i = 0; i < wordChars.Length; i++) { if (testGrid[startingRow, currentCol].PuzzleChar != '\0' && testGrid[startingRow, currentCol].PuzzleChar != wordChars[i]) { okay = false; break; } else { testGrid[startingRow, currentCol] = new Letter(wordChars[i], true); currentCol++; } } if (okay) { grid.puzzle = CopyArray(testGrid); wordLocs.Add(word, startPoint); } } } break; case orientation.VertFor: { bool okay = false; while (!okay) { Letter[,] testGrid = CopyArray(grid.puzzle); okay = true; int maxStartRow = puzzleHeight - word.Length; startingRow = random.Next(maxStartRow); startingCol = random.Next(puzzleWidth); Point startPoint = new Point(startingRow, startingCol); int currentRow = startingRow; for (int i = 0; i < wordChars.Length; i++) { if (testGrid[currentRow, startingCol].PuzzleChar != '\0' && testGrid[currentRow, startingCol].PuzzleChar != wordChars[i]) { okay = false; break; } else { testGrid[currentRow, startingCol] = new Letter(wordChars[i], true); currentRow++; } } if (okay) { grid.puzzle = CopyArray(testGrid); wordLocs.Add(word, startPoint); } } } break; case orientation.HorRev: { bool okay = false; while (!okay) { Letter[,] testGrid = CopyArray(grid.puzzle); okay = true; int minStartCol = wordChars.Length; //We're going backwards, so we don't want to start too close the left edge startingRow = random.Next(puzzleHeight); startingCol = random.Next(minStartCol, puzzleWidth); Point startPoint = new Point(startingRow, startingCol); int currentCol = startingCol; for (int i = 0; i < wordChars.Length; i++) { if (testGrid[startingRow, currentCol].PuzzleChar != '\0' && testGrid[startingRow, currentCol].PuzzleChar != wordChars[i]) { okay = false; break; } else { testGrid[startingRow, currentCol] = new Letter(wordChars[i], true); currentCol--; } } if (okay) { grid.puzzle = CopyArray(testGrid); wordLocs.Add(word, startPoint); } } } break; case orientation.VertRev: { bool okay = false; while (!okay) { Letter[,] testGrid = CopyArray(grid.puzzle); okay = true; int minStartRow = wordChars.Length; startingRow = random.Next(minStartRow, puzzleHeight); startingCol = random.Next(puzzleWidth); Point startPoint = new Point(startingRow, startingCol); int currentRow = startingRow; for (int i = 0; i < wordChars.Length; i++) { if (testGrid[currentRow, startingCol].PuzzleChar != '\0' && testGrid[currentRow, startingCol].PuzzleChar != wordChars[i]) { //There's a conflict here. Defer to the existing state and start this word over with a new random location okay = false; break; } else { testGrid[currentRow, startingCol] = new Letter(wordChars[i], true); currentRow--; } } if (okay) { grid.puzzle = CopyArray(testGrid); wordLocs.Add(word, startPoint); } } } break; case orientation.SlashFor: //Diagonal word populated up and to the right from the start location { bool okay = false; while (!okay) { Letter[,] testGrid = CopyArray(grid.puzzle); okay = true; int minStartRow = wordChars.Length; int maxStartCol = puzzleWidth - wordChars.Length; startingRow = random.Next(minStartRow, puzzleHeight); startingCol = random.Next(0, maxStartCol); Point startPoint = new Point(startingRow, startingCol); int currentRow = startingRow; int currentCol = startingCol; for (int i = 0; i < wordChars.Length; i++) { if (testGrid[currentRow, currentCol].PuzzleChar != '\0' && testGrid[currentRow, currentCol].PuzzleChar != wordChars[i]) { okay = false; break; } else { testGrid[currentRow, currentCol] = new Letter(wordChars[i], true); currentRow--; currentCol++; } } if (okay) { grid.puzzle = CopyArray(testGrid); wordLocs.Add(word, startPoint); } } } break; case orientation.SlashRev: //Diagonal word populated down and to the left from the start location { bool okay = false; while (!okay) { Letter[,] testGrid = CopyArray(grid.puzzle); okay = true; int maxStartRow = puzzleHeight - wordChars.Length; int minStartCol = wordChars.Length; startingRow = random.Next(0, maxStartRow); startingCol = random.Next(minStartCol, puzzleWidth); Point startPoint = new Point(startingRow, startingCol); int currentRow = startingRow; int currentCol = startingCol; for (int i = 0; i < wordChars.Length; i++) { if (testGrid[currentRow, currentCol].PuzzleChar != '\0' && testGrid[currentRow, currentCol].PuzzleChar != wordChars[i]) { okay = false; break; } else { testGrid[currentRow, currentCol] = new Letter(wordChars[i], true); currentRow++; currentCol--; } } if (okay) { grid.puzzle = CopyArray(testGrid); wordLocs.Add(word, startPoint); } } } break; case orientation.BackslashFor: //Diagonal word populated down and to the right from the start location { bool okay = false; while (!okay) { Letter[,] testGrid = CopyArray(grid.puzzle); okay = true; int maxStartRow = puzzleHeight - wordChars.Length; int maxStartCol = puzzleWidth - wordChars.Length; startingRow = random.Next(0, maxStartRow); startingCol = random.Next(0, maxStartCol); Point startPoint = new Point(startingRow, startingCol); int currentRow = startingRow; int currentCol = startingCol; for (int i = 0; i < wordChars.Length; i++) { if (testGrid[currentRow, currentCol].PuzzleChar != '\0' && testGrid[currentRow, currentCol].PuzzleChar != wordChars[i]) { okay = false; break; } else { testGrid[currentRow, currentCol] = new Letter(wordChars[i], true); currentRow++; currentCol++; } } if (okay) { grid.puzzle = CopyArray(testGrid); wordLocs.Add(word, startPoint); } } } break; case orientation.BackslashRev: //Diagonal word populated up and to the left from the starting position { bool okay = false; while (!okay) { Letter[,] testGrid = CopyArray(grid.puzzle); okay = true; int minStartRow = wordChars.Length; int minStartCol = wordChars.Length; startingRow = random.Next(minStartRow, puzzleWidth); startingCol = random.Next(minStartCol, puzzleHeight); Point startPoint = new Point(startingRow, startingCol); int currentRow = startingRow; int currentCol = startingCol; for (int i = 0; i < wordChars.Length; i++) { if (testGrid[currentRow, currentCol].PuzzleChar != '\0' && testGrid[currentRow, currentCol].PuzzleChar != wordChars[i]) { okay = false; break; } else { testGrid[currentRow, currentCol] = new Letter(wordChars[i], true); currentRow--; currentCol--; } } if (okay) { grid.puzzle = CopyArray(testGrid); wordLocs.Add(word, startPoint); } } } break; default: //should never reach here, but the default will be a horizontal, forward word MessageBox.Show("A word orientation is not being properly selected", "Oh Dear"); break; } } }
private Letter[] Next(Letter[][] letters, string word, int length) { List<Point> all = new List<Point>(AllPoints(length)); while (all.Count > 0) { int index = rand.Next(0, all.Count); List<Direction> dirs = new List<Direction>(AllDirections()); while (dirs.Count > 0) { int index2 = rand.Next(0, dirs.Count); Direction current = dirs[index2]; Letter[] c = Construct(all[index], current, word, length); bool legal = true; for (int i = 0; i < c.Length; i++) { if (c[i].X < 0 || c[i].X >= length || c[i].Y < 0 || c[i].Y >= length) { legal = false; break; } else { for (int j = 0; j < letters.Length; j++) { Point[] pts = letters[j].Select<Letter, Point>(t => new Point(t.X, t.Y)).ToArray(); int _index2 = pts.ToList().FindIndex(t => t.X == c[i].X && t.Y == c[i].Y); if (_index2 != -1) if (c[i]._Letter != letters[j][_index2]._Letter) legal = false; } } } if (legal) return c; dirs.RemoveAt(index2); } all.RemoveAt(index); } return null; }
private char[,] From(Letter[][] grid, int length) { char[,] _grid = new char[length, length]; for (int j = 0; j < grid.Length; j++) { Letter[] current = grid[j]; for (int i = 0; i < current.Length; i++) { _grid[current[i].X, current[i].Y] = current[i]._Letter; } } return _grid; }
private Letter[] Construct(Point p, Direction dir, string word, int length) { Letter[] array = new Letter[word.Length]; Point last = p; for (int i = 0; i < word.Length; i++) { array[i] = new Letter(word[i], last); switch (dir) { case Direction.E: last.X++; break; case Direction.N: last.Y--; break; case Direction.Ne: last.Y--; last.X++; break; case Direction.Nw: last.Y--; last.X--; break; case Direction.S: last.Y++; break; case Direction.Se: last.Y++; last.X++; break; case Direction.Sw: last.Y++; last.X--; break; case Direction.W: last.X--; break; } } return array; }