public WordPuzzle(List<string> wordList, int height, int width, int difficultyIndex) { //totalListChars = calculateTotalListChars(wordList); //Console.WriteLine("There is a total of " + totalListChars + " letters in the word list."); int difficulty; switch(difficultyIndex) { case 0: difficulty = 2; break; case 1: difficulty = 4; break; case 2: difficulty = 8; break; default: difficulty = 8; break; } puzzleGrid = CreateGrid(height, width); FillWords(wordList, puzzleGrid, difficulty); FillLetters(puzzleGrid); //Comment this line out for easy troubleshooting of the FillWords function }
//FillLetters takes an existing puzzle grid and fills in the empty spots with random letters private void FillLetters(WordGrid grid) { Random random = new Random(); int gridHeight = grid.Height; int gridWidth = grid.Width; for (int i = 0; i < gridHeight; i++) { for (int j = 0; j < gridWidth; j++) { if (grid.puzzle[i, j].PuzzleChar == '\0') { int letterToAdd = random.Next(65, 91); grid.puzzle[i, j].PuzzleChar = (char)letterToAdd; } } } }
private WordGrid CreateGrid(int width, int height) { WordGrid gridToCreate = new WordGrid(width, height); return gridToCreate; }
/*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; } } }
static void Main(string[] args) { // Program Prep: printLogo(); buildMenus(); string curFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); WordGrid wg; int answer; string folderName = "puzzles " + DateTime.Now.ToString("yyyy-MM-dd"); string fullPath = Path.Combine(curFolder, folderName); Directory.CreateDirectory(fullPath); // Questions: answer = question("\n\nPlease choose an option from the following:\n" + menuOptions(menu_mainMenu, 1)); // RANDOM VARIOUS PUZZLES OF ALL TYPES if (answer == 1) { answer = question("\n\nHow many puzzle files would you like to generate?\n" + menuOptions(menu_numPuzzles, 1)); int numPuzzles = (int)Math.Pow(2, (answer - 1)); Random ran = new Random(); string curPuzzle; string fileName; string filePath; string timeString; for (int i = 1; i <= numPuzzles; i++) { int puzzleSize = 5 + (5 * ran.Next(1, 5)); wg = new WordGrid(puzzleSize); int wordSize = ran.Next(4, puzzleSize - 2); int numWords = ran.Next(10, puzzleSize + 5); int wordList = ran.Next(1, 7); switch (wordList) { case 1: wg.buildWordList(wordSelections.L_fryFirstHundred, wordSize); break; case 2: wg.buildWordList(wordSelections.L_fryFirstFiveHundred, wordSize); break; case 3: wg.buildWordList(wordSelections.L_fryFirstThousand, wordSize); break; case 4: wg.buildWordList(wordSelections.L_popularComputerGames, wordSize); break; case 5: wg.buildWordList(wordSelections.L_sportsWords, wordSize); break; case 6: wg.buildWordList(wordSelections.L_piratesMedieval, wordSize); break; case 7: wg.buildWordList(wordSelections.L_xmasWords, wordSize); break; case 8: wg.buildWordList(wordSelections.L_Cobalt, wordSize); break; default: wg.buildWordList(wordSelections.L_fryFirstThousand, wordSize); break; } // end switch curPuzzle = wg.generatePuzzle(numWords); timeString = DateTime.Now.ToString("hhmmtt") + "-" + DateTime.Now.ToString("ss") + "s-"; fileName = timeString + "puzzle" + i.ToString() + ".txt"; filePath = Path.Combine(fullPath, fileName); System.IO.File.WriteAllText(@filePath, curPuzzle); } // end for } // end random generation // CUSTOM PUZZLES WITH SETTINGS: else { answer = question("How many letters wide/long would you like your puzzle?:\n" + menuOptions(menu_dimensions, 1)); int puzzleSize = 5 + 5 * answer; int wordList = question("\n\nPlease choose a word list:\n" + menuOptions(menu_wordLists, 1)); answer = question("\n\nMaximum possible word size?\n" + menuOptions(menu_wordLengths, 1)); int wordSize = 2 + answer * 2; answer = question("\n\nHow many words will each puzzle contain?\n" + menuOptions(menu_numWords, 1)); int numWords = answer * 5; answer = question("\n\nHow many puzzle files would you like to generate?\n" + menuOptions(menu_numPuzzles, 1)); int numPuzzles = (int)Math.Pow(2, (answer - 1)); // Generate Puzzle(s): wg = new WordGrid(puzzleSize); switch (wordList) { case 1: wg.buildWordList(wordSelections.L_fryFirstHundred, wordSize); break; case 2: wg.buildWordList(wordSelections.L_fryFirstFiveHundred, wordSize); break; case 3: wg.buildWordList(wordSelections.L_fryFirstThousand, wordSize); break; case 4: wg.buildWordList(wordSelections.L_popularComputerGames, wordSize); break; case 5: wg.buildWordList(wordSelections.L_sportsWords, wordSize); break; case 6: wg.buildWordList(wordSelections.L_piratesMedieval, wordSize); break; case 7: wg.buildWordList(wordSelections.L_xmasWords, wordSize); break; case 8: wg.buildWordList(wordSelections.L_Cobalt, wordSize); break; default: wg.buildWordList(wordSelections.L_fryFirstThousand, wordSize); break; } string curPuzzle; string fileName; string filePath; string timeString; for (int i = 1; i <= numPuzzles; i++) { curPuzzle = wg.generatePuzzle(numWords); timeString = DateTime.Now.ToString("hhmmtt") + "-" + DateTime.Now.ToString("ss") + "s-"; fileName = timeString + "puzzle" + i.ToString() + ".txt"; filePath = Path.Combine(fullPath, fileName); System.IO.File.WriteAllText(@filePath, curPuzzle); } } // Success and Exit: Console.Write("\n\n"); Console.WriteLine("Puzzles generated at the following file location:"); Console.WriteLine(curFolder); Console.WriteLine("Press any key to exit"); Console.ReadKey(); } // end main