Created
August 28, 2021 04:22
-
-
Save iam4722202468/3b4ed283c75bc11f823569ff25e08999 to your computer and use it in GitHub Desktop.
Free Flow Puzzle Generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
paths = {} | |
SIZE = 7 | |
def printPuzzle(): | |
puzzle = [] | |
for x in range(0, SIZE): | |
p_ = [] | |
for y in range(0, SIZE): | |
p_.append(-1) | |
puzzle.append(p_) | |
for colour in paths: | |
for v in paths[colour]: | |
puzzle[v[1]][v[0]] = colour | |
for x in puzzle: | |
print(x) | |
def initPuzzle(): | |
for colour in range(0,SIZE): | |
paths[colour] = [] | |
for y in range(0,SIZE): | |
paths[colour].append((colour, y)) | |
initPuzzle() | |
def distance(pos1, pos2): | |
x = pos1[0] - pos2[0] | |
y = pos1[1] - pos2[1] | |
return abs(x) + abs(y) | |
def checkDistOneCount (path): | |
distOneCount = 0 | |
for v in path: | |
for v2 in path: | |
distOneCount += distance(v, v2) == 1 | |
# Every point has two connections, left and right, except for the top and bottom. | |
# Ex. 1 - 1 - 1 has a total neighbor count of 2*1 + 2 = 4 | |
return distOneCount > 1+(len(path) - 2)*2 + 2 | |
def stepPuzzle(): | |
flowChosen = random.randrange(SIZE) | |
while len(paths[flowChosen]) <= 3: | |
flowChosen = random.randrange(SIZE) | |
isTail = bool(random.getrandbits(1)) | |
# Shorten head / tail by 1 and see if anyone can replace it | |
pos = None | |
if isTail: | |
pos = paths[flowChosen][0] | |
for colour in range(0,SIZE): | |
comparePos = paths[colour][0] | |
dist = distance(pos, comparePos) | |
if checkDistOneCount(paths[colour] + [pos]): | |
continue | |
if dist == 1: | |
oldPos = paths[flowChosen].pop(0) | |
paths[colour].insert(0, oldPos) | |
return | |
else: | |
pos = paths[flowChosen][-1] | |
for colour in range(0,SIZE): | |
comparePos = paths[colour][-1] | |
dist = distance(pos, comparePos) | |
if checkDistOneCount(paths[colour] + [pos]): | |
continue | |
if dist == 1: | |
oldPos = paths[flowChosen].pop() | |
paths[colour].append(oldPos) | |
return | |
def stepPuzzleTakeover(): | |
flowChosen = random.randrange(SIZE) | |
while len(paths[flowChosen]) <= 3: | |
flowChosen = random.randrange(SIZE) | |
pos = paths[flowChosen][0] | |
canReplace = [] | |
# Search for surrounding squares | |
for colour in paths: | |
if colour == flowChosen: | |
continue | |
for i, v in enumerate(paths[colour]): | |
if distance(pos, v) == 1: | |
if i != 0 and i != len(paths[colour])-1: | |
canReplace.append((colour, i)) | |
for c in canReplace: | |
portionUp = paths[c[0]][0:c[1]+1] + paths[flowChosen] | |
if checkDistOneCount(portionUp): | |
portionUp = [] | |
portionDown = list(reversed(paths[c[0]][c[1]:])) + paths[flowChosen] | |
if checkDistOneCount(portionDown): | |
portionDown = [] | |
if len(portionUp) > 0 and len(paths[c[0]][c[1]+1:]) >= 3: | |
paths[flowChosen] = portionUp | |
paths[c[0]] = paths[c[0]][c[1]+1:] | |
return | |
if len(portionDown) > 0 and len(paths[c[0]][:c[1]]) >= 3: | |
paths[flowChosen] = portionDown | |
paths[c[0]] = paths[c[0]][:c[1]] | |
return | |
def checkValid(): | |
for x in paths: | |
old = paths[x][0] | |
for v in paths[x][1:]: | |
dist = distance(old, v) | |
if dist != 1: | |
return False | |
old = v | |
return True | |
for v in range(0, 1000): | |
stepPuzzle() | |
stepPuzzleTakeover() | |
for x in paths: | |
print(x, paths[x]) | |
print() | |
printPuzzle() | |
print(checkValid()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment