Exemplo n.º 1
0
		/// <summary>
		/// Solves the boggle board!
		/// </summary>
		/// <param name="board">Board to solve.</param>
		/// <param name="library">Dictionary of words.</param>
		public Result Solve(IBoard board, ILibrary library)
		{
			var result = new Result();
			result.Words = new HashSet<string>();
			var start = Environment.TickCount;

			var tasks = new List<Task>();

			for (int i = 0; i < board.Width; i++)
			{
				for (int j = 0; j < board.Height; j++)
				{
					// Capture i/j values (will fail without since i/j change too fast before the thread runs)
					var state = new ThreadState(i, j);

					// note: I'm sure this is a lot of memory spawning a bajillion tasks but it was easy.
					tasks.Add(Task.Run(() =>
					{

						var path = new WordPath(board.Grid[state.X][state.Y], state.X, state.Y);
						var myWords = Worker(
							state.X, 
							state.Y, 
							path, 
							1, 
							board, 
							library.Books[board.Grid[state.X][state.Y]], 
							new HashSet<string>());

						// Merge results (queue up instead and have the main thread do the work?
						// This seems like a bottle neck but since tasks are not reused it might not matter.
						lock (_mergeResultsLock)
						{
							result.Words.UnionWith(myWords);
						}
					
					}));
				}
			}

			Task.WaitAll(tasks.ToArray());

			var stop = Environment.TickCount;
			result.ElapsedMS = stop - start;

			return result;
		}
Exemplo n.º 2
0
		/// <summary>
		/// Worker thread for a single square in the boggle grid.
		/// </summary>
		/// <param name="x">X grid position.</param>
		/// <param name="y">Y grid position.</param>
		/// <param name="path">Word Path object.</param>
		/// <param name="depth">Current number of squares deep, maximum is 32.</param>
		/// <param name="board">The boggle board.</param>
		/// <param name="parent">The parent node, when first called this is the first letter in the word's book from the dictionary.</param>
		/// <param name="words">The words this worker has found on the boggle board.</param>
		/// <returns></returns>
		private HashSet<string> Worker(
			int x, 
			int y, 
			WordPath 
			path, int 
			depth, 
			IBoard board, 
			ILetter parent, 
			HashSet<string> words)
		{
			var c = board.Grid[x][y];

			for (int i = 0; i < 8; i++)
			{
				var nX = x + _neighbors[i][0];
				var nY = y + _neighbors[i][1];

				// check for out of bounds
				if (nX < 0 ||
					nX >= board.Width)
					continue;

				if (nY < 0 ||
					nY >= board.Height)
					continue;

				// do not re-use tiles, and do not check your own level
				if (path.AlreadyVisited(nX, nY, depth - 1))
					continue;

				var nC = board.Grid[nX][nY];
				path.Set(nC, nX, nY, depth);

				if (parent.Children.ContainsKey(nC))
				{
					var word = string.Concat(path.Letters.Take(depth + 1).Select(letter => (char)letter));
					//var word = System.Text.Encoding.UTF8.GetString(path.Letters.Take(depth + 1).ToArray());

					var child = parent.Children[nC];

					if (child.IsWord)
					{
						if (!child.IsFound)
						{
							words.Add(word);
							child.IsFound = true;
						}
					}

					// maximum recursion should be maximum word length (28~)
					Worker(nX, nY, path, depth + 1, board, child, words);
				}
			}

			return words;
		}