Last active
August 29, 2015 14:01
-
-
Save oerpli/99651ff88f3354e37a54 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace flood { | |
class MainClass { | |
public static void Main(string[] args) { | |
while(true) { | |
Console.Clear(); | |
Console.WriteLine("Welcome to Flood Fill™!"); | |
Console.WriteLine("Press S to start, O to change options, or Q to quit."); | |
switch(Console.ReadKey(true).KeyChar) { | |
case 'S': //Start | |
case 's': Game(); | |
continue; | |
case 'O': //Options | |
case 'o': Settings(); | |
continue; | |
case 'Q'://Quit | |
case 'q': | |
return; | |
} | |
} | |
} | |
private static void Game() { | |
Console.Clear(); | |
Grid grid = new Grid(); ; | |
grid.PrintOut(); | |
while(!grid.Solved()) { | |
char c = Console.ReadKey(true).KeyChar; | |
if(c == 'H' || c == 'h') { | |
grid.Solve(false); | |
grid.PrintOut(); | |
break; | |
} | |
if(!char.IsDigit(c)) | |
continue; | |
int k = int.Parse(c.ToString()); | |
if(k > Grid.MAX || k == 0) | |
continue; | |
grid.Fill(k - 1); | |
Console.Clear(); | |
grid.PrintOut(); | |
} | |
Console.WriteLine("You win! \nPress any key continue."); | |
Console.ReadKey(true); | |
} | |
private static void Settings() { | |
Grid.HEIGHT = PromptNumber("Enter grid height(must be an odd number)", Grid.HEIGHT); | |
Grid.WIDTH = PromptNumber("Enter grid width(must be an odd number)", Grid.WIDTH); | |
Grid.MAX = Math.Min(PromptNumber("Enter maximum value (max 9)", Grid.MAX), 9); | |
if(Grid.HEIGHT % 2 == 0) Grid.HEIGHT++; | |
if(Grid.WIDTH % 2 == 0) Grid.WIDTH++; | |
} | |
public static int PromptNumber(string msg, int def = -1) { | |
if(def == -1) { | |
Console.Write(msg + ": "); | |
int of = 0; | |
string ss = Console.ReadLine(); | |
if(!int.TryParse(ss, out of)) | |
return PromptNumber(msg, def); | |
return of; | |
} | |
Console.Write(msg + "[" + def + "]: "); | |
int o = 0; | |
string s = Console.ReadLine(); | |
if(s.Trim() == string.Empty) | |
return def; | |
if(!int.TryParse(s, out o)) | |
return PromptNumber(msg, def); | |
return o; | |
} | |
} | |
class Grid { | |
public static int WIDTH = 19; | |
public static int HEIGHT = 19; | |
public static int MAX = 6; | |
int[,] arr = new int[WIDTH, HEIGHT]; | |
ConsoleColor[] COLORS = new ConsoleColor[]{ | |
ConsoleColor.DarkRed, | |
ConsoleColor.DarkGreen, | |
ConsoleColor.DarkYellow, | |
ConsoleColor.DarkCyan, | |
ConsoleColor.DarkBlue, | |
ConsoleColor.DarkGray, | |
ConsoleColor.Blue, | |
ConsoleColor.Red, | |
ConsoleColor.Green, | |
}; | |
public Grid() { | |
Random rnd = new Random(); | |
for(int x = 0; x < WIDTH; x++) { | |
for(int y = 0; y < HEIGHT; y++) { | |
arr[x, y] = rnd.Next(Grid.MAX); | |
} | |
} | |
} | |
public string Solve(bool returnSolvingSequence) { | |
if(returnSolvingSequence) { | |
string ret = ""; | |
while(!this.Solved()) { | |
int k = this.GetBestColor(); | |
ret += k.ToString(); | |
this.Fill(k); | |
System.Threading.Thread.Sleep(150); | |
this.PrintOut(); | |
} | |
return ret; | |
} else { | |
while(!this.Solved()) { | |
this.Fill(GetBestColor()); | |
System.Threading.Thread.Sleep(150); | |
this.PrintOut(); | |
} | |
return ""; | |
} | |
} | |
public bool Solved() { | |
int reference = arr[0, 0];//if not everything has this color it's not solved yet. | |
for(int x = 0; x < WIDTH; x++) { | |
for(int y = 0; y < HEIGHT; y++) { | |
if(arr[x, y] != reference) | |
return false; | |
} | |
} | |
return true; | |
} | |
public void Fill(int color) { | |
int originalcolor = arr[WIDTH / 2, HEIGHT / 2]; | |
bool[,] visited = new bool[WIDTH, HEIGHT]; | |
var nodes = new Stack<KeyValuePair<int, int>>(); | |
nodes.Push(new KeyValuePair<int, int>(WIDTH / 2, HEIGHT / 2)); | |
while(nodes.Count > 0) { | |
var active = nodes.Pop(); | |
int x = active.Key; | |
int y = active.Value; | |
visited[x, y] = true; | |
if(arr[x, y] != originalcolor) { | |
continue; | |
} | |
arr[x, y] = color; | |
if(x + 1 < WIDTH && !visited[x + 1, y]) | |
nodes.Push(new KeyValuePair<int, int>(x + 1, y)); | |
if(x - 1 >= 0 && !visited[x - 1, y]) | |
nodes.Push(new KeyValuePair<int, int>(x - 1, y)); | |
if(y - 1 >= 0 && !visited[x, y - 1]) | |
nodes.Push(new KeyValuePair<int, int>(x, y - 1)); | |
if(y + 1 < HEIGHT && !visited[x, y + 1]) | |
nodes.Push(new KeyValuePair<int, int>(x, y + 1)); | |
} | |
} | |
public List<KeyValuePair<int, int>> GetNeighbors(int x, int y) { | |
var ret = new List<KeyValuePair<int, int>>(); | |
ret.Add(new KeyValuePair<int, int>(x, y)); | |
ret.Add(new KeyValuePair<int, int>(x + 1, y)); | |
ret.Add(new KeyValuePair<int, int>(x - 1, y)); | |
ret.Add(new KeyValuePair<int, int>(x, y + 1)); | |
ret.Add(new KeyValuePair<int, int>(x, y - 1)); | |
return ret; | |
} | |
public int GetBestColor() { | |
//basically the same algorithm as the landfill but it doesn't fill but stores | |
//which neighbouring color is the most common. Only a heuristic - not really the best option. | |
int[] colors = new int[Grid.MAX]; | |
int originalcolor = arr[WIDTH / 2, HEIGHT / 2]; | |
bool[,] visited = new bool[WIDTH, HEIGHT]; | |
var nodes = new Stack<KeyValuePair<int, int>>(); | |
nodes.Push(new KeyValuePair<int, int>(WIDTH / 2, HEIGHT / 2)); | |
while(nodes.Count > 0) { | |
var active = nodes.Pop(); | |
int x = active.Key; | |
int y = active.Value; | |
visited[x, y] = true; | |
if(arr[x, y] != originalcolor) { | |
colors[arr[x, y]]++;//this line differs! | |
continue; | |
} | |
if(x + 1 < WIDTH && !visited[x + 1, y]) | |
nodes.Push(new KeyValuePair<int, int>(x + 1, y)); | |
if(x - 1 >= 0 && !visited[x - 1, y]) | |
nodes.Push(new KeyValuePair<int, int>(x - 1, y)); | |
if(y - 1 >= 0 && !visited[x, y - 1]) | |
nodes.Push(new KeyValuePair<int, int>(x, y - 1)); | |
if(y + 1 < HEIGHT && !visited[x, y + 1]) | |
nodes.Push(new KeyValuePair<int, int>(x, y + 1)); | |
} | |
return colors.ToList().IndexOf(colors.Max()); | |
} | |
public void PrintOut() { | |
Console.Clear(); | |
for(int x = 0; x < WIDTH; x++) { | |
for(int y = 0; y < HEIGHT; y++) { | |
Console.BackgroundColor = COLORS[arr[y, x]]; | |
Console.Write(arr[y, x] + 1); | |
} | |
Console.WriteLine(); | |
} | |
Console.BackgroundColor = ConsoleColor.Black; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment