Can someone explain me the logic part? I kinda know it should work but I cant trace the code step by step, It doesnt make sense. Exchange among temp, pre, and Tail part is so confusing.
How does it run with the framerate? Is TailX[0] and TailY[0] always ahead? WHY? How do new tail parts get assigned in correct position? HELP ME.
using System;
using System.Threading;
namespace Projects
{
class Snake
{
    public Random rand = new Random();
    public ConsoleKeyInfo keypress = new ConsoleKeyInfo();
    int score, headX, headY, fruitX, fruitY, nTail;
    int[] TailX = new int[100];
    int[] TailY = new int[100];
    const int height = 20;
    const int width = 60;
    bool gameOver, reset, isprinted, horizontal, vertical;
    string dir, pre_dir;
    void ShowBanner()
    {
        Console.SetWindowSize(width, height + 6);
        Console.ForegroundColor = ConsoleColor.Green;
        Console.CursorVisible = false;
        Console.WriteLine("!!####################################!!");
        Console.WriteLine("!!####################################!!");
        Console.WriteLine("!!####################################!!");
        Console.WriteLine("!!####################################!!");
        Console.WriteLine("!!####################################!!");
        Console.WriteLine("!!##########     Welcome    ##########!!");
        keypress = Console.ReadKey(true);
        if (keypress.Key == ConsoleKey.Escape)
        {
            Environment.Exit(0);
        }
    }
    void Setup()
    {
        dir = "Right";
        pre_dir = "";
        score = 0;
        nTail = 0;
        gameOver = false;
        reset = false;
        isprinted = false;
        headX = width / 2;
        headY = height / 2;
        fruitX = rand.Next(1, width - 1);
        fruitY = rand.Next(1, height - 1);
    }
    void CheckInput()
    {
        while (Console.KeyAvailable)
        {
            keypress = Console.ReadKey(true);
            if (keypress.Key == ConsoleKey.Escape)
                Environment.Exit(0);
            if (keypress.Key == ConsoleKey.S)
            {
                pre_dir = dir;
                dir = "STOP";
            }
            else if (keypress.Key ==ConsoleKey.LeftArrow)
            {
                pre_dir = dir;
                dir = "LEFT";
            }
            else if (keypress.Key == ConsoleKey.RightArrow)
            {
                pre_dir = dir;
                dir = "RIGHT";
            }
            else if (keypress.Key ==ConsoleKey.UpArrow)
            {
                pre_dir = dir;
                dir = "UP";
            }
            else if (keypress.Key == ConsoleKey.DownArrow)
            {
                pre_dir = dir;
                dir = "DOWN";
            }
        }
    }
    void Logic()
    {
        int preX = TailX[0];
        int preY = TailY[0];
        int tempX, tempY;
        if (dir != "STOP")
        {
            TailX[0] = headX;
            TailY[0] = headY;
            for (int i = 1; i < nTail; i++)
            {
                tempX = TailX[i];
                tempY = TailY[i];
                TailX[i] = preX;
                TailY[i] = preY;
                preX = tempX;
                preY = tempY;
            }
        }
        switch (dir)
        {
            case "RIGHT":
                headX++;
                break;
            case "LEFT":
                headX--;
                break;
            case "UP":
                headY--;
                break;
            case "DOWN":
                headY++;
                break;
            case "STOP":
                while (true)
                {
                    Console.Clear();
                    Console.CursorLeft = width / 2 - 6;
                    Console.WriteLine("GAME PAUSED");
                    Console.WriteLine();
                    Console.WriteLine();
                    Console.WriteLine("   -S to resume   ");
                    Console.WriteLine("   -R to reset   ");
                    Console.Write("   -ESC to quit   ");
                    keypress = Console.ReadKey(true);
                    if (keypress.Key == ConsoleKey.Escape)
                        Environment.Exit(0);
                    if (keypress.Key == ConsoleKey.R)
                    {
                        reset = true;
                        break;
                    }
                    if (keypress.Key == ConsoleKey.S)
                        break;
                }
                dir = pre_dir;
                break;
        }
        if (headX <= 0 || headX >= width - 1 || headY <= 0 || headY >= height - 1)
        {
            gameOver = true;
        }
        else
        {
            gameOver = false;
        }
        if (headX == fruitX && headY == fruitY)
        {
            score += 10;
            nTail++;
            fruitX = rand.Next(1, width - 1);
            fruitY = rand.Next(1, height - 1);
        }
        if (((dir == "LEFT" && pre_dir != "UP") && (dir == "LEFT" && pre_dir != "DOWN")) ||
          ((dir == "RIGHT" && pre_dir != "UP") && (dir == "RIGHT" && pre_dir != "DOWN")))
        {
            horizontal = true;
        }
        else
        {
            horizontal = false;
        }
        if (((dir == "UP" && pre_dir != "LEFT") && (dir == "UP" && pre_dir != "RIGHT")) ||
          ((dir == "DOWN" && pre_dir != "LEFT") && (dir == "RIGHT" && pre_dir != "RIGHT")))
        {
            vertical = true;
        }
        else
        {
            vertical = false;
        }
        for (int i = 1; i < nTail; i++)
        {
            if (TailX[i] == headX && TailY[i] == headY)
            {
                if (horizontal || vertical)
                {
                    gameOver = false;
                }
                else
                {
                    gameOver = true;
                }
            }
            if (TailX[i] == fruitX && TailY[i] == fruitY)
            {
                fruitX = rand.Next(1, width - 1);
                fruitY = rand.Next(1, height - 1);
            }
        }
    }
    void Render()
    {
        Console.SetCursorPosition(0, 0);
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                if (i == 0 || i == height - 1)
                {
                    Console.Write("#");
                }
                else if (j == 0 || j == width - 1)
                {
                    Console.Write("#");
                }
                else if (j == fruitX && i == fruitY)
                {
                    Console.Write("F");
                }
                else if (j == headX && i == headY)
                {
                    Console.Write("0");
                }
                else
                {
                    isprinted = false;
                    for (int k = 0; k < nTail; k++)
                    {
                        if (TailX[k] == j && TailY[k] == i)
                        {
                            Console.Write("o");
                            isprinted = true;
                        }
                    }
                    if (!isprinted)
                        Console.Write(" ");
                }
            }
            Console.WriteLine();
        }
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine(" YOUR SCORE : " + score);
    }
    void Lose()
    {
        Console.CursorTop = height + 3;
        Console.CursorLeft = width / 2 - 4;
        Console.WriteLine("YOU DIED");
        Console.WriteLine(" R to reset");
        Console.Write(" Esc to quit");
        while (true)
        {
            keypress = Console.ReadKey(true);
            if (keypress.Key == ConsoleKey.Escape)
            {
                Environment.Exit(0);
            }
            if (keypress.Key == ConsoleKey.R)
            {
                reset = true;
                break;
            }
        }
    }
    void Update()
    {
        while (!gameOver)
        {
            CheckInput();
            Logic();
            Render();
            if (reset)
                break;
            Thread.Sleep(30);
        }
        if (gameOver)
            Lose();
    }
    static void Main(string[] args)
    {
        Snake snake = new Snake();
        snake.ShowBanner();
        while (true)
        {
            snake.Setup();
            snake.Update();
            Console.Clear();
        }
    }
}
}
 
    
