Загрузка данных


using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;

unsafe class Program
{
    const int WIDTH = 30;
    const int HEIGHT = 15;

    // Звено двусвязного списка (часть тела змейки)
    struct Node
    {
        public int x, y;
        public Node* prev;
        public Node* next;
    }

    // Еда
    struct Food
    {
        public int x, y;
    }

    static Node* head = null;   // голова змейки
    static Node* tail = null;   // хвост змейки
    static Food* food = null;   // еда
    static int dx = 1, dy = 0;  // направление движения
    static int score = 0;
    static Random rnd = new Random();

    // Создание нового звена в динамической памяти
    static Node* NewNode(int x, int y)
    {
        Node* n = (Node*)Marshal.AllocHGlobal(sizeof(Node));
        n->x = x;
        n->y = y;
        n->prev = null;
        n->next = null;
        return n;
    }

    // Добавить новую голову
    static void AddHead(int x, int y)
    {
        Node* n = NewNode(x, y);
        n->next = head;
        if (head != null) head->prev = n;
        head = n;
        if (tail == null) tail = n;
    }

    // Удалить хвост и освободить память
    static void RemoveTail()
    {
        Node* t = tail;
        tail = t->prev;
        if (tail != null) tail->next = null;
        else head = null;
        Marshal.FreeHGlobal((IntPtr)t);
    }

    // Есть ли змейка в клетке (x, y)
    static bool InSnake(int x, int y)
    {
        for (Node* p = head; p != null; p = p->next)
            if (p->x == x && p->y == y) return true;
        return false;
    }

    // Поставить еду на свободную клетку
    static void PlaceFood()
    {
        do
        {
            food->x = rnd.Next(WIDTH);
            food->y = rnd.Next(HEIGHT);
        } while (InSnake(food->x, food->y));
    }

    // Отрисовка поля
    static void Draw()
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("Счёт: " + score + "   ");
        sb.AppendLine("+" + new string('-', WIDTH) + "+");
        for (int y = 0; y < HEIGHT; y++)
        {
            sb.Append('|');
            for (int x = 0; x < WIDTH; x++)
            {
                if (head->x == x && head->y == y) sb.Append('@');
                else if (InSnake(x, y)) sb.Append('o');
                else if (food->x == x && food->y == y) sb.Append('*');
                else sb.Append(' ');
            }
            sb.AppendLine("|");
        }
        sb.AppendLine("+" + new string('-', WIDTH) + "+");
        Console.SetCursorPosition(0, 0);
        Console.Write(sb.ToString());
    }

    static void Main()
    {
        Console.CursorVisible = false;
        Console.Clear();

        // Змейка и еда в динамической памяти
        AddHead(WIDTH / 2, HEIGHT / 2);
        food = (Food*)Marshal.AllocHGlobal(sizeof(Food));
        PlaceFood();

        while (true)
        {
            Draw();
            Thread.Sleep(150);

            // Неблокирующее чтение клавиатуры
            while (Console.KeyAvailable)
            {
                ConsoleKey key = Console.ReadKey(true).Key;
                if (key == ConsoleKey.LeftArrow && dx != 1) { dx = -1; dy = 0; }
                else if (key == ConsoleKey.RightArrow && dx != -1) { dx = 1; dy = 0; }
                else if (key == ConsoleKey.UpArrow && dy != 1) { dx = 0; dy = -1; }
                else if (key == ConsoleKey.DownArrow && dy != -1) { dx = 0; dy = 1; }
            }

            int nx = head->x + dx;
            int ny = head->y + dy;

            // Столкновение с границей или с собой
            if (nx < 0 || nx >= WIDTH || ny < 0 || ny >= HEIGHT || InSnake(nx, ny))
                break;

            AddHead(nx, ny);

            if (nx == food->x && ny == food->y)
            {
                score++;        // съели еду: хвост не удаляем
                PlaceFood();
            }
            else
            {
                RemoveTail();   // еды нет: хвост удаляем
            }
        }

        // Освобождение памяти
        while (head != null) RemoveTail();
        Marshal.FreeHGlobal((IntPtr)food);

        Console.SetCursorPosition(0, HEIGHT + 4);
        Console.WriteLine("Игра окончена! Счёт: " + score);
        Console.CursorVisible = true;
    }
}