Skip to content

Commit

Permalink
Merge pull request #93 from dotnet/word-search
Browse files Browse the repository at this point in the history
Word Search
  • Loading branch information
ZacharyPatten committed Dec 12, 2023
2 parents f91a6cf + cfc78d1 commit 7ce9777
Show file tree
Hide file tree
Showing 14 changed files with 934 additions and 289 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/Word Search Build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Word Search Build
on:
push:
paths:
- 'Projects/Word Search/**'
- '!**.md'
pull_request:
paths:
- 'Projects/Word Search/**'
- '!**.md'
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-dotnet@v3
with:
dotnet-version: 8.0.x
- run: dotnet build "Projects\Word Search\Word Search.csproj" --configuration Release
10 changes: 10 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,16 @@
"console": "externalTerminal",
"stopAtEntry": false,
},
{
"name": "Word Search",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "Build Word Search",
"program": "${workspaceFolder}/Projects/Word Search/bin/Debug/Word Search.dll",
"cwd": "${workspaceFolder}/Projects/Word Search/bin/Debug",
"console": "externalTerminal",
"stopAtEntry": false,
},
{
"name": "Pong",
"type": "coreclr",
Expand Down
13 changes: 13 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,19 @@
],
"problemMatcher": "$msCompile",
},
{
"label": "Build Word Search",
"command": "dotnet",
"type": "process",
"args":
[
"build",
"${workspaceFolder}/Projects/Word Search/Word Search.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary",
],
"problemMatcher": "$msCompile",
},
{
"label": "Build Solution",
"command": "dotnet",
Expand Down
31 changes: 16 additions & 15 deletions Projects/Tug Of War/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,22 @@
new string(' ', 2);
bool frame_a = false;
Console.Clear();
Console.WriteLine(@"
Tug Of War
Out pull your opponent in a rope pulling
competition. Mash the [left]+[right] arrow
keys and/or the [A]+[D] keys to pull on the
rope. First player to pull the center of the
rope into their boundary wins.
Choose Your Opponent:
[1] Easy.......2 mashes per second
[2] Medium.....4 mashes per second
[3] Hard.......8 mashes per second
[4] Harder....16 mashes per second
[escape] give up");
Console.Write("""
Tug Of War

Out pull your opponent in a rope pulling
competition. Mash the [left]+[right] arrow
keys and/or the [A]+[D] keys to pull on the
rope. First player to pull the center of the
rope into their boundary wins.

Choose Your Opponent:
[1] Easy.......2 mashes per second
[2] Medium.....4 mashes per second
[3] Hard.......8 mashes per second
[4] Harder....16 mashes per second
[escape] give up
""");
int? requiredMash = null;
while (requiredMash is null)
{
Expand Down
31 changes: 16 additions & 15 deletions Projects/Website/Games/Tug Of War/Tug Of War.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,22 @@ public async Task Run()
new string(' ', 2);
bool frame_a = false;
await Console.Clear();
await Console.WriteLine(@"
Tug Of War
Out pull your opponent in a rope pulling
competition. Mash the [left]+[right] arrow
keys and/or the [A]+[D] keys to pull on the
rope. First player to pull the center of the
rope into their boundary wins.
Choose Your Opponent:
[1] Easy.......2 mashes per second
[2] Medium.....4 mashes per second
[3] Hard.......8 mashes per second
[4] Harder....16 mashes per second
[escape] give up");
await Console.Write("""
Tug Of War

Out pull your opponent in a rope pulling
competition. Mash the [left]+[right] arrow
keys and/or the [A]+[D] keys to pull on the
rope. First player to pull the center of the
rope into their boundary wins.

Choose Your Opponent:
[1] Easy.......2 mashes per second
[2] Medium.....4 mashes per second
[3] Hard.......8 mashes per second
[4] Harder....16 mashes per second
[escape] give up
""");
int? requiredMash = null;
while (requiredMash is null)
{
Expand Down
225 changes: 225 additions & 0 deletions Projects/Website/Games/Word Search/Word Search.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Website.Games.Word_Search;

public class Word_Search
{
public readonly BlazorConsole Console = new();

public async Task Run()
{
char[,] board = new char[20, 20];
List<(int Left, int Top)> showWordSelections = [];
List<(int Left, int Top)> selections = [];

string[] wordArray = default!;
string currentWord = default!;
(int Left, int Top) cursor = (0, 0);

InitializeWords();
PlayAgain:
InitializeBoard();
await Console.Clear();
while (true)
{
await RenderBoard();
await Console.Write($"""

Highlight the word "{currentWord}" above.

Controls:
- arrow keys: move cursor
- enter: highlight characters
- backspace: clear highlighted characters
- home: new word search
- end: give up and show word
- escape: close game
""");
await Console.SetCursorPosition(2 * cursor.Left, cursor.Top);
Console.CursorVisible = true;
switch ((await Console.ReadKey(true)).Key)
{
case ConsoleKey.LeftArrow: cursor.Left = cursor.Left <= 0 ? board.GetLength(0) - 1 : cursor.Left - 1; break;
case ConsoleKey.RightArrow: cursor.Left = cursor.Left >= board.GetLength(0) - 1 ? 0 : cursor.Left + 1; break;
case ConsoleKey.UpArrow: cursor.Top = cursor.Top <= 0 ? board.GetLength(1) - 1 : cursor.Top - 1; break;
case ConsoleKey.DownArrow: cursor.Top = cursor.Top >= board.GetLength(1) - 1 ? 0 : cursor.Top + 1; break;
case ConsoleKey.Backspace: selections.Clear(); break;
case ConsoleKey.Home: goto PlayAgain;
case ConsoleKey.End:
selections.Clear();
selections.AddRange(showWordSelections);
await Console.Clear();
await RenderBoard();
await Console.Write($"""

Here is where "{currentWord}" was hiding.

Controls:
- enter/home: play again
- escape: close game
""");
while (true)
{
switch ((await Console.ReadKey(true)).Key)
{
case ConsoleKey.Enter or ConsoleKey.Home: goto PlayAgain;
case ConsoleKey.Escape: goto Close;
}
}
case ConsoleKey.Escape: goto Close;
case ConsoleKey.Enter:
if (!selections.Remove(cursor))
{
selections.Add(cursor);
selections.Sort();
if (UserFoundTheWord())
{
await Console.Clear();
await RenderBoard();
await Console.Write($"""

You found "{currentWord}"! You win!

Controls:
- enter/home: play again
- escape: close game
""");
while (true)
{
switch ((await Console.ReadKey(true)).Key)
{
case ConsoleKey.Enter or ConsoleKey.Home: goto PlayAgain;
case ConsoleKey.Escape: goto Close;
}
}
}
}
break;
}
}
Close:
await Console.Clear();
await Console.WriteLine("Word Search was closed.");
await Console.Refresh();

void InitializeWords()
{
wordArray = Resources.Words!.Select(word => word.ToUpper()).ToArray();
}

void InitializeBoard()
{
selections.Clear();

for (int i = 0; i < board.GetLength(1); i++)
{
for (int j = 0; j < board.GetLength(0); j++)
{
board[j, i] = (char)('A' + Random.Shared.Next(26));
}
}

currentWord = wordArray[Random.Shared.Next(wordArray.Length)];

// choose a random orientation for the word (down, right, left, up, down-right, down-left, up-right, or up-left)
bool r((int Left, int Top) location) => location.Left + currentWord.Length < board.GetLength(0);
bool d((int Left, int Top) location) => location.Top + currentWord.Length < board.GetLength(1);
bool l((int Left, int Top) location) => location.Left - currentWord.Length >= 0;
bool u((int Left, int Top) location) => location.Top - currentWord.Length >= 0;
bool dr((int Left, int Top) location) => d(location) && r(location);
bool dl((int Left, int Top) location) => d(location) && l(location);
bool ur((int Left, int Top) location) => u(location) && r(location);
bool ul((int Left, int Top) location) => u(location) && l(location);
(Func<(int Left, int Top), bool> Validator, (int Left, int Top) Adjustment) orientation = Random.Shared.Next(8) switch
{
0 => (d, (0, 1)),
1 => (r, (1, 0)),
2 => (u, (0, -1)),
3 => (l, (-1, 0)),
4 => (dr, (1, 1)),
5 => (dl, (-1, 1)),
6 => (ur, (1, -1)),
7 => (ul, (-1, -1)),
_ => throw new NotImplementedException(),
};

// choose a random starting location that is valid for the orientation
List<(int Left, int Top)> possibleLocations = [];
for (int i = 0; i < board.GetLength(1); i++)
{
for (int j = 0; j < board.GetLength(0); j++)
{
if (orientation.Validator((j, i)))
{
possibleLocations.Add((j, i));
}
}
}
(int Left, int Top) randomLocation = possibleLocations[Random.Shared.Next(possibleLocations.Count)];

showWordSelections.Clear();
for (int i = 0; i < currentWord.Length; i++)
{
showWordSelections.Add(randomLocation);
board[randomLocation.Left, randomLocation.Top] = currentWord[i];
randomLocation = (randomLocation.Left + orientation.Adjustment.Left, randomLocation.Top + orientation.Adjustment.Top);
}
}

async Task RenderBoard()
{
Console.CursorVisible = false;
await Console.SetCursorPosition(0, 0);
for (int i = 0; i < board.GetLength(1); i++)
{
for (int j = 0; j < board.GetLength(0); j++)
{
if (selections.Contains((j, i)))
{
(Console.ForegroundColor, Console.BackgroundColor) = (Console.BackgroundColor, Console.ForegroundColor);
}
await Console.Write(board[j, i]);
if (selections.Contains((j, i)))
{
(Console.ForegroundColor, Console.BackgroundColor) = (Console.BackgroundColor, Console.ForegroundColor);
}
if (j < board.GetLength(1) - 1)
{
await Console.Write(' ');
}
}
await Console.WriteLine();
}
}

bool UserFoundTheWord()
{
// make sure all the selections are in a straight line
if (selections.Count > 1)
{
(int Left, int Top) adjustment = (selections[1].Left - selections[0].Left, selections[1].Top - selections[0].Top);
if (adjustment.Left > 1 || adjustment.Left < -1 || adjustment.Top > 1 || adjustment.Top < -1)
{
return false;
}
for (int i = 2; i < selections.Count; i++)
{
if ((selections[i].Left - selections[i - 1].Left, selections[i].Top - selections[i - 1].Top) != adjustment)
{
return false;
}
}
}

char[] chars = selections.Select(location => board[location.Left, location.Top]).ToArray();
string charsString = new(chars);
Array.Reverse(chars);
string charsStringReverse = new(chars);
return charsString == currentWord || charsStringReverse == currentWord;
}

}
}
Loading

0 comments on commit 7ce9777

Please sign in to comment.