Skip to content

Commit

Permalink
Minor Refactors and Readme Updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ZacharyPatten committed Mar 1, 2020
1 parent 2b7bddf commit ccf1ab2
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 226 deletions.
10 changes: 7 additions & 3 deletions Projects/Hangman/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

Hangman is a game that chooses a random word from the english language, and you try to guess the word. If you make too many incorrect guesses you lose.

**_This game is depended on a "Words.txt" embedded resource file to provide the pool of possible random words. If you copy the code without the embedded resource it will not work._**

```
╔═══╗
Expand All @@ -22,4 +20,10 @@ Hangman is a game that chooses a random word from the english language, and you

## Input

The **alphabetic keys (a, b, c, ...)** are used to guess letters. The **escape** key may be used to close the game at any time. If you **resize** the console widow the game will be closed.
The **alphabetic keys (a, b, c, ...)** are used to guess letters. The **escape** key may be used to close the game at any time. If you **resize** the console widow the game will be closed.

## Dependencies

Don't forget these dependencies if you copy the code:

- "Words.txt" embedded resource _(included in source)_
53 changes: 27 additions & 26 deletions Projects/Maze/Prims/Graph.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

public class Graph
{
public class Node
{
public int OwnIndex { get; }
public List<int> Connections { get; }
public List<double> Costs { get; }
namespace Prims
{
public class Graph
{
public class Node
{
public int OwnIndex { get; }
public List<int> Connections { get; }
public List<double> Costs { get; }

public void Add(int other, double cost)
{
Connections.Add(other);
Costs.Add(cost);
}
public void Add(int other, double cost)
{
Connections.Add(other);
Costs.Add(cost);
}

public Node(int ownIndex)
{
OwnIndex = ownIndex;
Connections = new List<int>();
Costs = new List<double>();
}
}
public Node(int ownIndex)
{
OwnIndex = ownIndex;
Connections = new List<int>();
Costs = new List<double>();
}
}

public Node[] Nodes { get; }
public Node[] Nodes { get; }

public Graph(Node[] nodes)
{
Nodes = nodes ?? throw new ArgumentNullException(nameof(nodes));
}
public Graph(Node[] nodes)
{
Nodes = nodes ?? throw new ArgumentNullException(nameof(nodes));
}
}
}
109 changes: 55 additions & 54 deletions Projects/Maze/Prims/PrimsAlgorithm.cs
Original file line number Diff line number Diff line change
@@ -1,58 +1,59 @@

using System;
using System;
using Towel.DataStructures;

public static class PrimsAlgorithm
namespace Prims
{
private readonly struct TwoWayConnection : IComparable<TwoWayConnection>
{
public readonly int IndexA;
public readonly int IndexB;
public readonly double Cost;

public TwoWayConnection(int indexA, int indexB, double cost)
{
IndexA = indexA;
IndexB = indexB;
Cost = cost;
}

public int CompareTo(TwoWayConnection other) => other.Cost.CompareTo(Cost); // inversed because of how the heap works
}

public static Graph SimplePrims(Graph graph)
{
var newGraph = new Graph(new Graph.Node[graph.Nodes.Length]);
var nodes = graph.Nodes;
var current = nodes[0];
newGraph.Nodes[0] = new Graph.Node(0);

var heap = new HeapArray<TwoWayConnection>();


while(true)
{
for (int i = 0; i < current.Connections.Count; i++)
{
heap.Enqueue(new TwoWayConnection(current.OwnIndex, current.Connections[i], current.Costs[i]));
}

TwoWayConnection c;
do
{
if (heap.Count == 0)
return newGraph;

c = heap.Dequeue();
}
while (newGraph.Nodes[c.IndexB] != null);


newGraph.Nodes[c.IndexA].Add(c.IndexB, c.Cost);

newGraph.Nodes[c.IndexB] = new Graph.Node(c.IndexB);
current = graph.Nodes[c.IndexB];
newGraph.Nodes[c.IndexB].Add(c.IndexA, c.Cost);
}
}
public static class PrimsAlgorithm
{
private readonly struct TwoWayConnection : IComparable<TwoWayConnection>
{
public readonly int IndexA;
public readonly int IndexB;
public readonly double Cost;

public TwoWayConnection(int indexA, int indexB, double cost)
{
IndexA = indexA;
IndexB = indexB;
Cost = cost;
}

public int CompareTo(TwoWayConnection other) => other.Cost.CompareTo(Cost); // inversed because of how the heap works
}

public static Graph SimplePrims(Graph graph)
{
var newGraph = new Graph(new Graph.Node[graph.Nodes.Length]);
var nodes = graph.Nodes;
var current = nodes[0];
newGraph.Nodes[0] = new Graph.Node(0);

var heap = new HeapArray<TwoWayConnection>();

while (true)
{
for (int i = 0; i < current.Connections.Count; i++)
{
heap.Enqueue(new TwoWayConnection(current.OwnIndex, current.Connections[i], current.Costs[i]));
}

TwoWayConnection c;
do
{
if (heap.Count == 0)
{
return newGraph;
}
c = heap.Dequeue();
}
while (newGraph.Nodes[c.IndexB] != null);

newGraph.Nodes[c.IndexA].Add(c.IndexB, c.Cost);

newGraph.Nodes[c.IndexB] = new Graph.Node(c.IndexB);
current = graph.Nodes[c.IndexB];
newGraph.Nodes[c.IndexB].Add(c.IndexA, c.Cost);
}
}
}
}
168 changes: 88 additions & 80 deletions Projects/Maze/Prims/PrimsMazeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,84 +2,92 @@

namespace Prims
{
public class PrimsMazeGenerator
{
public static Maze.Tile[,] Generate(
int rows, int columns,
int? start_row = null, int? start_column = null,
int? end_row = null, int? end_column = null)
{
start_row ??= 0;
start_column ??= 0;
end_row ??= rows - 1;
end_column ??= columns - 1;

var grid = new Graph.Node[rows * columns];
int Index(int row, int col) => row + rows * col;
(int, int) Unpack(int i) => (i % rows, i / rows);

var random = new Random();

for (int row = 0; row < rows; row++)
{
for (int col = 0; col < columns; col++)
{
var n = new Graph.Node(Index(row, col));

if (row + 1 < rows)
n.Add(Index(row + 1, col), random.NextDouble());

if (row - 1 >= 0)
n.Add(Index(row - 1, col), random.NextDouble());

if (col + 1 < columns)
n.Add(Index(row, col + 1), random.NextDouble());

if (col - 1 >= 0)
n.Add(Index(row, col - 1), random.NextDouble());

grid[Index(row, col)] = n;
}
}

var res = PrimsAlgorithm.SimplePrims(new Graph(grid));

var tiles = new Maze.Tile[rows,columns];

foreach (var node in res.Nodes)
{
var (row, col) = Unpack(node.OwnIndex);

if (node.Connections.Contains(Index(row - 1, col)))
{
tiles[row, col] |= Maze.Tile.Up;
tiles[row - 1, col] |= Maze.Tile.Down;
}

if (node.Connections.Contains(Index(row + 1, col)))
{
tiles[row, col] |= Maze.Tile.Down;
tiles[row + 1, col] |= Maze.Tile.Up;
}

if (node.Connections.Contains(Index(row, col - 1)))
{
tiles[row, col] |= Maze.Tile.Left;
tiles[row, col - 1] |= Maze.Tile.Right;
}

if (node.Connections.Contains(Index(row, col + 1)))
{
tiles[row, col] |= Maze.Tile.Right;
tiles[row, col + 1] |= Maze.Tile.Left;
}

if (row == start_row.Value && col == start_column.Value) tiles[row, col] |= Maze.Tile.Start;
if (row == end_row.Value && col == end_column.Value) tiles[row, col] |= Maze.Tile.End;

}

return tiles;
}
}
public class PrimsMazeGenerator
{
public static Maze.Tile[,] Generate(
int rows, int columns,
int? start_row = null, int? start_column = null,
int? end_row = null, int? end_column = null)
{
start_row ??= 0;
start_column ??= 0;
end_row ??= rows - 1;
end_column ??= columns - 1;

var grid = new Graph.Node[rows * columns];

int Index(int row, int col) => row + rows * col;

var random = new Random();

for (int row = 0; row < rows; row++)
{
for (int col = 0; col < columns; col++)
{
var n = new Graph.Node(Index(row, col));
if (row + 1 < rows)
{
n.Add(Index(row + 1, col), random.NextDouble());
}
if (row - 1 >= 0)
{
n.Add(Index(row - 1, col), random.NextDouble());
}
if (col + 1 < columns)
{
n.Add(Index(row, col + 1), random.NextDouble());
}
if (col - 1 >= 0)
{
n.Add(Index(row, col - 1), random.NextDouble());
}
grid[Index(row, col)] = n;
}
}

var res = PrimsAlgorithm.SimplePrims(new Graph(grid));

var tiles = new Maze.Tile[rows, columns];

foreach (var node in res.Nodes)
{
(int, int) Unpack(int i) => (i % rows, i / rows);

var (row, col) = Unpack(node.OwnIndex);

// directional
if (node.Connections.Contains(Index(row - 1, col)))
{
tiles[row, col] |= Maze.Tile.Up;
tiles[row - 1, col] |= Maze.Tile.Down;
}
if (node.Connections.Contains(Index(row + 1, col)))
{
tiles[row, col] |= Maze.Tile.Down;
tiles[row + 1, col] |= Maze.Tile.Up;
}
if (node.Connections.Contains(Index(row, col - 1)))
{
tiles[row, col] |= Maze.Tile.Left;
tiles[row, col - 1] |= Maze.Tile.Right;
}
if (node.Connections.Contains(Index(row, col + 1)))
{
tiles[row, col] |= Maze.Tile.Right;
tiles[row, col + 1] |= Maze.Tile.Left;
}

// start/end
if (row == start_row.Value && col == start_column.Value)
{
tiles[row, col] |= Maze.Tile.Start;
}
if (row == end_row.Value && col == end_column.Value)
{
tiles[row, col] |= Maze.Tile.End;
}
}
return tiles;
}
}
}
6 changes: 4 additions & 2 deletions Projects/Maze/Program.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
//#define MazeGenertorLoop // uncomment to run the generator in a loop
//#define DebugRandomMazeGeneration // uncomment me to watch the maze being built node-by-node
//#define UsePrims
//#define UsePrims // uncomment me to use an alternate algorithm for maze generation

using System;
using System.Collections.Generic;
using System.Text;
#if UsePrims
using Prims;
#endif

class Program
{
Expand All @@ -19,7 +21,7 @@ static void Main()
PrimsMazeGenerator.Generate(rows, columns);
#else
Maze.Generate(rows, columns);
#endif
#endif
#if MazeGenertorLoop
while (true)
{
Expand Down
Loading

0 comments on commit ccf1ab2

Please sign in to comment.