Reputation: 3
I'm making a minesweeper game using python. I have the game working in a text only form and I'm adding a GUI now.
I have three difficulty options with different dimensions. Is there any way to generate a grid without having to make it manually. This is how I generated a square matrix in text form:
for count in range(side):
count2 = 0
temp1 = []
temp2 = []
for count2 in range(side):
temp1.append(0)
temp2.append("x")
grid.append(temp1)
field.append(temp2)
count+=1
Is there any way to automatically generate a grid like this in pygame? I am also using custom sprites and every cell needs to be clickable. Will I just have to make the grids manually and use them according to the difficulty?
Upvotes: 0
Views: 2004
Reputation: 31
I came across a similar issue, here is the solution I found worked well and is fairly simple to implement.
gridstate = {}
class Button:
def __init__(self, x, y, w, h, *get_co, action=False):
self.x = x
self.y = y
self.w = w
self.h = h
self.get_co = get_co
self.colour = (255, 255, 255)
self.clicked = False
self.box = py.draw.rect(screen, self.colour, (x, y, w, h))
self.action = action
def draw(self):
pos = py.mouse.get_pos()
if self.box.collidepoint(pos):
if py.mouse.get_pressed()[0] == 1 and self.clicked == False:
self.clicked = True
if self.action == False:
self.action = True
self.colour = (255, 0, 0)
elif self.action == True:
self.action = False
self.colour = (255, 255, 255)
if py.mouse.get_pressed()[0] == 0:
self.clicked = False
self.box = py.draw.rect(screen, self.colour,
(self.x, self.y, self.w, self.h))
gridstate.update({self.get_co: self.action})
return self.action
I created the class for the button as above, this accepts the argument "get_co" to which I put the 'co ordinate' relative to the rest of the grid so I am able to identify which button was pressed. I pass in the data in like so - This creates a 10x10 grid
resx = 10
resy = 10
buttonsize = 25
grid = []
for x in range(resx):
for y in range(resy):
grid.append(Button((x*buttonsize), (y*buttonsize),
buttonsize, buttonsize, x, y))
Within the loop of game I simply run
activecells = []
for key, value in gridstate.items():
if value == True:
activecells.append(key)
To find the clicked buttons and add them to a list to reference later.
for row in grid:
row.draw()
To draw the grid to the screen.
This seemed to do the trick for me. Apologies ahead of time for any actual programmers who will probably be horrified by my variable naming!
Upvotes: 2
Reputation: 657
There is no simple solution to draw a grid. You have to loop over each cell as you did in your example. You can find all functions to draw in the pygame wiki.
Example for grid creation:
size = (100, 100)
cell_width = 10
cell_height = 10
grid_surface = pygame.Surface(size) # here you draw
grid = [] # simple list to save your data
for x in range(side):
grid.append([]) # new column for the list
for y in range(side):
# save data to grid
grid[x][y] = "x"
# draw something
# e.g.: this draws a red rectangle in each cell
pygame.draw.rect(grid_surface, (200, 0, 0), (x * cell_width, y * cell_height, cell_width, cell_height)
Potential event loop:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
x, y = (event.pos[0] // cell_width, event.pos[1] // cell_height)
# do something
print(grid[x][y])
grid[x][y] = "a"
pygame.draw.rect(grid_surface, (0, 200, 0), (x * cell_width, y * cell_height, cell_width, cell_height)
Upvotes: 0
Reputation: 210889
I will give you a very simple start. You should create a class that represents a cell in the grid. Create a matrix of cells to represent your board:
class Cell:
def __init__(self):
self.clicked = False
grid_size = 10
board = [[Cell() for _ in range(grid_size)] for _ in range(grid_size)]
Calculate the index of a cell when the mouse button is clicked and change the attributes in the cell:
for event in pygame.event.get():
# [...]
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
row = event.pos[1] // 20
col = event.pos[0] // 20
board[row][col].clicked = True
Draw the board in 2 nested loops:
for iy, rowOfCells in enumerate(board):
for ix, cell in enumerate(rowOfCells):
color = (64, 64, 64) if cell.clicked else (164, 164, 164)
pygame.draw.rect(window, color, (ix*20, iy*20, 20, 20))
Minimal example:
import pygame
class Cell:
def __init__(self):
self.clicked = False
grid_size = 10
board = [[Cell() for _ in range(grid_size)] for _ in range(grid_size)]
pygame.init()
window = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
run = True
while run:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
row = event.pos[1] // 20
col = event.pos[0] // 20
board[row][col].clicked = True
window.fill(0)
for iy, rowOfCells in enumerate(board):
for ix, cell in enumerate(rowOfCells):
color = (64, 64, 64) if cell.clicked else (164, 164, 164)
pygame.draw.rect(window, color, (ix*20+1, iy*20+1, 18, 18))
pygame.display.flip()
pygame.quit()
exit()
Upvotes: 0