Блимає екран під час запуску гри C# console

Зразу скажу що в програмуванні я початківець, мигає екран коли натискаю старт, не знаю як пофіксити

Ось код:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;

namespace kursova
{
public enum MenuOption
{
HowToPlay = 1,
Information,
Start,
Records,
Exit
}

class Program
{
static readonly int x = 60;
static readonly int y = 26;
static readonly int SnakeInitialLength = 3;

static Walls walls;
static Snake snake;
static FoodFactory foodFactory;
static Timer timer;
static int score = 0;

static void Main()
{
Console.OutputEncoding = System.Text.Encoding.UTF8;
Console.SetWindowSize(x + 1, y + 1);
Console.SetBufferSize(x + 1, y + 1);
bool exit = false;

while (!exit)
{
Console.Clear();
DisplayMenu();

ConsoleKeyInfo keyInfo = Console.ReadKey();

switch (keyInfo.Key)
{
case ConsoleKey.D1:
DisplayHowToPlay();
break;

case ConsoleKey.D2:
DisplayInformation();
break;

case ConsoleKey.D3:
StartGame();
break;

case ConsoleKey.D4:
ShowHighScores();
break;

case ConsoleKey.D5:
exit = true;
break;

default:
DisplayUnknownOption();
break;
}
}
}

static void DisplayMenu()
{
Console.Clear();

string logo = @"
____ _
 / ___| _ __ __ _ | | __ ___
\___ \ | ’_ \ / _` | | |/ / / _ \
___) | | | | | | (_| | | < | __/
|____/ |_| |_| \__,_| |_|\_\ \___|

TurboPascal`♥
";

Console.WriteLine(logo);
Console.SetCursorPosition(x / 2 — 5, y / 2);
Console.WriteLine("Menu");
Console.SetCursorPosition(x / 2 — 10, y / 2 + 2);
Console.WriteLine("1. Як грати? ☺ 0000000000000″);
Console.SetCursorPosition(x / 2 — 10, y / 2 + 3);
Console.WriteLine("2. Інформація 0″);
Console.SetCursorPosition(x / 2 — 14, y / 2 + 4);
Console.WriteLine("00000000000000000000000000000000000000000000″);
Console.SetCursorPosition(x / 2 — 10, y / 2 + 5);
Console.WriteLine("3. Start");
Console.SetCursorPosition(x / 2 — 14, y / 2 + 5);
Console.WriteLine("0″);
Console.SetCursorPosition(x / 2 — 14, y / 2 + 6);
Console.WriteLine("0″);
Console.SetCursorPosition(x / 2 — 14, y / 2 + 7);
Console.WriteLine("000000000000000000000000000″);
Console.SetCursorPosition(x / 2 — 10, y / 2 + 8);
Console.WriteLine("4. Рекорди 0″);
Console.WriteLine("0000000000000000000000000000000000000000000 000″);
Console.SetCursorPosition(x / 2 — 10, y / 2 + 10);
Console.WriteLine("5. Вихід");
}

static void DisplayHowToPlay()
{
Console.Clear();
Console.WriteLine("Керування: ←, →, ↑, ↓");
Console.WriteLine("Ваша мета — з’їсти якомога більше їжі, не зіткнувшись зі стінами або самою собою.");
Console.WriteLine("Натисніть будь-яку клавішу, щоб продовжити...");
Console.ReadKey();
}

static void DisplayInformation()
{
Console.Clear();
Console.WriteLine("Змійка (Snake Game) — це жанр відеоігор,");
Console.WriteLine("де гравець керує точкою, квадратом або об’єктом на площині з чіткими межами.");
Console.WriteLine("Натисніть будь-яку клавішу, щоб продовжити...");
Console.ReadKey();
}

static void StartGame()
{
walls = new Walls(x, y, ’#’);
snake = new Snake(x / 2, y / 2, SnakeInitialLength);
foodFactory = new FoodFactory(x, y, ’☺’);
foodFactory.CreateFood();

timer = new Timer(Loop, null, 0, 250);

while (true)
{
if (Console.KeyAvailable)
{
ConsoleKeyInfo key = Console.ReadKey();
snake.Rotation(key.Key);
}

}
}

static void Loop(object obj)
{
snake.Move();

if (walls.IsHit(snake.GetHead()) || snake.IsHit(snake.GetHead()))
{
timer.Change(Timeout.Infinite, Timeout.Infinite);

Console.Clear();

Console.SetCursorPosition(x / 2 — 5, y / 2);
Console.Write("Гра закінчилася!");
Console.SetCursorPosition(x / 2 — 10, y / 2 + 1);
Console.Write("Ваш рахунок: " + score);

ScoreManager scoreManager = new ScoreManager("scores.txt");
scoreManager.SaveScore(score);

Console.SetCursorPosition(x / 2 — 30, y / 2 + 2);
Console.WriteLine("1. Вийти в головне меню");
Console.WriteLine("2. Почати гру спочатку");
Console.WriteLine("3. Рекорди");
Console.Write(«Виберіть опцію (Щоб вибрати, натисніть 1, 2 або 3 та ENTER):..«);

bool exit = false;
int choice;

while (!exit)
{
string input = Console.ReadLine();

if (int.TryParse(input, out choice))
{
if (choice == 1)
{
Console.Clear();
string logo = @»
____ _
 / ___| _ __ __ _ | | __ ___
\___ \ | ’_ \ / _` | | |/ / / _ \
___) | | | | | | (_| | | < | __/
|____/ |_| |_| \__,_| |_|\_\ \___|

TurboPascal`♥
";
Console.WriteLine(logo, ConsoleColor.Green);
Console.SetCursorPosition(x / 2 — 5, y / 2);
Console.WriteLine("Menu");
Console.SetCursorPosition(x / 2 — 10, y / 2 + 2);
Console.WriteLine("1. Як грати? ☺ 0000000000000″);
Console.SetCursorPosition(x / 2 — 10, y / 2 + 3);
Console.WriteLine("2. Інформація 0″);
Console.SetCursorPosition(x / 2 — 14, y / 2 + 4);
Console.WriteLine("00000000000000000000000000000000000000000000″);
Console.SetCursorPosition(x / 2 — 10, y / 2 + 5);
Console.WriteLine("3. Start");
Console.SetCursorPosition(x / 2 — 14, y / 2 + 5);
Console.WriteLine("0″);
Console.SetCursorPosition(x / 2 — 14, y / 2 + 6);
Console.WriteLine("0″);
Console.SetCursorPosition(x / 2 — 14, y / 2 + 7);
Console.WriteLine("000000000000000000000000000″);
Console.SetCursorPosition(x / 2 — 10, y / 2 + 8);
Console.WriteLine("4. Рекорди 0″);
Console.WriteLine("0000000000000000000000000000000000000000000 000″);
Console.SetCursorPosition(x / 2 — 10, y / 2 + 10);
Console.WriteLine("5. Вихід");
ConsoleKeyInfo keyInfo = Console.ReadKey();

switch (keyInfo.Key)
{
case ConsoleKey.D1:
Console.Clear();
Console.WriteLine("Керування: ←, →, ↑, ↓");
Console.WriteLine("Ваша мета — з’їсти якомога більше їжі, не зіткнувшись зі стінами або самою собою." +
" Є два вида їжі: ’☺’, ’X’, де ☺ - хороша(+1), а X — погана(-1). ");
Console.WriteLine("Натисніть будь-яку клавішу, щоб продовжити...");
Console.ReadKey();
break;

case ConsoleKey.D2:
Console.Clear();
Console.WriteLine("Змійка (Snake Game) — це жанр відеоігор,");
Console.WriteLine("де гравець керує точкою, квадратом або об’єктом на площині з чіткими межами.");
Console.WriteLine("Натисніть будь-яку клавішу, щоб продовжити...");
Console.ReadKey();
break;

case ConsoleKey.D3:
Console.Clear();
StartGame();
break;

case ConsoleKey.D4:
ShowHighScores(); // Виклик функції для відображення рекордів
break;

case ConsoleKey.D5:
exit = true;
break;

default:
Console.Clear();
Console.WriteLine("Невідомий вибір. Натисніть будь-яку клавішу, щоб продовжити...");
Console.ReadKey();
break;
}
}
}
if (choice == 2)
{
Console.Clear();
Console.SetCursorPosition(x / 2 — 30, y / 2);
Console.WriteLine("Гра почнеться спочатку. Натисніть ENTER, щоб почати гру знову");

ConsoleKeyInfo restartKeyInfo = Console.ReadKey();

if (restartKeyInfo.Key == ConsoleKey.Enter)
{
Console.Clear();
score = 0;
StartGame();
}
else
{
Console.Clear();
Console.WriteLine("Некоректний ввід. Спробуйте ще раз.");
Console.ReadKey();
}
}
if (choice == 3)
{
Console.Clear();
ShowHighScores();

}
}
}


if (snake.Eat(foodFactory.Food))
{
foodFactory.CreateFood();
score++;
}

Console.Clear();
walls.Draw();
snake.Draw();
foodFactory.DrawFood();
}

static void ShowHighScores()
{
Console.Clear();
Console.WriteLine("Топ-10 рекордів:");

ScoreManager scoreManager = new ScoreManager("scores.txt");
List<int> highScores = scoreManager.GetHighScores().Take(10).ToList();

if (highScores.Any())
{
for (int i = 0; i < highScores.Count; i++)
{
Console.WriteLine($"{i + 1}. {highScores[i]}");
}
}
else
{
Console.WriteLine("Рекордів поки немає.");
}

Console.WriteLine("Натисніть будь-яку клавішу для продовження...");
Console.ReadKey();
}


static void DisplayUnknownOption()
{
Console.Clear();
Console.WriteLine("Невідома опція. Спробуйте ще раз.");
Console.ReadKey();
}
}

class Walls
{
private char wallChar;
private List<Point> body;

public Walls(int consoleWidth, int consoleHeight, char wallChar)
{
this.wallChar = wallChar;
body = new List<Point>();

DrawHorizontal(consoleWidth, 0);
DrawHorizontal(consoleWidth, consoleHeight — 1);
DrawVertical(0, consoleHeight);
DrawVertical(consoleWidth — 1, consoleHeight);
}

private void DrawHorizontal(int consoleWidth, int y)
{
for (int x = 0; x < consoleWidth; x++)
{
body.Add(new Point(x, y, wallChar));
}
}

private void DrawVertical(int x, int consoleHeight)
{
for (int y = 0; y < consoleHeight; y++)
{
body.Add(new Point(x, y, wallChar));
}
}

public void Draw()
{
foreach (Point point in body)
{
point.Draw();
}
}

public bool IsHit(Point point)
{
foreach (Point wallPoint in body)
{
if (wallPoint.IsHit(point))
return true;
}
return false;
}
}

class FoodFactory
{
private int consoleWidth;
private int consoleHeight;
private char foodChar;
private Point food;

public Point Food { get { return food; } }

public FoodFactory(int consoleWidth, int consoleHeight, char foodChar)
{
this.consoleWidth = consoleWidth;
this.consoleHeight = consoleHeight;
this.foodChar = foodChar;
}

public void CreateFood()
{
Random random = new Random();
food = new Point(random.Next(2, consoleWidth — 2), random.Next(2, consoleHeight — 2), foodChar);
food.Draw();
}

public void DrawFood()
{
food.Draw();
}
}
class Point
{
public int x { get; private set; }
public int y { get; private set; }
private char sym;

public Point(int x, int y, char sym)
{
this.x = x;
this.y = y;
this.sym = sym;
}

public void Draw()
{
Console.SetCursorPosition(x, y);
Console.Write(sym);
}

public bool IsHit(Point p)
{
return p.x == this.x && p.y == this.y;
}
}


class Snake
{
private List<Point> body;
private int dx;
private int dy;
private readonly bool rotationChanged;

public Snake(int x, int y, int length)
{
body = new List<Point>();
for (int i = 0; i < length; i++)
{
body.Add(new Point(x — i, y, ’0′));
}

dx = 1;
dy = 0;
rotationChanged = false;
}

public Point GetHead()
{
return body.First();
}

public void Move()
{
Point tail = body.Last();
body.Remove(tail);

Point head = GetNextPoint();
body.Insert(0, head);

tail.Draw();
head.Draw();
}

public void Rotation(ConsoleKey key)
{
switch (key)
{
case ConsoleKey.UpArrow:
if (dy != 1) // Ensure the snake cannot turn 180 degrees on itself
{
dx = 0;
dy = −1;
}
break;
case ConsoleKey.DownArrow:
if (dy != −1)
{
dx = 0;
dy = 1;
}
break;
case ConsoleKey.LeftArrow:
if (dx != 1)
{
dx = −1;
dy = 0;
}
break;
case ConsoleKey.RightArrow:
if (dx != −1)
{
dx = 1;
dy = 0;
}
break;
}
}

private Point GetNextPoint()
{
Point head = GetHead();
Point nextPoint = new Point(head.x + dx, head.y + dy, ’0′);
return nextPoint;
}

public bool Eat(Point food)
{
Point head = GetHead();
if (head.IsHit(food))
{
body.Add(food);
return true;
}
return false;
}


public bool IsHit(Point point)
{
for (int i = 1; i < body.Count; i++)
{
if (body[i].IsHit(point))
return true;
}
return false;
}

public void Draw()
{
foreach (Point point in body)
{
point.Draw();
}
}
}

class ScoreManager
{
private string filePath;

public ScoreManager(string filePath)
{
this.filePath = filePath;
}

public List<int> GetHighScores()
{
if (File.Exists(filePath))
{
string[] lines = File.ReadAllLines(filePath);
return lines.Select(line => int.Parse(line)).OrderByDescending(score => score).ToList();
}
return new List<int>();
}

public void SaveScore(int score)
{
if (!File.Exists(filePath))
{
File.Create(filePath).Close();
}

List<int> scores = GetHighScores();
scores.Add(score);
scores = scores.OrderByDescending(s => s).Take(5).ToList();

File.WriteAllLines(filePath, scores.Select(s => s.ToString()));
}
}
}

Підписуйтеся на Telegram-канал @gamedev_dou, щоб не пропустити найважливіші статті і новини про геймдев

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Прочитайте про «double buffering» (может быть даже так, или есть варианты названий типа shadow screen).
Это универсальный подход против проблем показа состояния при частичной перерисовке, хотя, может, для вас и оверкилл — тогда попробуйте что-то попроще.

The flickering of the screen might be caused by the continuous redrawing of the game elements without proper clearing of the console. The Console.Clear() method is used in various places, but the continuous loop in the StartGame method and the absence of a delay between frames may lead to flickering.

Here are a few suggestions to reduce flickering:

Clear the Console Once per Frame:
Instead of clearing the console multiple times during the game loop, try clearing it once at the beginning of each frame. Move Console.Clear() outside the loop in the StartGame method.

Підписатись на коментарі