Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/60: Рейтинг темы: голосов - 60, средняя оценка - 4.57
0 / 0 / 0
Регистрация: 06.05.2019
Сообщений: 1
1

Генерация проходимого лабиринта для игры

06.05.2019, 17:12. Показов 11138. Ответов 8

Author24 — интернет-сервис помощи студентам
помогите пожалуйста я написал часть игры лабиринт надо чтобы он генерировался случайно но был проходим. там должны быть еда стены и враги и сам герой. вот что пока есть:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
 
 namespace jfnvf
    {
        public partial class Form1 : Form
        {
            int[,] Map;
 
            public Form1()
            {
                
                Random rnd = new Random();
                Map = new int[60, 30];
                for (int x = 0; x < 60; x++)
                    for (int y = 0; y < 30; y++)
                        Map[x, y] = rnd.Next(4);
            }
 
            void DrawBox(int x, int y, Brush br, Graphics gr)
            {
                gr.FillRectangle(br, x * 20, y * 20, 20, 20);
            }
 
            private void pictureBox2_Paint(object sender, PaintEventArgs e)
            {
                e.Graphics.FillRectangle(Brushes.Red, 100, 100, 50, 50);
                for (int x = 0; x < 60; x++)
                    for (int y = 0; y < 30; y++)
                    {
                        switch (Map[x, y])
                        {
                            case 0:
                                DrawBox(x, y, Brushes.White, e.Graphics);
                                break;
                            case 1:
                                DrawBox(x, y, Brushes.Yellow, e.Graphics);
                                break;
                            case 2:
                                DrawBox(x, y, Brushes.Black, e.Graphics);
                                break;
                            case 3:
                                DrawBox(x, y, Brushes.Purple, e.Graphics);
                                break;
                        }
                    }
 
            }
        }
    }
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.05.2019, 17:12
Ответы с готовыми решениями:

Генерация лабиринта
Нужно написать программу на C# в формах, которая будет генерировать лабиринт. Вначале я должен...

Генерация рандомного лабиринта с циклами
Суть задачи: нужно написать программу , которая генерировала бы случайные лабиринты с циклами(по...

Генерация проходимого лабиринта
Придумал идею генерации лабиринта, не знаю теорию графов вообще. Суть в следующем: есть булевский...

Генерация лабиринта с бOльшим количеством комнат
В общем говоря, данж я сгенирировал рекурсией, и есть одна загвоздка, когда рандом сотворяет...

8
916 / 497 / 201
Регистрация: 08.10.2018
Сообщений: 1,542
Записей в блоге: 11
06.05.2019, 17:35 2
Цитата Сообщение от Андрей рыгало Посмотреть сообщение
надо чтобы он генерировался случайно но был проходим. там должны быть еда стены и враги и сам герой. вот что пока есть:
Генерация проходимого лабиринта для игры

Потрудитесь-ка объяснить, где здесь у вас: еда стены и враги и сам герой?
2
304 / 186 / 45
Регистрация: 05.07.2018
Сообщений: 580
06.05.2019, 17:50 3
ashsvis,

Не по теме:


аывхахфывахывха )000))) Хух, не хорошо ржать конечно, но....

0
916 / 497 / 201
Регистрация: 08.10.2018
Сообщений: 1,542
Записей в блоге: 11
06.05.2019, 18:10 4
aenye,

Не по теме:

я просто тоже ужасно люблю всяческие лабиринты...



Добавлено через 15 минут
Андрей рыгало,
вот интересный примерчик на хабре: Генерация и решение лабиринта с помощью метода поиска в глубину по графу
0
916 / 497 / 201
Регистрация: 08.10.2018
Сообщений: 1,542
Записей в блоге: 11
07.05.2019, 19:18 5
Статья, опубликованная в хабре (автор Михаил Лубинец, @mersinvald), на которую я ссылался, вдохновила на следующее:

Создадим приложение WinForms со стандартной формой Form1.
Для формы включим свойство AutoScroll = true. Далее, разместим на форме панель типа Panel с именем panel1, левый верхний
угол которой совместим с левым верхним углом формы, а размер panel1 оставим произвольным.
В коде формы напишем следующее:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public partial class Form1 : Form
{
    int side = 20;
    State[,] Map;
    int width = 61;
    int height = 31;
    Point currentCell;
    Stack<Point> stack;
    Random rnd;
    bool builded = false;
 
    public Form1()
    {
        InitializeComponent();
        panel1.Size = new Size(width * side, height * side);
        stack = new Stack<Point>();
        rnd = new Random(); // new Random(DateTime.Now.Millisecond);
        Map = new State[width, height];
        InitMap();
        // выбираем начальную точку стартовой
        currentCell = new Point(1, 1);
    }
    ...
}
Частные поля формы содержат:
side - размер базовой ячейки, в пикселях;
width и height - ширина и высота лабиринта в ячейках;
Для хранения лабиринта создан двухмерный массив - State[,] Map, где State - перечисление:
C#
1
2
3
4
5
6
public enum State
{
    Wall,
    Cell,
    Visited
}
В конструкторе формы задаём размеры panel1: panel1.Size = new Size(width * side, height * side); При этом у формы появятся полосы прокрутки.
Далее произведём инициализацию вспомогательных объектов для стека, генератора случайных чисел и массива Map.
Метод InitMap() создаст начальную сетку ячеек:
Генерация проходимого лабиринта для игры

Код метода InitMap()

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/// <summary>
/// Создание начальной сетки ячеек
/// </summary>
private void InitMap()
{
    for (var i = 0; i < width; i++)
    {
        for (var j = 0; j < height; j++)
        {
            if (i % 2 != 0 && j % 2 != 0 &&         // если ячейка нечетная по x и y, 
                i < width - 1 && j < height - 1)    // и при этом находится в пределах стен лабиринта
                Map[i, j] = State.Cell;             // то это КЛЕТКА
            else Map[i, j] = State.Wall;            // в остальных случаях это СТЕНА.
        }
    }
}

Назначаем стартовую ячейку: currentCell = new Point(1, 1);

Два обработчика подключены к панели panel1:
Обработчик для рисования на поверхности panel1

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
private void panel1_Paint(object sender, PaintEventArgs e)
{
    for (int x = 0; x < width; x++)
        for (int y = 0; y < height; y++)
        {
            switch (Map[x, y])
            {
                case State.Cell:
                    DrawBox(x, y, Brushes.White, e.Graphics);
                    break;
                case State.Wall:
                    DrawBox(x, y, Brushes.Black, e.Graphics);
                    break;
                case State.Visited:
                    DrawBox(x, y, Brushes.Red, e.Graphics);
                    break;
            }
        }
}
 
/// <summary>
/// Рисуем ячейку лабиринта на поверхности рисования
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="br"></param>
/// <param name="gr"></param>
void DrawBox(int x, int y, Brush br, Graphics gr)
{
    gr.FillRectangle(br, x * side, y * side, side, side);
}

Обработчик клика мышки на поверхности panel1:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
private void panel1_Click(object sender, EventArgs e)
{
    if (builded)
    {
        InitMap();
        // выбираем начальную точку стартовой
        currentCell = new Point(1, 1);
    }
    BuildMap();
    PrepareAfterBuildMap();
    builded = true;
    panel1.Invalidate();
}
Метод BuildMap() по подготовленной карте Map строит лабиринт:
Код метода BuildMap()

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/// <summary>
/// Построение лабиринта
/// </summary>
private void BuildMap()
{
    while (true)
    {
        // перемещаемся к случайному не посещённому соседу, пока таковые есть.
        var neighbours = GetNeighbours(currentCell);
        if (neighbours.Length != 0)
        {
            var randNum = rnd.Next(neighbours.Length);
            // выбираем случайного соседа
            var neighbourCell = neighbours[randNum];
            // если соседей больше чем один
            if (neighbours.Length > 1)
                stack.Push(currentCell); // то запоминаем ячейку для возврата
            // убираем стену между текущей и соседней точками
            RemoveWall(currentCell, neighbourCell);
            // помечаем текущую ячейку как посещённую
            Map[currentCell.X, currentCell.Y] = State.Visited;
            // делаем соседнюю ячейку текущей и отмечаем ее посещённой
            currentCell = neighbourCell;
        }
        else if (stack.Count > 0) // если нет соседей, возвращаемся на предыдущую запомненную ячейку
        {
            Map[currentCell.X, currentCell.Y] = State.Visited;
            currentCell = stack.Pop();
        }
        else
            break;
    }
}

Метод PrepareAfterBuildMap() очищает для созданного лабиринта состояние State.Visited и устанавливает состояние State.Cell
Код метода PrepareAfterBuildMap()

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/// <summary>
/// Очистка посещённых ячеек после построения лабиринта
/// </summary>
private void PrepareAfterBuildMap()
{
    for (var i = 0; i < width; i++)
    {
        for (var j = 0; j < height; j++)
        {
            if (Map[i, j] == State.Visited)
                Map[i, j] = State.Cell;          
        }
    }
}

Код вспомогательных функций GetNeighbours() и RemoveWall(), используемых в методе BuildMap()

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/// <summary>
/// Функция RemoveWall убирает стенку между двумя клетками
/// </summary>
/// <param name="first"></param>
/// <param name="second"></param>
private void RemoveWall(Point first, Point second)
{
    var xDiff = second.X - first.X;
    var yDiff = second.Y - first.Y;
    int addX, addY;
    var target = new Point();
 
    addX = (xDiff != 0) ? (xDiff / Math.Abs(xDiff)) : 0;
    addY = (yDiff != 0) ? (yDiff / Math.Abs(yDiff)) : 0;
 
    target.X = first.X + addX; // координаты стенки
    target.Y = first.Y + addY;
 
    Map[target.X, target.Y] = State.Visited;
}
 
/// <summary>
/// Функция GetNeighbours возвращает массив не посещённых соседей клетки
/// </summary> 
/// <param name="c"></param>
/// <returns></returns>
private Point[] GetNeighbours(Point c)
{
    const int distance = 2;
    var points = new List<Point>();
    var x = c.X;
    var y = c.Y;
    var up = new Point(x, y - distance);
    var rt = new Point(x + distance, y);
    var dw = new Point(x, y + distance);
    var lt = new Point(x - distance, y);
    var d = new Point[] { dw, rt, up, lt };
    foreach (var p in d)
    {
        // если не выходит за границы лабиринта
        if (p.X > 0 && p.X < width && p.Y > 0 && p.Y < height)
        {
            // и не посещена\является стеной
            if (Map[p.X, p.Y] != State.Wall && Map[p.X, p.Y] != State.Visited)
                points.Add(p); // записать в массив
        }
    }
    return points.ToArray();
}

При клике мышкой по поверхности panel1 строится ещё один случайный замечательный лабиринт:
Вариант 1:
Генерация проходимого лабиринта для игры

Вариант 2:
Генерация проходимого лабиринта для игры


Я думаю, это можно использовать как начальный этап для создания программы - игры, которую задумал TC
1
916 / 497 / 201
Регистрация: 08.10.2018
Сообщений: 1,542
Записей в блоге: 11
07.05.2019, 19:28 6
Осталось добавить еду стены и врагов и самого героя
0
916 / 497 / 201
Регистрация: 08.10.2018
Сообщений: 1,542
Записей в блоге: 11
30.11.2021, 08:34 7
Пересобрал проект с программой генератора лабиринта под VS2019:
Labirint.zip

На гитхабе: https://github.com/ashsvis/Labirint
1
0 / 0 / 0
Регистрация: 10.11.2022
Сообщений: 1
12.11.2022, 11:55 8
а как добавить игрока допустим, не полностью разобрался в коде
0
916 / 497 / 201
Регистрация: 08.10.2018
Сообщений: 1,542
Записей в блоге: 11
12.11.2022, 15:25 9
multitronix, “не полностью разобрался в коде"
Почитайте по ссылке в ответе #4

Добавлено через 2 часа 30 минут
Цитата Сообщение от multitronix Посмотреть сообщение
а как добавить игрока допустим
Для начала нужно расширить enum State, добавив в него значение для игрока
(и для еды и для врагов...), ну а потом придумать, как эти состояния будут отображаться, как
их можно будет перемещать по клеткам...
0
12.11.2022, 15:25
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.11.2022, 15:25
Помогаю со студенческими работами здесь

Генерация 2D лабиринта. Как продолжить после первого шага?
как мне продолжить рандом, когда после первой ставится рандомно и чтобы продолжалось using...

Генерация уровней для Лабиринта
Привет. Есть небольшой проект: Лабиринт. Как можно реализовать генерацию уровня для лабиринта? 3D....

Генерация лабиринта
Здравствуйте, прошу помощи в решении проблемы! Делаю курсовую на тему кратчайший путь из лабиринта....

Генерация лабиринта
Добрый вечер! Подскажите, как решить ошибку (Вызвано исключение по адресу 0x00271DF4 в...

Генерация лабиринта
Разработать приложение, генерирующее лабиринт размером m x n клеток. Дополнительные условия: ...

Генерация лабиринта
Нужна программка генерации лабиринта, а точнее матрицы заданного размера из 0 и 1 где 0 это проход,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru