Skip to content

Instantly share code, notes, and snippets.

@nguyenthanhliemfc
Forked from M2vH/Snake.cs
Created December 5, 2019 13:02
Show Gist options
  • Save nguyenthanhliemfc/93358e61072b2faa11b18e546c3c38c2 to your computer and use it in GitHub Desktop.
Save nguyenthanhliemfc/93358e61072b2faa11b18e546c3c38c2 to your computer and use it in GitHub Desktop.
My personal view on Snake from @JerryNixon
// based on the work of JerryNixon
// find origin code here
// https://gist.github.com/JerryNixon/52e2821cdf888a3c492e22397c4b5dda
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading;
namespace Snake
{
public enum Direction { Up = 0, Down, Left, Right, Stop }
public class Program
{
private static Size _size;
private static Point _head;
private static Point _fruit;
private static bool _gameOver;
private static List<Point> _tail;
private static Direction _direction;
private static readonly Point[] _nextHead =
{
new Point(0,-1), // up (0,0)---> +x
new Point(0,1), // down |
new Point(-1,0), // left v
new Point(1,0) // right +y
};
private static readonly Random _random = new Random();
private static void Main(string[] args)
{
Start();
}
private static void Start()
{
Setup();
while (_gameOver == false)
{
Input();
Logic();
Draw();
Thread.Sleep(100);
}
End();
}
public static void Init()
{
_gameOver = false;
_size = new Size(40, 20);
_tail = new List<Point>();
_direction = Direction.Stop;
#if DEBUG
_direction = Direction.Right;
#endif
_head = RandomPoint();
_fruit = RandomPoint();
}
private static void Setup()
{
Init();
Console.Clear();
Console.CursorVisible = false;
Console.Title = "Snake Game";
for (var i = 0; i < _size.Height; i++)
{
if (i == 0 || i == _size.Height - 1)
{
$"+{new string('-', _size.Width - 2)}+".Write(0, i);
}
else
{
$"|{new string(' ', _size.Width - 2)}|".Write(0, i);
}
}
for (var i = 1; i < _size.Height - 1; i++)
{
new string('x', _size.Width - 2).Write(1, i, ConsoleColor.Blue, ConsoleColor.Black);
}
}
private static void Draw()
{
_head.Write("0", ConsoleColor.Yellow, ConsoleColor.Black);
_tail.Write("o");
_fruit.Write("*", ConsoleColor.Cyan, ConsoleColor.Black);
$"Score: {_tail.Count()}".Write(_size.Width + 3, 5);
}
private static void Input()
{
if (!Console.KeyAvailable) { return; }
var key = Console.ReadKey(false).Key;
if (key == ConsoleKey.UpArrow) { _direction = Direction.Up; }
else if (key == ConsoleKey.DownArrow) { _direction = Direction.Down; }
else if (key == ConsoleKey.LeftArrow) { _direction = Direction.Left; }
else if (key == ConsoleKey.RightArrow) { _direction = Direction.Right; }
else if (key == ConsoleKey.Escape) { _direction = Direction.Stop; }
}
private static void Logic()
{
if (_direction == Direction.Stop) { return; }
if (_tail.Contains(_head))
{
_gameOver = true;
_direction = Direction.Stop;
return;
}
_tail.Add(_head.Copy());
if (_head == _fruit) { _fruit = RandomPoint(); }
else
{
_tail.RemoveFirst();
}
if (_direction == Direction.Up)
{
_head = GetNextPoint(_head, _nextHead[(int)Direction.Up]);
}
else if (_direction == Direction.Down)
{
_head = GetNextPoint(_head, _nextHead[(int)Direction.Down]);
}
else if (_direction == Direction.Left)
{
_head = GetNextPoint(_head, _nextHead[(int)Direction.Left]);
}
else if (_direction == Direction.Right)
{
_head = GetNextPoint(_head, _nextHead[(int)Direction.Right]);
}
}
private static void End()
{
$"GAME OVER".Write(_size.Width + 3, 3, ConsoleColor.Red, ConsoleColor.White);
$"Spacebar to play again".Write(_size.Width + 3, 4, ConsoleColor.Black, ConsoleColor.Gray);
if (Console.ReadKey(true).Key == ConsoleKey.Spacebar) { Start(); }
}
public static Point RandomPoint()
{
var x = _random.Next(1, _size.Width - 1);
var y = _random.Next(1, _size.Height - 1);
var point = new Point(x, y);
if (_tail.Contains(point) || _head == point) { return RandomPoint(); }
else { return point; }
}
public static Point GetNextPoint(Point here, Point direction)
{
int deltaX = _size.Width - 1;
int deltaY = _size.Height - 1;
int tempX = here.X + direction.X;
int tempY = here.Y + direction.Y;
int x = ((tempX + deltaX) % deltaX) + (1 * (tempX / deltaX));
int y = ((tempY + deltaY) % deltaY) + (1 * (tempY / deltaY));
return new Point(x, y);
}
}
public static class Extensions
{
public static void RemoveFirst<T>(this List<T> list)
{
if (list.Any())
{
if (list.Count > 0)
{
Point first = Copy(list.Cast<Point>().First());
first.Write("x", ConsoleColor.Blue, ConsoleColor.Black);
}
list.Remove(list.First());
}
}
public static void RemoveLast<T>(this List<T> list)
{
if (list.Any())
{
list.Remove(list.Last());
}
}
public static Point Copy(this Point point)
{
return new Point(point.X, point.Y);
}
public static void Write(this IEnumerable<Point> points, string text)
{
foreach (var point in points)
{
Write(text, point.X, point.Y);
}
}
public static void Write(this IEnumerable<Point> points, string text, ConsoleColor foreground, ConsoleColor background)
{
foreach (var point in points)
{
Write(text, point.X, point.Y, foreground, background);
}
}
public static void Write(this Point point, string text)
{
Write(text, point.X, point.Y);
}
public static void Write(this Point point, string text, ConsoleColor foreground, ConsoleColor background)
{
Write(text, point.X, point.Y, foreground, background);
}
public static void Write(this string text, int x, int y)
{
Console.SetCursorPosition(x, y);
Console.Write(text);
}
public static void Write(this string text, int x, int y, ConsoleColor foreground, ConsoleColor background)
{
Console.SetCursorPosition(x, y);
Console.ForegroundColor = foreground;
Console.BackgroundColor = background;
Console.Write(text);
Console.ResetColor();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment