initial commit
This commit is contained in:
77
laby2/Kachel.py
Normal file
77
laby2/Kachel.py
Normal file
@ -0,0 +1,77 @@
|
||||
from PIL import Image
|
||||
from PIL import ImageDraw
|
||||
|
||||
NORTH = 0
|
||||
EAST = 1
|
||||
SOUTH = 2
|
||||
WEST = 3
|
||||
|
||||
|
||||
class Kachel:
|
||||
|
||||
def __init__(self, pos, size):
|
||||
self.dirs = [False, False, False, False]
|
||||
self.visited = False
|
||||
self.pos = pos
|
||||
self.size = size
|
||||
self.walkable = False
|
||||
|
||||
def isVisited(self):
|
||||
return self.visited
|
||||
|
||||
def getPos(self):
|
||||
return self.pos
|
||||
|
||||
def open(self, direction):
|
||||
self.dirs[direction] = True
|
||||
|
||||
def isOpen(self, direction):
|
||||
return self.dirs[direction]
|
||||
|
||||
def touch(self):
|
||||
self.visited = True
|
||||
|
||||
def makeWalkable(self):
|
||||
self.walkable = True
|
||||
|
||||
def isWalkable(self):
|
||||
return self.walkable
|
||||
|
||||
def getNumberOfOpenWays(self):
|
||||
n = 0
|
||||
for i in self.dirs:
|
||||
if i:
|
||||
n += 1
|
||||
|
||||
return n
|
||||
|
||||
def getArrayOfClosedWays(self):
|
||||
result = []
|
||||
for i in range(4):
|
||||
if not self.dirs[i]:
|
||||
result.append(i)
|
||||
return result
|
||||
|
||||
def draw(self, target, offset):
|
||||
|
||||
pos = [(self.pos[0] * self. size[0] + offset[0],
|
||||
self.pos[1] * self.size[1] + offset[1]),
|
||||
((self.pos[0] + 1) * self.size[0] + offset[0],
|
||||
self.pos[1] * self.size[1] + offset[1]),
|
||||
((self.pos[0] + 1) * self.size[0] + offset[0],
|
||||
(self.pos[1] + 1) * self.size[1] + offset[1]),
|
||||
(self.pos[0] * self.size[0] + offset[0],
|
||||
(self.pos[1] + 1) * self.size[1] + offset[1])]
|
||||
|
||||
if (not self.dirs[NORTH]):
|
||||
target.line((pos[0], pos[1]), (0, 0, 0))
|
||||
|
||||
if (not self.dirs[EAST]):
|
||||
target.line((pos[1], pos[2]), (0, 0, 0))
|
||||
|
||||
if (not self.dirs[SOUTH]):
|
||||
target.line((pos[2], pos[3]), (0, 0, 0))
|
||||
|
||||
if (not self.dirs[WEST]):
|
||||
target.line((pos[3], pos[0]), (0, 0, 0))
|
||||
|
255
laby2/Laby.py
Normal file
255
laby2/Laby.py
Normal file
@ -0,0 +1,255 @@
|
||||
#!/usr/bin/python
|
||||
from Kachel import *
|
||||
from PIL import Image
|
||||
from PIL import ImageDraw
|
||||
import random
|
||||
import sys
|
||||
import math
|
||||
|
||||
CHAR_WALL = "X"
|
||||
CHAR_START = "*"
|
||||
CHAR_END = "#"
|
||||
|
||||
|
||||
class Laby:
|
||||
|
||||
def __init__(self, size, arraySize, kachelSize, waySteps):
|
||||
self.kachelArray = []
|
||||
self.size = size
|
||||
self.arraySize = arraySize
|
||||
self.kachelSize = kachelSize
|
||||
self.img = None
|
||||
self.drawObject = None
|
||||
self.createImage()
|
||||
self.createArray()
|
||||
self.visitedFields = 0
|
||||
|
||||
self.maxWaysteps = waySteps # ein aenderung dieses wertes duerfte
|
||||
# den schwierigkeitsgrad beeinflussen
|
||||
|
||||
def createImage(self):
|
||||
self.img = Image.new("RGB", (self.size[0], self.size[1]),
|
||||
(255, 255, 255))
|
||||
self.drawObject = ImageDraw.ImageDraw(self.img)
|
||||
|
||||
def createArray(self):
|
||||
for x in range(self.arraySize[0]):
|
||||
tmp = []
|
||||
for y in range(self.arraySize[1]):
|
||||
tmp.append(Kachel((x, y), self.kachelSize))
|
||||
|
||||
self.kachelArray.append(tmp)
|
||||
|
||||
def makeAllWalkable(self):
|
||||
for y in self.kachelArray:
|
||||
for x in y:
|
||||
x.makeWalkable()
|
||||
|
||||
|
||||
|
||||
def draw(self):
|
||||
for i in self.kachelArray:
|
||||
for j in i:
|
||||
j.draw(self.drawObject, self.kachelSize)
|
||||
|
||||
def saveToTxt(self, filename):
|
||||
fobj = open(filename, "w")
|
||||
for j in range(self.arraySize[0]*2 + 1):
|
||||
fobj.write(CHAR_WALL)
|
||||
fobj.write("\n")
|
||||
for i in range(self.arraySize[1]):
|
||||
fobj.write(CHAR_WALL)
|
||||
for j in range(self.arraySize[0]):
|
||||
if (i == 0 and j == 0):
|
||||
fobj.write(CHAR_START)
|
||||
elif(i == self.arraySize[1]-1 and j == self.arraySize[0]-1):
|
||||
fobj.write(CHAR_END)
|
||||
else:
|
||||
fobj.write(" ")
|
||||
|
||||
if self.kachelArray[j][i].isOpen(EAST):
|
||||
fobj.write(" ")
|
||||
else:
|
||||
fobj.write(CHAR_WALL)
|
||||
|
||||
fobj.write("\n" + CHAR_WALL)
|
||||
for j in range(self.arraySize[0]):
|
||||
if self.kachelArray[j][i].isOpen(SOUTH):
|
||||
fobj.write(" ")
|
||||
else:
|
||||
fobj.write(CHAR_WALL)
|
||||
|
||||
fobj.write(CHAR_WALL)
|
||||
|
||||
fobj.write("\n")
|
||||
|
||||
fobj.close();
|
||||
|
||||
def showOnScreen(self):
|
||||
|
||||
self.img.show()
|
||||
|
||||
def save(self, filename):
|
||||
self.img.save(filename)
|
||||
|
||||
def openWay(self, pos, direction):
|
||||
self.kachelArray[pos[0]][pos[1]].open(direction)
|
||||
|
||||
if direction == NORTH:
|
||||
if pos[1] > 0:
|
||||
self.kachelArray[pos[0]][pos[1] - 1].open(SOUTH)
|
||||
elif direction == EAST:
|
||||
if pos[0] < self.arraySize[0] - 1:
|
||||
self.kachelArray[pos[0] + 1][pos[1]].open(WEST)
|
||||
elif direction == SOUTH:
|
||||
if pos[1] < self.arraySize[1] - 1:
|
||||
self.kachelArray[pos[0]][pos[1] + 1].open(NORTH)
|
||||
elif direction == WEST:
|
||||
if pos[0] > 0:
|
||||
self.kachelArray[pos[0] - 1][pos[1]].open(EAST)
|
||||
|
||||
def scanNeighbours(self, scanPos):
|
||||
scanResult = [0, 0, 0, 0] # 0 = nix, 1 = unbesucht, 2 = besucht
|
||||
# NORTH:
|
||||
if scanPos[1] > 0:
|
||||
north = self.kachelArray[scanPos[0]][scanPos[1] - 1]
|
||||
if north.isWalkable():
|
||||
if north.isVisited():
|
||||
scanResult[NORTH] = 2
|
||||
else:
|
||||
scanResult[NORTH] = 1
|
||||
# SOUTH:
|
||||
if scanPos[1] < self.arraySize[1] - 1:
|
||||
south = self.kachelArray[scanPos[0]][scanPos[1] + 1]
|
||||
if south.isWalkable():
|
||||
if south.isVisited():
|
||||
scanResult[SOUTH] = 2
|
||||
else:
|
||||
scanResult[SOUTH] = 1
|
||||
# WEST:
|
||||
if scanPos[0] > 0:
|
||||
west = self.kachelArray[scanPos[0] - 1][scanPos[1]]
|
||||
if west.isWalkable():
|
||||
if west.isVisited():
|
||||
scanResult[WEST] = 2
|
||||
else:
|
||||
scanResult[WEST] = 1
|
||||
# EAST:
|
||||
if scanPos[0] < self.arraySize[0] - 1:
|
||||
east = self.kachelArray[scanPos[0] + 1][scanPos[1]]
|
||||
if east.isWalkable():
|
||||
if east.isVisited():
|
||||
scanResult[EAST] = 2
|
||||
else:
|
||||
scanResult[EAST] = 1
|
||||
|
||||
return scanResult
|
||||
|
||||
def bakeWay(self, startPos):
|
||||
self.pos = startPos
|
||||
for c in range(self.maxWaysteps): # pro weg maximal waysteps schritte
|
||||
|
||||
self.kachelArray[self.pos[0]][self.pos[1]].touch()
|
||||
self.visitedFields += 1
|
||||
neighbours = self.scanNeighbours(self.pos)
|
||||
if neighbours.count(1) == 0:
|
||||
break
|
||||
|
||||
possibleDirections = []
|
||||
for i in range(4):
|
||||
if neighbours[i] == 1:
|
||||
possibleDirections.append(i)
|
||||
|
||||
#zufaellige richtung waehlen:
|
||||
nextDir = random.sample(possibleDirections, 1)[0]
|
||||
self.openWay(self.pos, nextDir)
|
||||
|
||||
#zur naechsten Kachel gehen:
|
||||
if nextDir == NORTH:
|
||||
self.pos = (self.pos[0], self.pos[1] - 1)
|
||||
|
||||
elif nextDir == EAST:
|
||||
self.pos = (self.pos[0] + 1, self.pos[1])
|
||||
|
||||
elif nextDir == SOUTH:
|
||||
self.pos = (self.pos[0], self.pos[1] + 1)
|
||||
|
||||
elif nextDir == WEST:
|
||||
self.pos = (self.pos[0] - 1, self.pos[1])
|
||||
|
||||
def bakeLaby(self, startPos, isFirstBake):
|
||||
if isFirstBake:
|
||||
print("Berechne Labyrinth...")
|
||||
self.bakeWay(startPos)
|
||||
unvisitedCounter = (self.arraySize[0]*self.arraySize[1]
|
||||
- self.visitedFields)
|
||||
|
||||
while unvisitedCounter > 0:
|
||||
#fortschritt in Prozent
|
||||
print(str(float(self.visitedFields * 100.0)
|
||||
/ float(self.arraySize[0] * self.arraySize[1])) + "%")
|
||||
# zaehle unbesuchte, an besuchten Feldern angrenzende Felder
|
||||
neighbours = []
|
||||
unvisitedCounter = 0
|
||||
for y in self.kachelArray:
|
||||
for x in y:
|
||||
if not x.isVisited():
|
||||
|
||||
if self.scanNeighbours(x.getPos()).count(2) > 0:
|
||||
unvisitedCounter += 1
|
||||
neighbours.append(x)
|
||||
|
||||
if unvisitedCounter > 0:
|
||||
nextPos = random.sample(neighbours, 1)[0]
|
||||
tmp = self.scanNeighbours(nextPos.getPos())
|
||||
possibleConnectDirs = []
|
||||
for i in range(4):
|
||||
if tmp[i] == 2:
|
||||
possibleConnectDirs.append(i)
|
||||
|
||||
connectDir = random.sample(possibleConnectDirs, 1)[0]
|
||||
self.openWay(nextPos.getPos(), connectDir)
|
||||
self.bakeWay(nextPos.getPos())
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
#programmaufruf: Laby.py [W] [H] [Feldgroesse] [filename]
|
||||
|
||||
try:
|
||||
KACHELSIZE = int(sys.argv[3])
|
||||
WIDTH = int(sys.argv[1])
|
||||
HEIGHT = int(sys.argv[2])
|
||||
FILENAME = sys.argv[4]
|
||||
|
||||
except:
|
||||
print("\nFehlerhafte Parameter!")
|
||||
print("Benoetigte Parameter:"
|
||||
+ "[BREITE] [HOEHE] [FELDGROESSE] [DATEINAME] <WAYSTEPS>"
|
||||
+ "\n\nBREITE: die Breite des Labyrinthes in Anzahl an Feldern"
|
||||
+ "\n\nHOEHE: die Hoehe des Labyrinthes in Anzahl an Feldern"
|
||||
+ "\n\nFELDGROESSE: Kantenlaenge eines Feldes in Pixeln"
|
||||
+ "\n\nDATEINAME: Dateiname fuer das fertige Labyrinth (ohne dateiendung)"
|
||||
+ "\n\nWAYSTEPS(optional): gibt die maximale Laenge eines "
|
||||
+ "\nWegstuecks in Feldern an, die ohne Abzweigung vom Algorithmus"
|
||||
+ "\ngeneriert werden kann. Pauschal kann man sagen: je kleiner "
|
||||
+ "\nder Wert, desto kuerzer ist der kuerzeste Weg zwischen zwei "
|
||||
+ "\nPunkten im Labyrinth. Standardwert ist 100 \n")
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
# optionale Argumente:
|
||||
try:
|
||||
WAYSTEPS = int(sys.argv[5])
|
||||
except:
|
||||
WAYSTEPS = 100
|
||||
|
||||
laby = Laby(((WIDTH + 2) * KACHELSIZE, (HEIGHT + 2) * KACHELSIZE),
|
||||
(WIDTH, HEIGHT), (KACHELSIZE, KACHELSIZE), WAYSTEPS)
|
||||
laby.makeAllWalkable()
|
||||
laby.bakeLaby((0, 0),True)
|
||||
laby.saveToTxt(FILENAME + ".txt")
|
||||
laby.openWay((0, 0), WEST)
|
||||
laby.openWay((WIDTH - 1, HEIGHT - 1), EAST)
|
||||
laby.draw()
|
||||
laby.save(FILENAME + ".png")
|
||||
laby.showOnScreen()
|
Reference in New Issue
Block a user