Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Генерация лабиринта. Python / Отчет по курсовой за 3 семестр

.docx
Скачиваний:
43
Добавлен:
12.02.2018
Размер:
67.25 Кб
Скачать

МИНОБРНАУКИ РОССИИ

САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ

ЭЛЕКТРОТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ

«ЛЭТИ» ИМ. В.И. УЛЬЯНОВА (ЛЕНИНА)

Кафедра автоматики и процессов управления

ОТЧЕТ

по курсовой работе

по дисциплине «Программирование»

Тема: Генерация лабиринтов

Студентка гр. 5371

Локкина О.С.

Преподаватель

Жеронкин К.М.

Санкт-Петербург

2016

Оглавление

1.Задание курсовой работы 2

2.Описание алгоритма генерации 3

3.Сущность данных 3

4.Интерфейс программы 4

5.Исходный код программы 5

6.Дальнейшее развитие 7

  1. Задание курсовой работы

Задание курсовой работы состоит в создании работающего алгоритма генерации лабиринтов.

  1. Описание алгоритма генерации

Изначально лабиринт задается в виде решетки, т.е. сначала все ячейки имеют стенки.

Ячейки задаются как массив, в котором на первых двух позициях стоят координаты клетки, а последнее значение определяет является ли ячейка посещенной (1) или нет (0 – по умолчанию).

Стены описываются одним целым числом: 1 означает, что стена существует; 0 – нет.

Так как ячейки и стены задаются отдельными объектами, то при условии, что желаемая размерность лабиринта составляет w0 единиц по ширине и h0 – по высоте, исходный размер используемой матрицы будет составлять 2w0+1 на 2h0+1 кв. единиц.

Также необходимо создать стэк, в котором будет хранится цепь из посещенных клеток.

В самом начале случайно выбирается ячейка, находящаяся в первом столбце лабиринта, и помещается в стек. От нее пойдет генерироваться лабиринт. Слева от этой ячейки убирается стена для обозначения входа.

Далее с помощью функции getNeighbours, описанной ниже, и функции randint, находящейся в библиотеке random, из непосещённых соседей клетки случайно берется один сосед, который добавляется в стэк и становится исходной клеткой. Между ячейкой и ее выбранным соседом убирается стенка с помощью функции removeWall.

В случае, когда у клетки нет непосещенных соседей, из стэка выкидывается одна ячейка, а для следующей идущей в стэке также происходит проверка на соседей и так далее до тех пор, пока количество непосещенных клеток не станет равным нулю.

В самом конце программы из крайнего правого столбца лабиринта случайно определяется ячейка, справа от которой убирается стенка для обозначения выхода.

Использование стэка гарантирует единственность пути.

  1. Сущность данных

Код был написан на языке Python из-за простоты использования в нем динамической памяти.

Для работы генератора случайных чисел была импортирована библиотека random. Использован модуль turtle (черепашка) для отрисовки получившегося лабиринта.

В программе используется 4 функции:

  • getNeighbours для получения списка непосещенных соседей исходной ячейки.

  • removeWall для удаления стены между двумя ячейками лабиринта

  • drawturtle для отрисовки лабиринта с помощью черепашки

  • drawconsole для вывода лабиринта в консоль

Ниже приведены коды этих функций:

def getNeighbours(mh,mw,cell,m):

res=[]

x=cell[0]

y=cell[1]

if (y+2)<mw and m[x][y+2][-1]!=1: #right

res.append(m[x][y+2])

if (x+2)<mh and m[x+2][y][-1]!=1: #down

res.append(m[x+2][y])

if (y-2)>0 and m[x][y-2][-1]!=1: #left

res.append(m[x][y-2])

if (x-2)>0 and m[x-2][y][-1]!=1: #up

res.append(m[x-2][y])

return res

def removeWall(cf,cs,m):

x=(cf[0]-cs[0])//2

y=(cf[1]-cs[1])//2

m[cs[0]+x][cs[1]+y]=0

def drawturtle(m,mh,mw,d,a):

hideturtle()

pensize(5)

speed(0)

for i in range(mh):

if(not i%2):

penup()

setposition(0-a,-d*i+a)

seth(0)

pendown()

for k in range(len(m[i][:-1])):

if(m[i][k] and m[i][k+1]):

forward(d)

else:

penup()

forward(d)

pendown()

else:

for t in range(0,mw,2):

if(m[i][t]):

penup()

setposition(d*t-a,-d*(i-1)+a)

pendown()

seth(270)

forward(2*d)

def drawconsole(m,mh):

for i in range(mh):

if(i%2==0):

t=['■■' if x else ' ' for x in m[i]]

print(''.join(x for x in t))

else:

t=['■■ ' if x else ' ' for x in m[i][::2]]

print(''.join(x for x in t))

  1. Интерфейс программы

Приведены два варианта вывода лабиринта:

Консоль

Черепашка

  1. Исходный код программы

from turtle import *

import random

def getNeighbours(mh,mw,cell,m):

res=[]

x=cell[0]

y=cell[1]

if (y+2)<mw and m[x][y+2][-1]!=1: #right

res.append(m[x][y+2])

if (x+2)<mh and m[x+2][y][-1]!=1: #down

res.append(m[x+2][y])

if (y-2)>0 and m[x][y-2][-1]!=1: #left

res.append(m[x][y-2])

if (x-2)>0 and m[x-2][y][-1]!=1: #up

res.append(m[x-2][y])

return res

def removeWall(cf,cs,m):

x=(cf[0]-cs[0])//2

y=(cf[1]-cs[1])//2

m[cs[0]+x][cs[1]+y]=0

def drawturtle(m,mh,mw,d,a):

hideturtle()

pensize(5)

speed(0)

for i in range(mh):

if(not i%2):

penup()

setposition(0-a,-d*i+a)

seth(0)

pendown()

for k in range(len(m[i][:-1])):

if(m[i][k] and m[i][k+1]):

forward(d)

else:

penup()

forward(d)

pendown()

else:

for t in range(0,mw,2):

if(m[i][t]):

penup()

setposition(d*t-a,-d*(i-1)+a)

pendown()

seth(270)

forward(2*d)

def drawconsole(m,mh):

for i in range(mh):

if(i%2==0):

t=['■■' if x else ' ' for x in m[i]]

print(''.join(x for x in t))

else:

t=['■■ ' if x else ' ' for x in m[i][::2]]

print(''.join(x for x in t))

w0,h0=map(int, input("Vvedite razmernost labirinta: w,h\n>>>").strip().split(" "))

flag=int(input("\nVivesti cherez:\n1.Console;\n2.Turtle.\n>>>"))

w=2*w0+1

h=2*h0+1

maze=[]

stackcurr=[] #Цепочка посещенных клеток

unvisitedcells=w0*h0 #Количество непосещенных клеток

for i in range(h):

maze.append([])

if (i%2==0):

maze[i].extend([int(x) for x in '1'*w])

else:

for j in range(w):

if(j%2==0):

maze[i].append(1) #Стена

else:

maze[i].append([i,j,0]) #Непосещенная клетка

startcell=random.randrange(1,h,2)

currentcell=maze[startcell][1]

maze[startcell][0]=0

currentcell[-1]=1

unvisitedcells-=1

stackcurr.append(currentcell)

while (unvisitedcells):

neigh=getNeighbours(h,w,currentcell,maze)

if (neigh):

randnum=random.randint(0,len(neigh)-1)

neighbourcell=neigh[randnum]

neighbourcell[-1]=1

unvisitedcells-=1

removeWall(neighbourcell,currentcell,maze)

currentcell=neighbourcell

stackcurr.append(neighbourcell)

else:

stackcurr.pop()

currentcell=stackcurr[-1]

endcell=random.randrange(1,h,2)

maze[endcell][-1]=0

if (flag==1):

drawconsole(maze,h)

elif(flag==2):

drawturtle(maze,h,w,15,400)

  1. Дальнейшее развитие

В планах модифицировать программу для решения таких задач, как:

  • Проверка данных, веденных пользователем;

  • Поиск выхода в лабиринте;

  • Использование более быстрых и менее емких алгоритмов (алгоритм Эллера и др.);

  • Вывод лабиринта в более интерактивную форму.