Files
paper-racing-gpi/Examples.md
2025-10-20 19:35:38 +05:00

7.2 KiB
Raw Permalink Blame History

Примеры конфигураций карт

Простая карта (обучение)

int width = 15;
int height = 15;
var start = new Point(1, 1);

var checkpoints = new Dictionary<int, Point>
{
    { 1, new Point(5, 5) },
    { 2, new Point(10, 10) }
};

var obstacles = new HashSet<Point>();
// Простая стена
for (int x = 3; x <= 8; x++)
    obstacles.Add(new Point(x, 7));

Ожидаемое время:

  • BFS: < 1 сек
  • A*: < 0.5 сек

Средняя сложность (лабиринт)

int width = 25;
int height = 25;
var start = new Point(2, 2);

var checkpoints = new Dictionary<int, Point>
{
    { 1, new Point(8, 8) },
    { 2, new Point(20, 20) },
    { 3, new Point(22, 5) }
};

var obstacles = new HashSet<Point>();

// Горизонтальные стены
for (int x = 5; x <= 15; x++)
{
    obstacles.Add(new Point(x, 10));
    obstacles.Add(new Point(x + 5, 15));
}

// Вертикальные стены
for (int y = 5; y <= 15; y++)
{
    obstacles.Add(new Point(12, y));
    obstacles.Add(new Point(18, y));
}

// Блок препятствий
for (int x = 8; x <= 10; x++)
    for (int y = 3; y <= 5; y++)
        obstacles.Add(new Point(x, y));

Ожидаемое время:

  • BFS: 5-15 сек
  • A*: 1-3 сек

Высокая сложность (большая карта)

int width = 42;
int height = 42;
var start = new Point(2, 2);

var checkpoints = new Dictionary<int, Point>
{
    { 1, new Point(10, 10) },
    { 2, new Point(30, 35) },
    { 3, new Point(38, 8) },
    { 4, new Point(15, 30) },
    { 5, new Point(25, 15) }
};

var obstacles = new HashSet<Point>();

// Спиральный лабиринт
for (int x = 5; x <= 35; x++)
    obstacles.Add(new Point(x, 15));

for (int y = 5; y <= 35; y++)
    obstacles.Add(new Point(20, y));

for (int x = 10; x <= 30; x++)
    obstacles.Add(new Point(x, 25));

// Диагональные стены
for (int i = 0; i <= 15; i++)
{
    obstacles.Add(new Point(25 + i, 25 + i));
    obstacles.Add(new Point(10 + i, 5 + i));
}

// Комнаты
CreateRoom(obstacles, 35, 18, 3, 3);
CreateRoom(obstacles, 8, 32, 4, 4);

void CreateRoom(HashSet<Point> obs, int startX, int startY, int w, int h)
{
    for (int x = startX; x < startX + w; x++)
        for (int y = startY; y < startY + h; y++)
            obs.Add(new Point(x, y));
}

Ожидаемое время:

  • BFS: >30 сек (или не найдет)
  • A*: 1-5 сек

Экстремальная сложность (гоночная трасса)

int width = 60;
int height = 60;
var start = new Point(3, 3);

var checkpoints = new Dictionary<int, Point>
{
    { 1, new Point(15, 10) },
    { 2, new Point(45, 15) },
    { 3, new Point(50, 45) },
    { 4, new Point(25, 50) },
    { 5, new Point(10, 35) },
    { 6, new Point(30, 30) }
};

var obstacles = new HashSet<Point>();

// Внешняя граница трассы
for (int i = 5; i <= 55; i++)
{
    obstacles.Add(new Point(i, 5));
    obstacles.Add(new Point(i, 55));
    obstacles.Add(new Point(5, i));
    obstacles.Add(new Point(55, i));
}

// Внутренние препятствия - создаем узкие проходы
for (int y = 10; y <= 50; y += 10)
{
    for (int x = 10; x <= 45; x++)
    {
        if (x % 15 < 3) // Оставляем проходы
            obstacles.Add(new Point(x, y));
    }
}

// S-образные повороты
for (int i = 0; i <= 20; i++)
{
    obstacles.Add(new Point(20 + i, 20 + i / 2));
    obstacles.Add(new Point(40 - i, 30 + i / 2));
}

Ожидаемое время:

  • BFS: Может не найти решение
  • A*: 5-20 сек

Тестирование физики (ускорение)

// Длинная прямая дорога - тестирует высокие скорости
int width = 80;
int height = 20;
var start = new Point(2, 10);

var checkpoints = new Dictionary<int, Point>
{
    { 1, new Point(75, 10) }
};

var obstacles = new HashSet<Point>();

// Граничные стены
for (int x = 0; x < width; x++)
{
    obstacles.Add(new Point(x, 0));
    obstacles.Add(new Point(x, 19));
}

Ожидаемый результат:

  • Машина должна разогнаться до максимальной скорости
  • Оптимальное решение: ~10-12 ходов

Челлендж: Узкие проходы

int width = 30;
int height = 30;
var start = new Point(2, 2);

var checkpoints = new Dictionary<int, Point>
{
    { 1, new Point(15, 15) },
    { 2, new Point(27, 27) }
};

var obstacles = new HashSet<Point>();

// Создаем зигзагообразный узкий коридор
for (int y = 5; y <= 25; y++)
{
    int offset = (y / 5) % 2 == 0 ? 0 : 10;
    for (int x = 8 + offset; x <= 20 + offset; x++)
    {
        if (x < 10 + offset || x > 18 + offset)
            obstacles.Add(new Point(x, y));
    }
}

Челлендж:

  • Требует точного управления скоростью
  • Нельзя разгоняться слишком сильно
  • Тестирует алгоритм торможения

Как использовать

  1. Скопируйте нужную конфигурацию
  2. Замените код в Main метод в Program.cs или ProgramAStar.cs
  3. Запустите программу
  4. Сравните время работы BFS и A*

Генератор случайных карт

public static HashSet<Point> GenerateRandomObstacles(int width, int height, int density)
{
    var random = new Random();
    var obstacles = new HashSet<Point>();
    
    int totalCells = width * height;
    int obstacleCount = totalCells * density / 100;
    
    while (obstacles.Count < obstacleCount)
    {
        int x = random.Next(width);
        int y = random.Next(height);
        obstacles.Add(new Point(x, y));
    }
    
    return obstacles;
}

// Использование:
var obstacles = GenerateRandomObstacles(40, 40, 15); // 15% препятствий

Советы по созданию интересных карт

  1. Баланс сложности: 10-20% препятствий от площади поля
  2. Проходы: Всегда оставляйте пути между чекпоинтами
  3. Узкие места: Создают интересные челленджи для алгоритма
  4. Длинные прямые: Позволяют разгоняться
  5. Зигзаги: Требуют точного управления скоростью
  6. Комнаты: Добавляют разнообразие

Тестирование масштабируемости

# Маленькая карта (15×15, 2 чекпоинта)
# Ожидается: BFS и A* одинаково быстрые

# Средняя карта (30×30, 3 чекпоинта)
# Ожидается: A* в 2-3 раза быстрее

# Большая карта (50×50, 4 чекпоинта)
# Ожидается: A* в 5-10 раз быстрее

# Огромная карта (80×80, 5+ чекпоинтов)
# Ожидается: BFS не справится, A* найдет решение