Created
January 8, 2020 13:53
-
-
Save JerryNixon/f3e101c5de50b2069867e83060156db4 to your computer and use it in GitHub Desktop.
This file contains hidden or 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.Diagnostics; | |
| using System.Drawing; | |
| using System.Linq; | |
| namespace SnakePrep | |
| { | |
| internal class Program | |
| { | |
| private static Game _game; | |
| private static int _iteration = 0; | |
| private static Direction _direction; | |
| private static void Main(string[] args) | |
| { | |
| _game = new Game(); | |
| Start(); | |
| } | |
| private static void Start() | |
| { | |
| Setup(); | |
| while (_game.GameOver == false) | |
| { | |
| Input(); | |
| Logic(); | |
| Draw(); | |
| System.Threading.Thread.Sleep(100); | |
| } | |
| _game.Input.WaitForSpacebar(); | |
| Start(); | |
| } | |
| public static void Setup() | |
| { | |
| _game.Reset(); | |
| _game.Border.Draw(); | |
| } | |
| public static void Input() | |
| { | |
| _direction = _game.Input.Read(); | |
| } | |
| public static void Draw() | |
| { | |
| _game.Ship.Draw(); | |
| _game.Fruit.Draw(); | |
| _game.Tail.Draw(); | |
| _game.Score.Draw(_game.GameOver); | |
| if (_game.GameOver) | |
| { | |
| Game.Draw(" ", _game.Ship.Previous, ConsoleColor.Black, ConsoleColor.Black); | |
| Game.Draw("!", _game.Ship.Current, ConsoleColor.Red, ConsoleColor.Red); | |
| } | |
| } | |
| public static void Logic() | |
| { | |
| _game.Ship.Move(_direction); | |
| if (_game.Tail.IntersectsWith(_game.Ship.Previous)) | |
| { | |
| _game.GameOver = true; | |
| } | |
| else if (_game.Ship.Current == _game.Fruit.Location) | |
| { | |
| IncreaseScore(); | |
| } | |
| else if (_game.Input.Current != Direction.Stop) | |
| { | |
| _game.Tail.Move(_game.Ship.Current, false); | |
| } | |
| ReduceFruit(); | |
| void IncreaseScore() | |
| { | |
| _game.Score.Add(_game.Fruit.Value); | |
| _game.Fruit.Move(_game.Ship.Previous, 9); | |
| _game.Tail.Move(_game.Ship.Current, true); | |
| } | |
| void ReduceFruit() | |
| { | |
| if (_game.Fruit.Value > 0 | |
| && _game.Input.Current != Direction.Stop | |
| && ++_iteration % 10 == 0) | |
| { | |
| _game.Fruit.Value--; | |
| } | |
| } | |
| } | |
| } | |
| public enum Direction { Up, Down, Left, Right, Stop } | |
| public class Game | |
| { | |
| public static Size GameSize; | |
| public bool GameOver; | |
| public Game(Size? size = null) | |
| { | |
| GameSize = size ?? new Size(40, 20); | |
| Reset(); | |
| } | |
| public void Reset() | |
| { | |
| Console.CursorVisible = false; | |
| Console.Clear(); | |
| GameOver = false; | |
| Input.Reset(); | |
| Score.Reset(); | |
| Ship.Reset(); | |
| Tail.Reset(); | |
| Fruit.Move(Ship.Previous); | |
| } | |
| public ScoreLogic Score = new ScoreLogic(); | |
| public BorderLogic Border = new BorderLogic(); | |
| public InputLogic Input = new InputLogic(); | |
| public ShipLogic Ship = new ShipLogic(); | |
| public FruitLogic Fruit = new FruitLogic(); | |
| public TailLogic Tail = new TailLogic(); | |
| public static void Draw(string text, Point location, ConsoleColor foreground, ConsoleColor background) | |
| { | |
| Draw(text, location.X, location.Y, foreground, background); | |
| } | |
| public static void Draw(string text, int x, int y, ConsoleColor foreground, ConsoleColor background) | |
| { | |
| Console.ForegroundColor = foreground; | |
| Console.BackgroundColor = background; | |
| Console.SetCursorPosition(x, y); | |
| Console.Write(text); | |
| Console.ResetColor(); | |
| } | |
| } | |
| public class TailLogic | |
| { | |
| public readonly List<Point> Points = new List<Point>(); | |
| public readonly List<Point> Previous = new List<Point>(); | |
| public void Move(Point point, bool grow) | |
| { | |
| Points.Add(point); | |
| if (!grow) | |
| { | |
| Previous.Add(Points.First()); | |
| Points.Remove(Points.First()); | |
| } | |
| } | |
| public void Draw() | |
| { | |
| ErasePrevious(); | |
| DrawCurrent(); | |
| } | |
| public void DrawCurrent(char text = '+', ConsoleColor foreground = ConsoleColor.Gray, ConsoleColor background = ConsoleColor.Black) | |
| { | |
| foreach (var point in Points) | |
| { | |
| Game.Draw(text.ToString(), point, foreground, background); | |
| } | |
| } | |
| public void ErasePrevious(ConsoleColor foreground = ConsoleColor.Black, ConsoleColor background = ConsoleColor.Black) | |
| { | |
| foreach (var point in Previous.ToArray()) | |
| { | |
| Previous.Remove(point); | |
| Game.Draw(" ", point, foreground, background); | |
| } | |
| } | |
| public bool IntersectsWith(Point point) | |
| { | |
| return Points.Contains(point); | |
| } | |
| public void Reset() | |
| { | |
| Points.Clear(); | |
| Previous.Clear(); | |
| } | |
| } | |
| public class ScoreLogic | |
| { | |
| public int Value; | |
| public int Count; | |
| public Stopwatch Timer = new Stopwatch(); | |
| public void Reset() | |
| { | |
| Value = 0; | |
| Count = 0; | |
| Timer.Restart(); | |
| } | |
| public void Add(int value) | |
| { | |
| Value += value; | |
| Count++; | |
| } | |
| public void Draw(bool gameOver, ConsoleColor foreground = ConsoleColor.White, ConsoleColor background = ConsoleColor.Black) | |
| { | |
| var value = $"Score: {Value} Length: {Count} Seconds: {Timer.Elapsed.TotalSeconds.ToString("#,###")}"; | |
| Game.Draw(value.PadLeft(10), 3, Game.GameSize.Height + 1, foreground, background); | |
| if (gameOver) | |
| { | |
| Game.Draw("Game Over", 3, Game.GameSize.Height + 2, ConsoleColor.White, ConsoleColor.Red); | |
| } | |
| } | |
| } | |
| public class BorderLogic | |
| { | |
| public void Draw(char text = '+', ConsoleColor foreground = ConsoleColor.White, ConsoleColor background = ConsoleColor.Black) | |
| { | |
| var line = new string(text, Game.GameSize.Width); | |
| Game.Draw(line, 0, 0, foreground, background); | |
| Game.Draw(line, 0, Game.GameSize.Height - 1, foreground, background); | |
| line = $"{text}{new string(' ', Game.GameSize.Width - 2)}{text}"; | |
| for (var i = 1; i < Game.GameSize.Height - 1; i++) | |
| { | |
| Game.Draw(line, 0, i, foreground, background); | |
| } | |
| } | |
| public static bool Intersects(Point point) | |
| { | |
| return (point.X <= 0 | |
| || point.Y <= 0 | |
| || point.X >= Game.GameSize.Width - 1 | |
| || point.Y >= Game.GameSize.Height - 1); | |
| } | |
| } | |
| public class InputLogic | |
| { | |
| public Direction Current = Direction.Stop; | |
| public void Reset() | |
| { | |
| Current = Direction.Stop; | |
| } | |
| public Direction Read() | |
| { | |
| if (Console.KeyAvailable) | |
| { | |
| var key = Console.ReadKey(true).Key; | |
| if (key == ConsoleKey.UpArrow && Current != Direction.Down) | |
| { | |
| return Current = Direction.Up; | |
| } | |
| else if (key == ConsoleKey.DownArrow && Current != Direction.Up) | |
| { | |
| return Current = Direction.Down; | |
| } | |
| else if (key == ConsoleKey.LeftArrow && Current != Direction.Right) | |
| { | |
| return Current = Direction.Left; | |
| } | |
| else if (key == ConsoleKey.RightArrow && Current != Direction.Left) | |
| { | |
| return Current = Direction.Right; | |
| } | |
| else if (key == ConsoleKey.Escape) | |
| { | |
| return Current = Direction.Stop; | |
| } | |
| else | |
| { | |
| return Current; | |
| } | |
| } | |
| else | |
| { | |
| return Current; | |
| } | |
| } | |
| public void WaitForSpacebar() | |
| { | |
| if (Console.ReadKey(true).Key == ConsoleKey.Spacebar) { return; } | |
| } | |
| } | |
| public class ShipLogic | |
| { | |
| public Point Previous = new Point(10, 10); | |
| public Point Current = new Point(10, 10); | |
| public void Move(Direction direction) | |
| { | |
| var newLocation = GetMovedPoint(direction); | |
| if (BorderLogic.Intersects(newLocation)) | |
| { | |
| newLocation = GetWrappedPoint(newLocation, direction); | |
| } | |
| Current = Previous; | |
| Previous = newLocation; | |
| } | |
| public void Draw() | |
| { | |
| ErasePrevious(); | |
| DrawCurrent(); | |
| } | |
| public void DrawCurrent(char text = 'X', ConsoleColor foreground = ConsoleColor.White, ConsoleColor background = ConsoleColor.Black) | |
| { | |
| Game.Draw(text.ToString(), Previous, foreground, background); | |
| } | |
| public void ErasePrevious(char text = ' ', ConsoleColor foreground = ConsoleColor.Black, ConsoleColor background = ConsoleColor.Black) | |
| { | |
| Game.Draw(" ", Current, foreground, background); | |
| } | |
| private Point GetMovedPoint(Direction direction) | |
| { | |
| var point = Previous; | |
| if (direction == Direction.Up) | |
| { | |
| point.Y--; | |
| } | |
| else if (direction == Direction.Down) | |
| { | |
| point.Y++; | |
| } | |
| else if (direction == Direction.Left) | |
| { | |
| point.X--; | |
| } | |
| else if (direction == Direction.Right) | |
| { | |
| point.X++; | |
| } | |
| return point; | |
| } | |
| private Point GetWrappedPoint(Point point, Direction direction) | |
| { | |
| if (direction == Direction.Up) | |
| { | |
| point.Y = Game.GameSize.Height - 2; | |
| } | |
| else if (direction == Direction.Down) | |
| { | |
| point.Y = 1; | |
| } | |
| else if (direction == Direction.Left) | |
| { | |
| point.X = Game.GameSize.Width - 2; | |
| } | |
| else if (direction == Direction.Right) | |
| { | |
| point.X = 1; | |
| } | |
| return point; | |
| } | |
| public void Reset() | |
| { | |
| var random = new Random(); | |
| Previous = new Point(0, 0); | |
| while (BorderLogic.Intersects(Previous)) | |
| { | |
| var x = random.Next(1, Game.GameSize.Width - 1); | |
| var y = random.Next(1, Game.GameSize.Height - 1); | |
| Previous = new Point(x, y); | |
| } | |
| } | |
| } | |
| public class FruitLogic | |
| { | |
| public Point Location; | |
| public Point Previous; | |
| public int Value; | |
| public void Move(Point avoid, int? value = null) | |
| { | |
| var random = new Random(); | |
| Previous = Location; | |
| Location = avoid; | |
| while (Location == avoid) | |
| { | |
| var x = random.Next(1, Game.GameSize.Width - 1); | |
| var y = random.Next(1, Game.GameSize.Height - 1); | |
| Location = new Point(x, y); | |
| } | |
| Value = value ?? 9; | |
| } | |
| public void Draw() | |
| { | |
| ErasePrevious(); | |
| DrawCurrent(); | |
| } | |
| public void DrawCurrent(ConsoleColor foreground = ConsoleColor.Red, ConsoleColor background = ConsoleColor.Black) | |
| { | |
| Game.Draw(Value.ToString(), Location, foreground, background); | |
| } | |
| public void ErasePrevious(char text = ' ', ConsoleColor foreground = ConsoleColor.Black, ConsoleColor background = ConsoleColor.Black) | |
| { | |
| Game.Draw(" ", Previous, foreground, background); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment