first commit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/workspace.code-workspace
|
||||||
|
/__pycache__
|
||||||
286
aztecDiamond.py
Normal file
286
aztecDiamond.py
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
from tile import Tile
|
||||||
|
from tuple_addition import tuple_add as tAdd
|
||||||
|
from tkinter import Canvas, Frame, BOTH
|
||||||
|
from random import random
|
||||||
|
|
||||||
|
class AztecDiamond(Frame):
|
||||||
|
|
||||||
|
def __init__(self, x, y):
|
||||||
|
super().__init__()
|
||||||
|
self.n = 1
|
||||||
|
self.tiles = []
|
||||||
|
self.dimensions = (x, y)
|
||||||
|
self.color_neutral = "orange"
|
||||||
|
self.triag_color = "black"
|
||||||
|
self.direction_colors = ["red", "green", "yellow", "blue"]
|
||||||
|
self.direction_colored = False
|
||||||
|
self.black = True
|
||||||
|
self.initialize_draw()
|
||||||
|
self.init_tiles()
|
||||||
|
self.place()
|
||||||
|
|
||||||
|
def init_tiles(self):
|
||||||
|
i = random()
|
||||||
|
if i < 0.5:
|
||||||
|
self.tiles.append(Tile((0, 0), (0, -1), (1, 0)))
|
||||||
|
self.tiles.append(Tile((-1, 0), (-1, -1), (-1, 0)))
|
||||||
|
else:
|
||||||
|
self.tiles.append(Tile((0, 0), (-1, 0), (0, 1)))
|
||||||
|
self.tiles.append(Tile((0, -1), (-1, -1), (0, -1)))
|
||||||
|
|
||||||
|
def grow(self):
|
||||||
|
shift_dict = {} # dict that maps tile sources to shift directions to determine if two tiles shifted over each other
|
||||||
|
free_tiles = [] # list that tracks all tiles that are free to fill
|
||||||
|
|
||||||
|
self.n = self.n + 1
|
||||||
|
n = self.n
|
||||||
|
|
||||||
|
# register newgrown tiles
|
||||||
|
for i in range(n):
|
||||||
|
free_tiles.append((i, n-i-1))
|
||||||
|
free_tiles.append((-i-1, i-n))
|
||||||
|
free_tiles.append((i, -n+i))
|
||||||
|
free_tiles.append((i-n, i))
|
||||||
|
# register all tiles that will be shifting away as free (after the shift), and store the direction the shift will happen
|
||||||
|
for tile in self.tiles:
|
||||||
|
shift_dict[tile.coord_black] = tile.direction
|
||||||
|
shift_dict[tile.coord_white] = tile.direction
|
||||||
|
free_tiles.append(tile.coord_black)
|
||||||
|
free_tiles.append(tile.coord_white)
|
||||||
|
# performs the tile-shift and check for tiles that shifted over one another
|
||||||
|
tiles_to_remove = []
|
||||||
|
for tile in self.tiles:
|
||||||
|
(c1, c2) = tile.shift()
|
||||||
|
a = (0,0)
|
||||||
|
b = (0,0)
|
||||||
|
try:
|
||||||
|
a = shift_dict[tile.coord_black]
|
||||||
|
b = shift_dict[tile.coord_white]
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if (tAdd(a, tile.direction) == (0,0)) | (tAdd(b, tile.direction) == (0,0)):
|
||||||
|
tiles_to_remove.append(tile)
|
||||||
|
else:
|
||||||
|
if c1 in free_tiles:
|
||||||
|
free_tiles.remove(c1)
|
||||||
|
if c2 in free_tiles:
|
||||||
|
free_tiles.remove(c2)
|
||||||
|
for tile in tiles_to_remove:
|
||||||
|
self.tiles.remove(tile)
|
||||||
|
while True:
|
||||||
|
# finds corners that correspond to squares that will have to be filled
|
||||||
|
corners = {}
|
||||||
|
for field in free_tiles:
|
||||||
|
x = field[0]
|
||||||
|
y = field[1]
|
||||||
|
if not((x,y-1) in free_tiles):
|
||||||
|
if not((x-1,y) in free_tiles):
|
||||||
|
corners[(x,y)] = (x+1,y+1)
|
||||||
|
if not((x+1,y) in free_tiles):
|
||||||
|
corners[(x,y)] = (x-1,y+1)
|
||||||
|
elif not((x,y+1) in free_tiles):
|
||||||
|
if not((x-1,y) in free_tiles):
|
||||||
|
corners[(x,y)] = (x+1,y-1)
|
||||||
|
if not((x+1,y) in free_tiles):
|
||||||
|
corners[(x,y)] = (x-1,y-1)
|
||||||
|
# fills found squares with new tiles
|
||||||
|
worked_on = []
|
||||||
|
for corner in corners:
|
||||||
|
i = random()
|
||||||
|
(x, y) = corner
|
||||||
|
(m, n) = corners[corner]
|
||||||
|
if (x,y) in worked_on:
|
||||||
|
continue
|
||||||
|
if i < 0.5:
|
||||||
|
if x < m:
|
||||||
|
direction_x = (-1, 0)
|
||||||
|
direction_m = (1, 0)
|
||||||
|
else:
|
||||||
|
direction_x = (1, 0)
|
||||||
|
direction_m = (-1, 0)
|
||||||
|
self.tiles.append(Tile((x, y), (x, n), direction_x))
|
||||||
|
self.tiles.append(Tile((m, y), (m, n), direction_m))
|
||||||
|
else:
|
||||||
|
if y < n:
|
||||||
|
direction_y = (0, -1)
|
||||||
|
direction_n = (0, 1)
|
||||||
|
else:
|
||||||
|
direction_y = (0, 1)
|
||||||
|
direction_n = (0, -1)
|
||||||
|
self.tiles.append(Tile((x, y), (m, y), (direction_y)))
|
||||||
|
self.tiles.append(Tile((x, n), (m, n), (direction_n)))
|
||||||
|
worked_on.append((x,y))
|
||||||
|
worked_on.append((x,n))
|
||||||
|
worked_on.append((m,y))
|
||||||
|
worked_on.append((m,n))
|
||||||
|
for coord in worked_on:
|
||||||
|
free_tiles.remove(coord)
|
||||||
|
if len(free_tiles) == 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
def grow_and_draw(self):
|
||||||
|
self.grow()
|
||||||
|
self.place()
|
||||||
|
|
||||||
|
def initialize_draw(self):
|
||||||
|
self.initialize_draw_constants()
|
||||||
|
self.master.title("Aztec Diamond")
|
||||||
|
self.pack(fill=BOTH, expand=1)
|
||||||
|
self.canvas = Canvas(self)
|
||||||
|
self.canvas.pack(fill=BOTH, expand=1)
|
||||||
|
|
||||||
|
def initialize_draw_constants(self):
|
||||||
|
(x, y) = self.dimensions
|
||||||
|
self.alpha = 0.9
|
||||||
|
self.available_size = round(min(x, y)*self.alpha)
|
||||||
|
self.corner = ((x-self.available_size)/2, (y-self.available_size)/2)
|
||||||
|
|
||||||
|
def place(self):
|
||||||
|
self.canvas.delete("all")
|
||||||
|
|
||||||
|
(x, y) = self.corner
|
||||||
|
dim = self.available_size
|
||||||
|
n = self.n
|
||||||
|
stepping = dim/(2*n)
|
||||||
|
|
||||||
|
if self.black:
|
||||||
|
self.draw_line_frame(0.12, x, y, dim, n, stepping)
|
||||||
|
self.draw_tiles(0.14, x, y, dim, stepping)
|
||||||
|
|
||||||
|
self.canvas.pack(fill=BOTH, expand=1)
|
||||||
|
|
||||||
|
def draw_line_frame(self, thickness, x, y, dim, n, stepping):
|
||||||
|
self.canvas.create_line(
|
||||||
|
x+dim/2,
|
||||||
|
y,
|
||||||
|
x+dim/2,
|
||||||
|
y+dim,
|
||||||
|
width=thickness*stepping
|
||||||
|
)
|
||||||
|
self.canvas.create_line(
|
||||||
|
x,
|
||||||
|
y+dim/2,
|
||||||
|
x+dim,
|
||||||
|
y+dim/2,
|
||||||
|
width=thickness*stepping
|
||||||
|
)
|
||||||
|
for i in range(n):
|
||||||
|
self.canvas.create_rectangle(
|
||||||
|
x+stepping*i,
|
||||||
|
y+stepping*(n-i-1),
|
||||||
|
x+stepping*(2*n-i),
|
||||||
|
y+stepping*(n+i+1),
|
||||||
|
width=thickness*stepping
|
||||||
|
)
|
||||||
|
|
||||||
|
def draw_tiles(self, spacing, x, y, dim, stepping):
|
||||||
|
offset = stepping*spacing/2
|
||||||
|
edge = stepping*(1-spacing)
|
||||||
|
x_center = x+dim/2
|
||||||
|
y_center = y+dim/2
|
||||||
|
|
||||||
|
colors = {
|
||||||
|
"white": "#fff",
|
||||||
|
"black": "#000",
|
||||||
|
"red": "#f00",
|
||||||
|
"green": "#0f0",
|
||||||
|
"blue": "#00f",
|
||||||
|
"yellow": "#ff0",
|
||||||
|
"cyan": "#0ff",
|
||||||
|
"magenta": "#f0f",
|
||||||
|
"orange": "#f50"
|
||||||
|
}
|
||||||
|
if self.direction_colored:
|
||||||
|
(up, down, left, right) = self.direction_colors
|
||||||
|
else:
|
||||||
|
(up, down, left, right) = [self.color_neutral] * 4
|
||||||
|
triag_color = colors[self.triag_color]
|
||||||
|
|
||||||
|
for tile in self.tiles:
|
||||||
|
black = tile.coord_black
|
||||||
|
white = tile.coord_white
|
||||||
|
|
||||||
|
b_corner_x = (x_center + black[0]*stepping) + offset
|
||||||
|
b_corner_y = (y_center + black[1]*stepping) + offset
|
||||||
|
w_corner_x = (x_center + white[0]*stepping) + offset
|
||||||
|
w_corner_y = (y_center + white[1]*stepping) + offset
|
||||||
|
fill_corner_x = (x_center + (black[0] + white[0])/2 * stepping) + offset
|
||||||
|
fill_corner_y = (y_center + (black[1] + white[1])/2 * stepping) + offset
|
||||||
|
|
||||||
|
triag_radius = 0.35*edge
|
||||||
|
triag_center_x = fill_corner_x + edge/2
|
||||||
|
triag_center_y = fill_corner_y + edge/2
|
||||||
|
triag_offset_height = 0.5*triag_radius
|
||||||
|
triag_offset_width = 1.732050580/2*triag_radius
|
||||||
|
|
||||||
|
x_peak = triag_center_x
|
||||||
|
y_peak = triag_center_y
|
||||||
|
x_left = triag_center_x
|
||||||
|
y_left = triag_center_y
|
||||||
|
x_right = triag_center_x
|
||||||
|
y_right = triag_center_y
|
||||||
|
direction = tile.direction
|
||||||
|
if direction == (1, 0):
|
||||||
|
x_peak += triag_radius
|
||||||
|
x_left -= triag_offset_height
|
||||||
|
x_right -= triag_offset_height
|
||||||
|
y_left -= triag_offset_width
|
||||||
|
y_right += triag_offset_width
|
||||||
|
color = right
|
||||||
|
elif direction == (0, 1):
|
||||||
|
x_left += triag_offset_width
|
||||||
|
x_right -= triag_offset_width
|
||||||
|
y_peak += triag_radius
|
||||||
|
y_left -= triag_offset_height
|
||||||
|
y_right -= triag_offset_height
|
||||||
|
color = down
|
||||||
|
elif direction == (-1, 0):
|
||||||
|
x_peak -= triag_radius
|
||||||
|
x_left += triag_offset_height
|
||||||
|
x_right += triag_offset_height
|
||||||
|
y_left -= triag_offset_width
|
||||||
|
y_right += triag_offset_width
|
||||||
|
color = left
|
||||||
|
elif direction == (0, -1):
|
||||||
|
x_left += triag_offset_width
|
||||||
|
x_right -= triag_offset_width
|
||||||
|
y_peak -= triag_radius
|
||||||
|
y_left += triag_offset_height
|
||||||
|
y_right += triag_offset_height
|
||||||
|
color = up
|
||||||
|
|
||||||
|
self.canvas.create_rectangle(
|
||||||
|
b_corner_x,
|
||||||
|
b_corner_y,
|
||||||
|
b_corner_x + edge,
|
||||||
|
b_corner_y + edge,
|
||||||
|
outline=colors[color],
|
||||||
|
fill=colors[color]
|
||||||
|
)
|
||||||
|
self.canvas.create_rectangle(
|
||||||
|
w_corner_x,
|
||||||
|
w_corner_y,
|
||||||
|
w_corner_x + edge,
|
||||||
|
w_corner_y + edge,
|
||||||
|
outline=colors[color],
|
||||||
|
fill=colors[color]
|
||||||
|
)
|
||||||
|
self.canvas.create_rectangle(
|
||||||
|
fill_corner_x,
|
||||||
|
fill_corner_y,
|
||||||
|
fill_corner_x + edge,
|
||||||
|
fill_corner_y + edge,
|
||||||
|
outline=colors[color],
|
||||||
|
fill=colors[color]
|
||||||
|
)
|
||||||
|
if self.black:
|
||||||
|
self.canvas.create_polygon(
|
||||||
|
x_peak,
|
||||||
|
y_peak,
|
||||||
|
x_left,
|
||||||
|
y_left,
|
||||||
|
x_right,
|
||||||
|
y_right,
|
||||||
|
outline=triag_color,
|
||||||
|
fill=triag_color
|
||||||
|
)
|
||||||
19
main.py
Normal file
19
main.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from aztecDiamond import AztecDiamond
|
||||||
|
from resizeTracker import ResizeTracker
|
||||||
|
from menuBar import MenuBar
|
||||||
|
from tkinter import Tk
|
||||||
|
|
||||||
|
def main():
|
||||||
|
x = 10005
|
||||||
|
y = 600
|
||||||
|
root = Tk()
|
||||||
|
ad = AztecDiamond(x, y)
|
||||||
|
tracker = ResizeTracker(ad)
|
||||||
|
root.geometry(str(x)+"x"+str(y)+"+300+300")
|
||||||
|
|
||||||
|
menubar = MenuBar(root, ad)
|
||||||
|
|
||||||
|
root.mainloop()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
29
menuBar.py
Normal file
29
menuBar.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
from tkinter import Menu
|
||||||
|
|
||||||
|
class MenuBar(Menu):
|
||||||
|
|
||||||
|
def __init__(self, root, aztecDiamond):
|
||||||
|
super().__init__(root)
|
||||||
|
self.aztecDiamond = aztecDiamond
|
||||||
|
root.config(menu=self)
|
||||||
|
|
||||||
|
self.growLock = False
|
||||||
|
|
||||||
|
self.add_command(label="Grow", command=self.growDiamond)
|
||||||
|
self.add_command(label="Color", command=self.toggleColor)
|
||||||
|
self.add_command(label="NoBlack", command=self.toggleBlack)
|
||||||
|
|
||||||
|
def growDiamond(self):
|
||||||
|
if ~self.growLock:
|
||||||
|
self.growLock = ~self.growLock
|
||||||
|
self.aztecDiamond.grow_and_draw()
|
||||||
|
self.aztecDiamond.update()
|
||||||
|
self.growLock = ~self.growLock
|
||||||
|
|
||||||
|
def toggleColor(self):
|
||||||
|
self.aztecDiamond.direction_colored = not self.aztecDiamond.direction_colored
|
||||||
|
self.aztecDiamond.place()
|
||||||
|
|
||||||
|
def toggleBlack(self):
|
||||||
|
self.aztecDiamond.black = not self.aztecDiamond.black
|
||||||
|
self.aztecDiamond.place()
|
||||||
15
resizeTracker.py
Normal file
15
resizeTracker.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
class ResizeTracker:
|
||||||
|
|
||||||
|
def __init__(self, frame):
|
||||||
|
self.frame = frame
|
||||||
|
self.width = frame.winfo_width()
|
||||||
|
self.height = frame.winfo_height()
|
||||||
|
frame.bind("<Configure>", self.resize)
|
||||||
|
|
||||||
|
def resize(self, event):
|
||||||
|
if (event.widget == self.frame) and (self.width != event.width or self.height != event.height):
|
||||||
|
self.width = event.width
|
||||||
|
self.height = event.height
|
||||||
|
self.frame.dimensions = (self.width, self.height)
|
||||||
|
self.frame.initialize_draw_constants()
|
||||||
|
self.frame.place()
|
||||||
15
tile.py
Normal file
15
tile.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from tuple_addition import tuple_add as tAdd
|
||||||
|
|
||||||
|
class Tile:
|
||||||
|
|
||||||
|
def __init__(self, coord_black, coord_white, direction):
|
||||||
|
self.coord_black = coord_black
|
||||||
|
self.coord_white = coord_white
|
||||||
|
self.direction = direction
|
||||||
|
|
||||||
|
def shift(self):
|
||||||
|
self.coord_black = tAdd(self.coord_black, self.direction)
|
||||||
|
self.coord_white = tAdd(self.coord_white, self.direction)
|
||||||
|
return (self.coord_black, self.coord_white)
|
||||||
|
|
||||||
|
|
||||||
8
tuple_addition.py
Normal file
8
tuple_addition.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
def tuple_add(t1, t2):
|
||||||
|
n = len(t1)
|
||||||
|
if n != len(t2):
|
||||||
|
raise TypeError()
|
||||||
|
ret = []
|
||||||
|
for i in range(n):
|
||||||
|
ret.append(t1[i] + t2[i])
|
||||||
|
return tuple(ret)
|
||||||
Reference in New Issue
Block a user