Diagonal lines of squares in grids - python

I have a python grid class in which I am trying to create a method to get the diagonal line of tiles that a certain tile belongs to. I have succeeded in doing this for going down from left to right in a diagonal line, and would like to know how to change it so that I can go from right to left by changing the "direction" parameter. Here is my method:
def getDiagonal(self, tile, direction = 1):
index = self.index(tile)
diagonal = []
currentIndex = [i - index[0] for i in index]
while currentIndex[1] != self.y:
diagonal.append(self[currentIndex[0]][currentIndex[1]])
currentIndex = [i + 1 for i in currentIndex]
return diagonal
And here is the entire module in which the Grid class is contained:
# Grid library for Pygame by Bobby Clarke
# GNU General Public License 3.0
# Version 1.1
import pygame
import math
from fractions import gcd
from functools import reduce
def _isEven(i):
return i % 2 == 0
def product(_list):
return reduce(lambda x, y: x * y, _list, 1)
def _range(start, stop, step=1):
"""Range function which can handle floats."""
while start < stop:
yield start
start += step
def _simplify(a, b):
hcf = gcd(a, b)
return (a / hcf, b / hcf)
class Tile(pygame.Rect):
def __init__(self, point, size, colour = None, imgs = [], tags = []):
self.size = [int(i) for i in size]
self.point = point
self.colour = colour
for img in imgs:
if isinstance(img, tuple):
imgs[imgs.index(img)] = pygame.image.fromstring(img[0],
img[1],
img[2])
self.imgs = imgs[:]
self.tags = tags[:]
pygame.Rect.__init__(self, self.point, self.size)
def __lt__(self, other):
return (self.point[0] < other.point[0] or
self.point[1] < other.point[1])
def __gt__(self, other):
return (self.point[0] > other.point[0] or
self.point[1] > other.point[1])
def __le__(self, other):
return (self.point[0] <= other.point[0] or
self.point[1] <= other.point[1])
def __ge__(self, other):
return (self.point[0] >= other.point[0] or
self.point[1] >= other.point[1])
def toData(self, imgFormat = "RGBA"):
return (self.point, self.size, self.colour,
[(pygame.image.tostring(img, imgFormat),
img.get_size(), imgFormat) for img in self.imgs], self.tags)
def fromData(data, baseTile = None):
tile = Tile(*data)
if baseTile and isinstance(baseTile, Tile):
baseTile = tile
else:
return tile
def getRect(self):
return self
def getColour(self):
return self.colour
def setColour(self, colour):
self.colour = colour
def getPoint(self):
return self.point
def addTag(self, *tags):
if isinstance(tags[0], list):
self.tags.extend(tags[0])
else:
self.tags.extend(tags)
def hasTag(self, tag):
return (tag in self.tags)
def delTag(self, tag):
self.tags.remove(tag)
def clearTags(self):
self.tags = []
def addImg(self, img, resize = False):
if isinstance(img, pygame.Surface):
if img.get_rect() != self and resize:
img = pygame.transform.scale(img, (self.size))
self.imgs.append(img)
elif img is not None:
raise TypeError("Images must be pygame.Surface object")
def delImg(self, img):
self.imgs.remove(img)
def clearImgs(self):
self.imgs = []
def isClicked(self):
return self.collidepoint(pygame.mouse.get_pos())
def draw(self, surface):
if self.colour is not None:
surface.fill(self.colour, self)
for img in self.imgs:
surface.blit(img, self)
class Grid():
def __init__(self, surface, num, colour = None, tiles = None,
force_square = False):
self.WIDTH = surface.get_width()
self.HEIGHT = surface.get_height()
self.surface = surface
aspect_ratio = _simplify(self.WIDTH, self.HEIGHT)
if isinstance(num, int):
if aspect_ratio == (1, 1) or force_square:
self.x = math.sqrt(num)
self.y = math.sqrt(num)
else:
self.x = aspect_ratio[0] * (num / product(aspect_ratio))
self.y = aspect_ratio[1] * (num / product(aspect_ratio))
else:
try:
self.x = num[0]
self.y = num[1]
except TypeError:
raise TypeError("2nd argument must be int or subscriptable")
self.tilesize = (self.WIDTH / self.x,
self.HEIGHT / self.y)
self.num = num
self.colour = colour
if tiles:
if hasattr(tiles, "__getitem__") and isinstance(tiles[0], Tile):
self.tiles = tiles
else:
self.tiles = [[Tile.fromData(tile) for tile in column]
for column in tiles]
else:
self.tiles = self.maketiles(colour)
def __getitem__(self, index):
return self.tiles[index]
def __setitem__(self, index, new):
self.tiles[index] = new
def __len__(self):
return len(self.tiles)
def index(self, tile):
for column in self.tiles:
if tile in column:
return self.tiles.index(column), column.index(tile)
def getTiles(self):
"""Get all tiles. Returns a generator"""
for column in self.tiles:
for tile in column:
yield tile
def tagSearch(self, tag):
"""Search for tiles by tag. Returns a generator"""
for tile in self.getTiles():
if tile.hasTag(tag):
yield tile
def pointSearch(self, point):
"""Search for tiles by point. Returns a tile"""
for tile in self.getTiles():
if tile.collidepoint(point):
return tile
def rectSearch(self, rect):
"""Search for tiles by rect. Returns a generator"""
for tile in self.getTiles():
if tile.colliderect(rect):
yield tile
def getColumn(self, i):
return self.tiles[i]
def getRow(self, i):
return [column[i] for column in self.tiles]
def checker(self, colour1, colour2 = None):
for column in self.tiles:
for tile in column:
if _isEven(self.tiles.index(column) + column.index(tile)):
tile.setColour(colour1)
else:
if colour2:
tile.setColour(colour2)
def getDiagonal(self, tile, direction = 1):
index = self.index(tile)
diagonal = []
currentIndex = [i - index[0] for i in index]
while currentIndex[1] != self.y:
diagonal.append(self[currentIndex[0]][currentIndex[1]])
currentIndex = [i + 1 for i in currentIndex]
return diagonal
def getBetweenTiles(self, tile1, tile2):
"""Inefficient and badly implemented"""
index1 = self.index(tile1)
index2 = self.index(tile2)
if index1[0] != index2[0] and index1[1] != index2[1]:
raise ValueError("Tiles must be in same row or column")
for column in self.tiles:
if tile1 in column and tile2 in column:
return column[column.index(tile1) : column.index(tile2)]
for i in range(self.y):
row = self.getRow(i)
if tile1 in row and tile2 in row:
return row[row.index(tile1) : row.index(tile2)]
def getSurroundingTiles(self, tile, adjacent = True, diagonal = True):
di = (0, 1, 0, -1, 1, 1, -1, -1)
dj = (1, 0, -1, 0, 1, -1, 1, -1)
# indices 0 - 3 are for horizontal, 4 - 7 are for vertical
index = list(self.getTiles()).index(tile)
max_x = self.x - 1 # Offset for 0 indexing
max_y = self.y - 1
i = int(math.floor(index / self.x))
j = int(index % self.y)
surroundingTiles = []
startat = 0 if adjacent else 4
stopat = 8 if diagonal else 4
for k in range(startat, stopat):
ni = i + di[k]
nj = j + dj[k]
if ni >= 0 and nj >= 0 and ni <= max_x and nj <= max_y:
surroundingTiles.append(self[ni][nj])
surroundingTiles.reverse()
return sorted(surroundingTiles)
def draw(self, drawGrid = False, gridColour = (0, 0, 0), gridSize = 1):
for tile in self.getTiles():
tile.draw(self.surface)
if drawGrid:
pygame.draw.rect(self.surface, gridColour, tile, gridSize)
def maketiles(self, colour):
"""Make the tiles for the grid"""
tiles = []
width = self.WIDTH / self.x
height = self.HEIGHT / self.y
for i in _range(0, self.WIDTH, width):
column = []
for j in _range(0, self.HEIGHT, height):
sq = Tile((i, j), (width, height), colour)
column.append(sq)
tiles.append(column)
return tiles
def toData(self):
return (self.num, self.colour,
[[tile.toData() for tile in column] for column in self.tiles])
def fromData(data, surface):
return Grid(*([surface] + list(data)))
Update:
I have pictorial examples of what I want to do here:
https://dl.dropboxusercontent.com/u/127476718/Images/this%20tile.png
https://dl.dropboxusercontent.com/u/127476718/Images/diags.png

To find the cells along the diagonal through another cell, you must go from this cell in the 4 diagonal directions. The following algorithm finds all cells along the diagonal in a grid of size rows x columns, starting with the cell (row, column):
cells_on_diagonals.append((row, column))
for dir in [(1, 1), (1, -1), (-1, 1), (-1, -1)]:
rn, cn = row + dir[1], column + dir[0]
while 0 <= cn < columns and 0 <= rn < rows:
cells_on_diagonals.append((rn, cn))
rn += dir[1]
cn += dir[0]
Minimal example
import pygame
pygame.init()
window = pygame.display.set_mode((350, 350))
clock = pygame.time.Clock()
grid_x, grid_y = 25, 25
tile_size, rows, columns = 20, 15, 15
run = True
while run:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
mx, my = pygame.mouse.get_pos()
column, row = (mx - grid_x) // tile_size, (my - grid_y) // tile_size
cells_on_diagonals = []
if 0 <= column < columns and 0 <= row < rows:
cells_on_diagonals.append((row, column))
for dir in [(1, 1), (1, -1), (-1, 1), (-1, -1)]:
rn, cn = row + dir[1], column + dir[0]
while 0 <= cn < columns and 0 <= rn < rows:
cells_on_diagonals.append((rn, cn))
rn += dir[1]
cn += dir[0]
window.fill(0)
for row in range(rows):
for column in range(columns):
if (row, column) in cells_on_diagonals:
rect = (grid_x + column*tile_size, grid_y + row*tile_size, tile_size, tile_size)
pygame.draw.rect(window, "red", rect)
for column in range(columns+1):
x = grid_x + column*tile_size
pygame.draw.line(window, "white", (x, grid_y), (x, grid_x + rows*tile_size))
for row in range(rows+1):
y = grid_y + row*tile_size
pygame.draw.line(window, "white", (grid_x, y), (grid_x + columns*tile_size, y))
pygame.display.flip()
pygame.quit()
exit()

Related

Trying to create the game minesweeper in python using Tkinter but have a problem finding the number of neighbors around a tile

The numbers show how many neighbors the tile has and should show: 3 neighbors on each corner, 5 on all four edges, and everything else 8. but for some reason the right edge shows 6 instead of five.
Here is an image of what I just done:
from tkinter import *
from random import choice
root = Tk()
root.geometry("544x544")
# tile class
class Tile:
def __init__(self, x, y, state=0):
self.x = x
self.y = y
self.state = state
self.button = Button(root,command=self.button_command, image=empty_block, height=28, width=28)
self.listOfNeighbors = []
self.neighbors = 0
def button_command(self):
print(self.x, self.y)
def findNeighbors(self):
self.listOfNeighbors.append(board[self.y-1][self.x])
self.listOfNeighbors.append(board[self.y][self.x-1])
self.listOfNeighbors.append(board[self.y-1][self.x-1])
try: self.listOfNeighbors.append(board[self.y+1][self.x])
except: pass
try: self.listOfNeighbors.append(board[self.y+1][self.x-1])
except: pass
try: self.listOfNeighbors.append(board[self.y-1][self.x+1])
except: pass
try: self.listOfNeighbors.append(board[self.y+1][self.x+1])
except: pass
try: self.listOfNeighbors.append(board[self.y][self.x+1])
except: pass
self.sortNeighbors()
def sortNeighbors(self):
for i in self.listOfNeighbors:
if self.y == 0:
if i.y == 15: self.listOfNeighbors.remove(i);print(self.x, self.y," ", i.x, i.y)
elif self.x == 0:
if i.x == 15: self.listOfNeighbors.remove(i);print(self.x, self.y," ", i.x, i.y)
self.neighbors = len(self.listOfNeighbors)
self.button.config(image=neighbors_images[self.neighbors])
#variable
empty_block = PhotoImage(file="images/empty-block.png")
bomb_unclicked = PhotoImage(file="images/unclicked-bomb.png")
bomb_clicked = PhotoImage(file="images/bomb-at-clicked-block.png")
neighbors_images = [
PhotoImage(file="images/0.png"),
PhotoImage(file="images/1.png"),
PhotoImage(file="images/2.png"),
PhotoImage(file="images/3.png"),
PhotoImage(file="images/4.png"),
PhotoImage(file="images/5.png"),
PhotoImage(file="images/6.png"),
PhotoImage(file="images/7.png"),
PhotoImage(file="images/8.png"),
]
board = []
for y in range(16):
temp = []
for x in range(16):
temp.append(Tile(x, y))
temp[-1].button.grid(row=y, column=x)
board.append(temp)
for i in range(40):
choice(choice(board)).state = 1
for y in board:
for x in y:
x.findNeighbors()
root.mainloop()
As far as I see, the problem comes from line 42 in which I trying to remove from the list of neighbors any Tile that is outside the board.
You are making it harder on yourself. I suggest being explicit and avoid adding and then removing unnecessary neighbours:
def findNeighbors(self):
NEIGHBOURS = [
(-1, -1),
(-1, 0),
(-1, 1),
(0, -1),
(0, 1),
(1, -1),
(1, 0),
(1, 1)
]
for dx, dy in NEIGHBOURS:
if 0 <= self.x + dx < len(board[0]) and 0 <= self.y + dy < len(board):
self.listOfNeighbors.append(board[self.y + dy][self.x + dx])
self.sortNeighbors()
def sortNeighbors(self):
self.neighbors = len(self.listOfNeighbors)
self.button.config(image=neighbors_images[self.neighbors])

How to generate my maze instantly so I don't have to watch it Generate?

So I'm creating a game and I'm using Recursive backtracking algorithm to create the maze, however, I don't want it to show the maze generation and just to instantly generate the maze. I'm unsure of how to actually do this though so any help would be appreciated, I've already tried not drawing the generated white part but that then doesn't create the maze.
import pygame
import random
import time
class Cell(object):
def __init__(self, x, y, cell_size, screen, black, white, red, blue):
# position in matrix
self.x = x
self.y = y
# keeps track of which walls are still visible
self.walls = [True, True, True, True]
# checks if cell has been visited during generation
self.generated = False
# checks if cell is on path during solving
self.on_path = False
# checks if cell has been visited during solving
self.visited = False
self.cell_size = cell_size
self.screen = screen
self.black = black
self.white = white
self.red = red
self.blue = blue
def draw_cell(self):
# coordinates on screen
x = self.x * self.cell_size
y = self.y * self.cell_size
# draws a wall if it still exists
if self.walls[0]:
pygame.draw.line(self.screen, self.black, (x, y), (x + self.cell_size, y), 5)
if self.walls[1]:
pygame.draw.line(self.screen, self.black,
(x, y + self.cell_size), (x + self.cell_size, y + self.cell_size), 5)
if self.walls[2]:
pygame.draw.line(self.screen, self.black,
(x + self.cell_size, y), (x + self.cell_size, y + self.cell_size), 5)
if self.walls[3]:
pygame.draw.line(self.screen, self.black, (x, y), (x, y + self.cell_size), 5)
# marks out white if generated during generation
if self.generated:
pygame.draw.rect(self.screen, self.white, (x, y, self.cell_size, self.cell_size))
class Maze:
def __init__(self, screen, cell_size, rows, cols, white, black, red, blue):
self.screen = screen
self.cell_size = cell_size
self.rows = rows
self.cols = cols
self.state = None
self.maze = []
self.stack = []
self.current_x = 0
self.current_y = 0
self.row = []
self.neighbours = []
self.black = black
self.white = white
self.red = red
self.blue = blue
self.cell = None
def on_start(self):
# maintains the current state
# maze matrix of cell instances
self.maze = []
# stack of current cells on path
self.stack = []
self.current_x, self.current_y = 0, 0
self.maze.clear()
self.stack.clear()
for x in range(self.cols):
self.row = []
for y in range(self.rows):
self.cell = Cell(x, y, self.cell_size, self.screen, self.black, self.white, self.red, self.blue)
self.row.append(self.cell)
self.maze.append(self.row)
def in_bounds(self, x, y):
return 0 <= x < self.cols and 0 <= y < self.rows
def find_next_cell(self, x, y):
# keeps track of valid neighbors
self.neighbours = []
# loop through these two arrays to find all 4 neighbor cells
dx, dy = [1, -1, 0, 0], [0, 0, 1, -1]
for d in range(4):
# add cell to neighbor list if it is in bounds and not generated
if self.in_bounds(x + dx[d], y + dy[d]):
if not self.maze[x + dx[d]][y + dy[d]].generated:
self.neighbours.append((x + dx[d], y + dy[d]))
# returns a random cell in the neighbors list, or -1 -1 otherwise
if len(self.neighbours) > 0:
return self.neighbours[random.randint(0, len(self.neighbours) - 1)]
else:
return -1, -1
def remove_wall(self, x1, y1, x2, y2):
# x distance between original cell and neighbor cell
xd = self.maze[x1][y1].x - self.maze[x2][y2].x
# to the bottom
if xd == 1:
self.maze[x1][y1].walls[3] = False
self.maze[x2][y2].walls[1] = False
# to the top
elif xd == -1:
self.maze[x1][y1].walls[1] = False
self.maze[x2][y2].walls[3] = False
# y distance between original cell and neighbor cell
xy = self.maze[x1][y1].y - self.maze[x2][y2].y
# to the right
if xy == 1:
self.maze[x1][y1].walls[0] = False
self.maze[x2][y2].walls[2] = False
# to the left
elif xy == -1:
self.maze[x1][y1].walls[2] = False
self.maze[x2][y2].walls[0] = False
def create_maze(self):
self.maze[self.current_x][self.current_y].generated = True
# self.maze[self.current_x][self.current_y].draw_current()
next_cell = self.find_next_cell(self.current_x, self.current_y)
# checks if a neighbor was returned
if next_cell[0] >= 0 and next_cell[1] >= 0:
self.stack.append((self.current_x, self.current_y))
self.remove_wall(self.current_x, self.current_y, next_cell[0], next_cell[1])
self.current_x = next_cell[0]
self.current_y = next_cell[1]
# no neighbor, so go to the previous cell in the stack
elif len(self.stack) > 0:
previous = self.stack.pop()
self.current_x = previous[0]
self.current_y = previous[1]
def main():
WIDTH, HEIGHT = 800, 800
CELL_SIZE = 40
ROWS, COLUMNS = int(HEIGHT / CELL_SIZE), int(WIDTH / CELL_SIZE)
# color variables
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
# initialize pygame
pygame.init()
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
SCREEN.fill(WHITE)
pygame.display.set_caption("Maze Gen")
CLOCK = pygame.time.Clock()
FPS = 60
m = Maze(SCREEN, CELL_SIZE, ROWS, COLUMNS, WHITE, BLACK, RED, BLUE)
m.on_start()
running = True
while running:
CLOCK.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
for i in range(m.cols):
for j in range(m.rows):
m.maze[i][j].draw_cell()
m.create_maze()
pygame.display.flip()
if __name__ == "__main__":
main()
pygame.quit()
Call m.create_maze() in a loop before the application loop. Terminate the loop when len(m.stack) == 0:
def main():
# [...]
m = Maze(SCREEN, CELL_SIZE, ROWS, COLUMNS, WHITE, BLACK, RED, BLUE)
m.on_start()
while True:
m.create_maze()
if len(m.stack) == 0:
break
running = True
while running:
CLOCK.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
for i in range(m.cols):
for j in range(m.rows):
m.maze[i][j].draw_cell()
pygame.display.flip()

Pathfinding Visualizer in pygame [duplicate]

This question already has answers here:
tips on Adding/creating a drop down selection box in pygame
(1 answer)
trying creating dropdown menu pygame, but got stuck
(1 answer)
Closed 1 year ago.
I am still learning how to code and wanted to create a pathfinding visualizer by following this video:
https://www.youtube.com/watch?v=JtiK0DOeI4A&ab_channel=TechWithTim
I think i understand the algorithm and the whole code more or less, but i want to expand the program. I want to implement more algorithms, some buttons and a file dialog to import and export labyrinths and stop the time the algorithm takes and some stuff like that. I know how to implement another algorithm, but i am new to Pygame, so i have no idea how to display that. I tried to combined it with PyQt5 and searched for different solutions with Pygame itself, but nothing really worked.
How can i add some bar or something like that above where i can choose the algorithm i want to use with a dropdown menu or similar and import the labyrinth and all that stuff?
This is the corresponding code:
import pygame
import math
from queue import PriorityQueue
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
PURPLE = (128, 0, 128)
ORANGE = (255, 165, 0)
GREY = (128, 128, 128)
TURQUOISE = (64, 224, 208)
class Spot:
def __init__(self, row, col, width, total_rows):
self.row = row
self.col = col
self.x = row * width
self.y = col * width
self.color = WHITE
self.neighbors = []
self.width = width
self.total_rows = total_rows
def get_pos(self):
return (self.row, self.col)
def is_closed(self):
return (self.color == RED)
def is_open(self):
return (self.color == GREEN)
def is_barrier(self):
return (self.color == BLACK)
def is_start(self):
return (self.color == ORANGE)
def is_end(self):
return (self.color == TURQUOISE)
def reset(self):
self.color = WHITE
def make_closed(self):
self.color = RED
def make_open(self):
self.color = GREEN
def make_barrier(self):
self.color = BLACK
def make_start(self):
self.color = ORANGE
def make_end(self):
self.color = TURQUOISE
def make_path(self):
self.color = PURPLE
def draw(self, win):
pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.width))
def update_neighbors(self, grid):
self.neightbors = []
if self.row < self.total_rows -1 and not grid[self.row + 1][self.col].is_barrier(): # DOWN
self.neightbors.append(grid[self.row + 1][self.col])
if self.row > 0 and not grid[self.row - 1][self.col].is_barrier(): # UP
self.neightbors.append(grid[self.row - 1][self.col])
if self.col < self.total_rows -1 and not grid[self.row][self.col + 1].is_barrier(): # RIGHT
self.neightbors.append(grid[self.row][self.col + 1])
if self.col > 0 and not grid[self.row][self.col - 1].is_barrier(): # LEFT
self.neightbors.append(grid[self.row][self.col - 1])
def __lt__(self, other):
return (False)
def h(p1, p2):
x1, y1 = p1
x2, y2 = p2
return (abs(x1 - x2) + abs(y1 - y2))
def reconstruct_path(came_from, current, draw):
while current in came_from:
current = came_from[current]
current.make_path()
draw()
def algorithm(draw, grid, start, end):
count = 0
open_set = PriorityQueue()
open_set.put((0, count, start))
came_from = {}
g_score = {spot: float ("inf") for row in grid for spot in row}
g_score[start] = 0
f_score = {spot: float ("inf") for row in grid for spot in row}
f_score[start] = h(start.get_pos(), end.get_pos())
open_set_hash = {start}
while not open_set.empty():
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
current = open_set.get()[2]
open_set_hash.remove(current)
if current == end: # draws the path
reconstruct_path(came_from, end, draw)
end.make_end()
return True
for neighbor in current.neightbors:
temp_g_score = g_score[current] + 1
if temp_g_score < g_score[neighbor]:
came_from[neighbor] = current
g_score[neighbor] = temp_g_score
f_score[neighbor] = temp_g_score + h(neighbor.get_pos(), end.get_pos())
if neighbor not in open_set_hash:
count += 1
open_set.put((f_score[neighbor], count, neighbor))
open_set_hash.add(neighbor)
neighbor.make_open()
draw()
if current != start:
current.make_closed()
return False
def make_grid(rows, width):
grid = []
gap = width // rows
for i in range(rows):
grid.append([])
for j in range(rows):
spot = Spot(i, j, gap, rows)
grid[i].append(spot)
return grid
def draw_grid(win, rows, width):
gap = width // rows
for i in range(rows):
pygame.draw.line(win, GREY, (0, i * gap), (width, i * gap))
for j in range(rows):
pygame.draw.line(win, GREY, (j * gap, 0), (j * gap, width))
def draw(win, grid, rows, width):
win.fill(WHITE)
for row in grid:
for spot in row:
spot.draw(win)
draw_grid(win, rows, width)
pygame.display.update()
def get_clicked_pos(pos, rows, width):
gap = width // rows
y, x = pos
row = y // gap
col = x // gap
return (row, col)
def main():
width = 800
win = pygame.display.set_mode((width, width))
pygame.display.set_caption("A* Path Finding Algorithm")
ROWS = 50
grid = make_grid(ROWS, width)
start = None
end = None
run = True
while run:
draw(win, grid, ROWS, width)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if pygame.mouse.get_pressed()[0]:
pos = pygame.mouse.get_pos()
row, col = get_clicked_pos(pos, ROWS, width)
spot = grid [row][col]
if not start and spot != end:
start = spot
start.make_start()
elif not end and spot != start:
end = spot
end.make_end()
elif spot != end and spot != start:
spot.make_barrier()
elif pygame.mouse.get_pressed()[2]:
pos = pygame.mouse.get_pos()
row, col = get_clicked_pos(pos, ROWS, width)
spot = grid [row][col]
spot.reset()
if spot == start:
start = None
elif spot == end:
end = None
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE and start and end:
for row in grid:
for spot in row:
spot.update_neighbors(grid)
algorithm(lambda: draw(win, grid, ROWS, width), grid, start, end)
if event.key == pygame.K_c:
start = None
end = None
grid = make_grid(ROWS, width)
pygame.quit()
if __name__ == "__main__":
main()

percolation in hexagonal lattice with 0.5 probability

I am trying to draw a (10,000 x 10,000) hexagonal lattice which is randomly half black and half white.I don't know how to fill hexagons of this lattice randomly to black and white([this is a sample of what i really want from this code but I couldn't make it.])1.here is my code(written in python language):
from __future__ import division, print_function
import math
import pygame
import random
pygame.init()
window_size = window_width, window_height = 1360, 768
rows, columns = 100, 100
fps = 10000
black = (0, 0, 0)
white = (255, 255, 255)
std_color = white
background_color =white
edge_color = black
color = black
class Hexagon(object):
"""
row: int - the row of the hexagon in the grid
col: int - the column of the hexagon in the grid
"""
def __init__(self, row, col, rows, cols, width=8):
"""
Constructs a new hexagon.
Arguments:
row: int - the row of the hexagon in the grid
col: int - the column of the hexagon in the grid
"""
self.row, self.col = row, col
self.width = width
alpha = 2*math.pi/3
self.a = width / (2*math.cos(alpha/2) + 1)
self.h = math.cos(alpha/2)*self.a
self.b = math.sin(alpha/2)*self.a*2
if row % 2 == 0:
self.x = self.a + self.h
else:
self.x = 0.0
self.x += self.col*(self.a + width)
self.y = (self.row + 1)*self.b/2
self.index = (self.row, self.col)
self.points = [
(self.x, self.y),
(self.x + self.h, self.y - self.b/2),
(self.x + self.h + self.a, self.y - self.b/2),
(self.x + width, self.y),
(self.x + self.h + self.a, self.y + self.b/2),
(self.x + self.h, self.y + self.b/2)
]
rel_indices = [
(1,0),
(2,0),
(-1,0),
(-2,0),
]
if self.row % 2 == 0:
rel_indices += [(1, 1), (-1, 1)]
else:
rel_indices += [(-1, -1), (1, -1)]
self.neighbor_indices = [((self.row + drow) % rows, (self.col + dcol) % cols)
for drow, dcol in rel_indices]
def draw(self, window, color):
pygame.draw.lines(window, edge_color, True, self.points)
grid=[Hexagon(row, col, rows, columns) for row in range(rows) for col in range(columns)]
window = pygame.display.set_mode(window_size)
pygame.display.set_caption("Hexgrid")
clock = pygame.time.Clock()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
window.fill(background_color)
for hexagon in grid:
hexagon.draw(window, std_color)
pygame.display.flip()
clock.tick(fps)
How should I do this?

Python NameError: name -- syntax error [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
I have a compiler error “not defined” although there is a definition
from gasp import *
GRID_SIZE = 30
MARGIN = GRID_SIZE
BACKGROUND_COLOR = color.BLACK # Colors we use
WALL_COLOR = (0.6 * 255, 0.9 * 255, 0.9 * 255)
# The shape of the maze. Each character
# represents a different type of object
# % - Wall
# . - Food
# o - Capsule
# G - Ghost
# P - Chomp
# Other characters are ignored
the_layout = [
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%",
"%.....%.................%.....%",
"%o%%%.%.%%%.%%%%%%%.%%%.%.%%%o%",
"%.%.....%......%......%.....%.%",
"%...%%%.%.%%%%.%.%%%%.%.%%%...%",
"%%%.%...%.%.........%.%...%.%%%",
"%...%.%%%.%.%%% %%%.%.%%%.%...%",
"%.%%%.......%GG GG%.......%%%.%",
"%...%.%%%.%.%%%%%%%.%.%%%.%...%",
"%%%.%...%.%.........%.%...%.%%%",
"%...%%%.%.%%%%.%.%%%%.%.%%%...%",
"%.%.....%......%......%.....%.%",
"%o%%%.%.%%%.%%%%%%%.%%%.%.%%%o%",
"%.....%........P........%.....%",
"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"]
class Immovable:
def is_a_wall(self):
return False
class Nothing(Immovable):
pass
class Maze:
def __init__(self):
self.have_window = False
self.game_over = False
self.set_layout(the_layout)
set_speed(20)
def set_layout(self, layout):
height = len(layout)
width = len(layout[0])
self.make_window(width, height)
self.make_map(width, height)
max_y = height - 1
for x in range( width ):
for y in range(height):
char = layout[max_y - y][x]
self.make_object((x, y), char)
def make_window(self, width, height):
grid_width = (width -1) * GRID_SIZE
grid_height = (height - 1) * GRID_SIZE
screen_width = 2 * MARGIN + grid_width
screen_height = 2 * MARGIN + grid_height
begin_graphics(screen_width, screen_height,"Chomp",BACKGROUND_COLOR)
def to_screen(self, point):
(x,y) = point
x = x * GRID_SIZE + MARGIN
y = y * GRID_SIZE + MARGIN
return(x,y)
def make_map(self, width, height):
self.width = width
self.height = height
self.map = []
for y in range(width):
new_row = []
for x in range(width):
new_row.append(Nothing())
self.map.append(new_row)
def make_object(self,point,charactor):
(x,y) = point
if charactor == "%":
self.map[y][x] = Wall(self,point)
def finished(self):
return self.game_over
def play(self):
update_when('next_tick')
def done(self):
end_graphics()
self.map = []
def object_at(self,point):
(x,y) = point
if y < 0 or y >= self.height:
return Nothing()
if x < 0 or x >= self.width:
return Nothing()
return self.map[y][x]
class Wall(Immovable):
def __init__(self, maze, point):
self.place = point # Store our position
self.screen_point = maze.to_screen(point)
self.maze = maze # Keep hold of Maze
self.draw()
def draw(self):
(screen_x, screen_y) = self.screen_point
dot_size = GRID_SIZE * 0.2
Circle(self.screen_point, dot_size,
color = WALL_COLOR, filled = 1)
(x, y) = self.place
neighbors = [ (x+1, y), (x-1, y)]
for neighbor in neighbors:
self.check_neighbor(neighbor)
def check_neighbor(self,neighbor):
maze = self.maze
object = maze.object_at(neighbor)
if object.is_a_wall():
here = self.screen_point
there = maze.to_screen(neighbor)
Line(here, there, color = WALL_COLOR,thickness = 2)
def is_a_wall(self):
return True
the_maze = Maze()
while not the_maze.finished():
the_maze.play()
the_maze.done()
I got this error..
Traceback (most recent call last): File "chomp.py", line 110, in
class Wall(Immovable): File "chomp.py", line 124, in Wall
for neighbor in neighbors: NameError: name '
neighbors' is not defined
I spent lot of time still can't find what's wrong, need some help
You never close the function call to Circle() two lines about line 122, that's probably it. You're probably missing an argument based on the trailing comma.
dot_size = GRID_SIZE * 0.2
Circle(self.screen_point, dot_size, # No closing parentheses
(x, y) = self.place
neighbors = [ (x+1, y), (x-1, y)]
for neighbor in neighbors:
self.check_neighbor(neighbor)
Circle(self.screen_point, dot_size,
missing something at the end of that line

Categories