Canvas shows only one picture(the last) from the list - python

I'm trying to draw a chessboard by canvas, but I get only one piece at the end of the code. I tried to draw a line and it still exists, but piece no!
Here is the code:
from tkinter import *
class pawn:
def __init__(self,coords, color, board):
self.color = color
self.board = board
self.type = "pawn"
self.x = coords[0]
self.y = coords[1]
pass
def draw_board(board):
root = Tk()
canvas = Canvas(root, width=512, height=512)
canvas.pack()
for line in range(8):
for cell in range(8):
if board[line][cell] != "":
l = r"C:\python\Chess\images\ "[:-1]
l = l + board[line][cell].type + board[line][cell].color[0] + ".png"
print(l)
img = PhotoImage(file=l)
canvas.create_image(32 + line*64, 32 + cell*64, image=img)
root.mainloop()
board = [[""for j in range(8)] for k in range(8)]
pawn_1 = pawn([1,1],"White",board)
pawn_2 = pawn([2,2],"Black",board)
board[2][2] = pawn_1
board[1][1] = pawn_2
draw_board(board)
It's working with one piece, but if I create 2 in the list, it'll draw only the last.

Related

tk.Misc.lift(canvas) seemingly not working

The full code for the chess game im making
import chess
#from stockfish import Stockfish
import tkinter as tk
import time
board = chess.Board()
def boardtoarr(board): #converts chess board string to 2d array
boardlist = []
linelist = []
for b in range(0,128,2):
linelist.append(str(board)[b])
if len(linelist) == 8:
boardlist.append(linelist)
linelist = []
return boardlist
#given the square of a piece on the board, returns the legal squares the piece can move to
def piecelegalmoves(square,cboard):
ans = []
for a in cboard.legal_moves:
a = str(a)
if a[0:2] == square:
ans.append(a[2::])
return ans
def alllegalmoves(cboard): #given a chess board it will return all legal moves
x = str(cboard.legal_moves)[38:-2]
x = x.split(', ')
return x
squarevar = [] #variable to contain the starting square and the moving-to square
def squareclicked(event):
global squarevar
x,y = event.x,event.y
#print(x,y)
#print(pixeltosquare(x,y))
#print(lsquaretocsquare(pixeltosquare(x,y)))
#squarevar.append(lsquaretocsquare(pixeltosquare(x,y)))
#print(squarevar)
return lsquaretocsquare(pixeltosquare(x,y))
def highlightlegalmoves(piece,board):
global BoardImage,redsquare
#for widget in root.winfo_children(): #code to clear page
#widget.destroy()
legalmoves = piecelegalmoves(piece,board)
canvas = tk.Canvas(root,width = BoardImage.width(), height = BoardImage.height())
#canvas = tk.Canvas(root,width = 500, height = 500)
canvas.pack()
for a in legalmoves:
x = csquaretolsquare(a)
print(x)
pixel = topleftpixels(x[0],x[1])
#canvas.create_image(0,0, image = redsquare, anchor = 'nw')
canvas.create_image(pixel[1],pixel[0], image = redsquare, anchor = 'nw')
tk.Misc.lift(canvas)
def makemoves(event): #Function to make chess moves when clicks have been inputted
global squarevar
squarevar.append(squareclicked(event))
if len(squarevar) != 2:
#print(squarevar[0])
highlightlegalmoves(squarevar[0],board)
if len(squarevar) == 2:
if squarevar[1] in piecelegalmoves(squarevar[0],board): #checking if move is legal to prevent errors (input validation)
board.push_san(squarevar[0]+squarevar[1]) #play move on backend board
squarevar = []
for widget in root.winfo_children(): #code to clear page
widget.destroy()
boardtoimage(root,str(board))
else:
squarevar = []
def topleftpixels(x,y): #returns top left pixel of given square
return [x*100,y*100]
def pixeltosquare(x,y): #given a pixel it will return what chess square it is on
x = ('000' + str(x))
x = x[len(x)-3::]
y = ('000' + str(y))
y = y[len(y)-3::]
return [int(y[0]),int(x[0])]
def csquaretolsquare(square): #converts chess square notation to list square notation
ans = []
letterorder = 'abcdefgh'
ans.append(8-int(square[1]))
ans.append(letterorder.index(square[0]))
return ans
def lsquaretocsquare(square): #converts list square notation to chess square notation
ans = ''
letterorder = 'abcdefgh'
ans += (letterorder[square[1]])
ans += str(8-square[0])
return ans
def boardtoimage(root,boardstr): #places all pieces onto the window graphically
global wQueen,wKing,wKnight,wBishop,wPawn,wRook,bQueen,bKing,bKnight,bBishop,bPawn,bRook,BoardImage
LetterToImage= {
'r': bRook, 'n': bKnight, 'b': bBishop, 'q': bQueen, 'k': bKing, 'p': bPawn,
'R': wRook, 'N': wKnight, 'B': wBishop, 'Q': wQueen, 'K': wKing, 'P': wPawn,
}
boardcanvas = tk.Canvas(root,width = BoardImage.width(), height = BoardImage.height()) #This will be the canvas for the whole board, pieces and all
boardcanvas.pack()
boardcanvas.create_image(0,0, image = BoardImage, anchor = 'nw') #placing chess board on canvas
#iterate through board and place piece images in correct place
for y in range(8):
for x in range(8):
piece = boardtoarr(boardstr)[y][x]
if piece in LetterToImage.keys():
boardcanvas.create_image(topleftpixels(x,y)[0], topleftpixels(x,y)[1], image=LetterToImage[piece], anchor="nw")
boolvar = False
def CMI_clicked(): #check if the chess menu image was clicked
global root
global BoardImage
global boolvar
for widget in root.winfo_children(): #code to clear page
widget.destroy()
boardtoimage(root,str(board))
root.bind("<Button-1>", makemoves)
def Menu():
global root
global ChessMenuImage
#Menu
ChessMenuOption = tk.Button(root ,image = ChessMenuImage, command = CMI_clicked) #create button using chess menu image and call function 'CMI_clicked' when pressed
ChessMenuOption.place(x = 380, y = 380) #place the chess menu image at given coordinates
root = tk.Tk()
ChessMenuImage = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\Chess_Selection_Image.png') #Load chess menu image file
BoardImage = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\ChessBoardImage.png') #Load board image file
redsquare = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\redsquare.png') #Load see-through red square file, used for showing legal moves in the GUI
#Piece image loading
#White
wQueen = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wQueen.png')
wKing = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wKing.png')
wPawn = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wPawn.png')
wBishop = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wBishop.png')
wKnight = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wKnight.png')
wRook = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\wRook.png')
#Black
bQueen = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bQueen.png')
bKing = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bKing.png')
bPawn = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bPawn.png')
bBishop = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bBishop.png')
bKnight = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bKnight.png')
bRook = tk.PhotoImage(file = r'C:\Users\benja\Documents\Python\Chess project\bRook.png')
root.geometry('800x800')
Menu()
root.mainloop()
specifically lines 47-61 'highlightlegalmoves' function
def highlightlegalmoves(piece,board):
global BoardImage,redsquare
#for widget in root.winfo_children(): #code to clear page
#widget.destroy()
legalmoves = piecelegalmoves(piece,board)
canvas = tk.Canvas(root,width = BoardImage.width(), height = BoardImage.height())
#canvas = tk.Canvas(root,width = 500, height = 500)
canvas.pack()
for a in legalmoves:
x = csquaretolsquare(a)
print(x)
pixel = topleftpixels(x[0],x[1])
#canvas.create_image(0,0, image = redsquare, anchor = 'nw')
canvas.create_image(pixel[1],pixel[0], image = redsquare, anchor = 'nw')
tk.Misc.lift(canvas)
so if I run the code
for widget in root.winfo_children(): #code to clear page
widget.destroy()
the image I get (before/after I click a piece)
before:
after (I clicked the e2 pawn):
so I know that under the original canvas its actually displaying what I want. I just what to show to lift it but its not doing that.
when I have the delete all widgets code commented, the image does not change once I click a piece, it does not display the legal moves of the piece.

Error object has no attribute in Paint app

This is the code, I got it from here https://www.youtube.com/watch?v=uW-NLL9dlBs
After many attempts, I solved some issues, but I still couldnt get it to work.
Its supposed to be an app for painting. I wanted it to have very large pixels with invisible grid too, so painting in it would create low resolution pixel art, similar to this. I dont know how to do that, as I couldnt find it anywhere. pixel image
from tkinter import *
from tkinter.ttk import Scale
from tkinter import colorchooser,filedialog,messagebox
import PIL.ImageGrab as ImageGrab
class Paint():
def __init__(self,root):
self.root = root
self.root.title("Paint")
self.root.geometry("800x520")
self.root.configure(background='white')
self.root.resizable(0,0)
self.pen_color = "black"
self.eraser_color = "white"
self.color_frame = LabelFrame(self.root,text='Color',font = ('arial',15),bd=5,relief=RIDGE,bg='white')
self.color_frame.place(x=0,y=0,width=70,height=185)
colors = ['#ff0000','#ff4dd2','#ffff33','#000000','#0066ff','#660033','#4dff4d','#b300b3','#00ffff','#808080','#99ffcc','#336600','#ff9966','#ff99ff','#00cc99']
i=j=0
for color in colors:
Button(self.color_frame,bg=color,bd=2,relief=RIDGE,width=3,command=lambda col =color:self.select_color(col)).grid(row=i,column=j)
i+=1
if i==6:
i=0
j=1
self.eraser_button = Button(self.root,text="ERASER",bd=4,bg='white',command=self.eraser,width=8,relief=RIDGE)
self.eraser_button.place(x=0,y=187)
self.clear_button = Button(self.root, text="Clear",bd=4,bg='white',command=lambda : self.canvas.delete("all"),width=8,relief=RIDGE)
self.clear_button.place(x=0,y=217)
self.save_button = Button(self.root,text="Save",bd=4,bg='white',command=self.save_paint,width=8,relief=RIDGE)
self.save_button.place(x=0,y=247)
self.canvas_color_button = Button(self.root,text="Canvas", bd=4 , bg='white', command=self.canvas_color(),width=8,relief=RIDGE)
self.canvas_color_button.place(x=0, y=277)
self.pen_size_scale_frame = LabelFrame(self.root,text="size",bd=5,bg='white',font=('arial',15,'bold'),relief=RIDGE)
self.pen_size_scale_frame.place(x=0,y=310,height=200,width=70)
self.pen_size = Scale(self.pen_size_scale_frame,orient=VERTICAL,from_ = 50, to = 0,length=170)
self.pen_size.set(1)
self.pen_size.grid(row=0,column=1,padx=15)
self.canvas = Canvas(self.root,bg='white',bd=5,relief=GROOVE,height=500,width=700)
self.canvas.place(x=80,y=0)
self.canvas.bind("<B1-Motion>",self.paint)
def paint(self,event):
x1,y1 = (event.x-2),(event.y-2)
x2,y2 = (event.x + 2),(event.y + 2)
self.canvas.create_oval(x1,y1,x2,y2,fill=self.pen_color,outline=self.pen_color,width=self.pen_size.get())
def select_color(self,col):
self.pen_color = self.eraser_color
def eraser(self):
self.pen_color = "white"
def canvas_color(self):
color = colorchooser.askcolor()
self.canvas.configure(background=color[1])
self.eraser_color = color[1]
def save_paint(self):
try:
filename = asksaveasfilename(defaultextension='.jpg')
x = self.root.winfo_rooty() + self.canvas.winfo_x()
y = self.root.winfo_rooty() + self.canvas.winfo_y()
x1 = x + self.canvas.winfo_width()
y1 = y + self.canvas.winfo_height()
ImageGrab.grab().crop((x,y,x1,y1)).save(filename)
messagebox.showinfo('paint says','image is saved as ' + str(filename))
except:
messagebox.showerror("paint says","unable to save image ,\n something went wrong")
if __name__ == "__main__":
root = Tk()
p = Paint(root)
root.mainloop()
In order to get your paint program working, the following bugs need to be addressed.
The self.canvas_color_button command has a bug. Just remove the parens to make it work.
There's a problem with color selection methods.
Here is the solution.
def select_color(self,col):
self.pen_color = col
def eraser(self):
self.pen_color = self.eraser_color
When saving a drawing, the image is not cropped correctly due to other widgets.
self.color_frame has a width of 70.
Your canvas is defined with a borderwidth(5) and a highlightthickness(2).
These values must be taken into account.
Here is one solution to crop your saved images correctly.
xoffset = self.color_frame.winfo_width()
yoffset = int(self.canvas["borderwidth"]) + int(self.canvas["highlightthickness"])
x = self.root.winfo_rooty() + self.canvas.winfo_x()
y = self.root.winfo_rooty() + self.canvas.winfo_y() + yoffset
x1 = x + self.canvas.winfo_width() - xoffset
y1 = y + self.canvas.winfo_height() - (yoffset * 2)

tkinter - problem with a coloring a rectangle in a grid made out of rectangles

I am trying to write a pathfinding algorithm in python. The user is supposed to select a starting point by hovering the mouse of a field and pressing s. The field should now change the color.
However, I can't figure out what is wrong with my code. I am only able to color to color the fields from top left corner to the bottom right corner. In the code, Im printing out the objectID in console, which shows that there is maybe something wrong with the way of how I created the rectangles.
I'm creating the rectangles in the draw_grid method in the Window class and coloring the fields in the select_start_node method.
import tkinter as tk
class Window:
def __init__(self):
self.height = 600
self.width = 600
self.grid_list = {x for x in range(0, 600)}
self.grid = []
self.grid_dict = {}
self.root = tk.Tk()
self.root.geometry("600x600")
self.root.resizable(False, False)
self.canvas = tk.Canvas(self.root, width=self.width,
height=self.height, background="white")
self.canvas.bind("s", self.select_start_node)
self.canvas.bind("<1>", lambda event:
self.canvas.focus_set())
def draw_grid(self):
print(self.grid)
for x in self.grid_list:
if x % 30 == 0:
self.grid.append(x)
else:
pass
print(self.grid)
for x in self.grid:
for y in self.grid:
print(x, y+30)
rec = self.canvas.create_rectangle(x, x, y+30, y+30)
self.canvas.pack()
def select_start_node(self, event):
print(event.x, event.y)
x = self.canvas.canvasx(event.x)
y = self.canvas.canvasy(event.y)
item = self.canvas.find_closest(x, y)
p = self.canvas.coords(item)
print(item)
print(p)
self.canvas.create_rectangle(p[0], p[0], p[0]+30, p[0]+30, fill="red")
def main():
node_list = []
cord_list = []
window = Window()
window.draw_grid()
window.root.mainloop()
if __name__ == "__main__":
main()
I don't know the entire design of you game, but suggest that you do things differently with respect to the grid of rectangles. In the code below self.grid is a 2-dimensional list-of-lists and each entry is a Canvas rectangle object. This make selecting and changing one of them relatively each because canvas.find_closest(x, y) will give you the object id of the associated rectangle object directly, which makes changing its fill color trivial.
Because of that, I also changed it so you can just click on one of the rectangles to change it instead of moving the mouse cursor and then pressing a key.
Also note that I also got rid of most those hardcoded numerical constants you were using all over the place, which makes the code more flexible in case you decide to change one of them at a later time.
import tkinter as tk
class Window:
def __init__(self):
self.cell_size = 30
self.height = 600
self.width = 600
self.hz_cells = self.width // self.cell_size # Number of horizontal cells.
self.vt_cells = self.height // self.cell_size # Number of vertical cells.
# Preallocate 2D grid (list-of-lists).
self.grid = [[None for _ in range(self.hz_cells)]
for _ in range(self.vt_cells)]
self.root = tk.Tk()
self.root.geometry("%sx%s" % (self.width, self.height))
self.root.resizable(False, False)
self.canvas = tk.Canvas(self.root, width=self.width,
height=self.height, background="white")
self.canvas.pack()
self.canvas.bind("<1>", self.select_start_node)
# You can still do it this way if you want.
# self.canvas.bind("s", self.select_start_node)
# self.canvas.bind("<1>", lambda event: self.canvas.focus_set())
def draw_grid(self):
""" Fill Canvas with a grid of white rectangles. """
for i in range(self.hz_cells):
x = i * self.cell_size
for j in range(self.vt_cells):
y = j * self.cell_size
self.grid[i][j] = self.canvas.create_rectangle(
x, y, x+self.cell_size, y+self.cell_size, fill="white")
def select_start_node(self, event):
""" Change the color of the rectangle closest to x, y of event. """
x = self.canvas.canvasx(event.x)
y = self.canvas.canvasy(event.y)
selected_rect = self.canvas.find_closest(x, y)
if selected_rect:
self.canvas.itemconfigure(selected_rect, fill="red") # Change color.
def main():
node_list = []
cord_list = []
window = Window()
window.draw_grid()
window.root.mainloop()
if __name__ == "__main__":
main()

Grid Generation for minesweeper

Hi so I am making a minesweeper game and I am a bit stuck with the grid generation part. This is my code so far:
from random import randint
import pygame
def MineGen():
mineamount = 100
grid_across = 40
grid_up = 25
mine_list = []
my2dthatlist = []
numacoss = 0
for i in range (mineamount):
numacoss = randint(1,40)
my2dthatlist.append(numacoss)
numup = randint(1,25)
my2dthatlist.append(numup)
mine_list.append(my2dthatlist)
my2dthatlist = []
return mine_list
def GridGen():
grid_across = 40
grid_up = 25
GRIDD = [[0]* grid_across for i in range(grid_up)]
return GRIDD
def MineGrid(GridOutMine, mine_list):
mineplace = 0
placeX = 0
placeY = 0
for i in range(100):
mineplace = mine_list[i]
placeX = mineplace[0]
placeY = mineplace[1]
GridOutMine[placeX][placeY] = 1
print(GridOutMine)
mine_list = MineGen()
GridOutMine = GridGen()
MineGrid(GridOutMine, mine_list)
My issue is that i am getting a list index out of range for the
GridOutMine[placeX][placeY] = 1
part. I don't really know why this is. If you could give me some assistance in what to do, or just some general comments on my code, I would really appreciate it thanks.
That's because, unlike range, random.randint outputs numbers within the specified bounds inclusively. That is, randint(1, 25) could output 25, which is not a valid index for a list that's only 25 elements long (since the last index is 24).
In MineGen, you need to change randint(1, 25) to randint(1, 25-1) or randint(1, 24), and likewise for randint(1, 40) which needs to be randint(1, 39). I'd actually suggest randint(0, 24) and (0, 39), but I don't know if that's intentional.
There are many other things that could/should be improved about this code, but I'd suggest you ask for that kind of input over on CodeReview instead of here once your code is working (they don't fix broken code).
EDIT:
Also, you're indexing your grid in the wrong order. It's a list (25-long) of rows (40-long), so you need to index it in the Y dimension first, then X: GridOutMine[placeY][placeX] = 1
If you are trying to build a grid for the game and want to display buttons in a GUI your users can interact with, you may want to start with the following code as a basic framework for the rest of the code you will be writing.
import tkinter
import functools
class MineSweep(tkinter.Frame):
#classmethod
def main(cls, width, height):
root = tkinter.Tk()
window = cls(root, width, height)
root.mainloop()
def __init__(self, master, width, height):
super().__init__(master)
self.__width = width
self.__height = height
self.__build_buttons()
self.grid()
def __build_buttons(self):
self.__buttons = []
for y in range(self.__height):
row = []
for x in range(self.__width):
button = tkinter.Button(self)
button.grid(column=x, row=y)
button['text'] = '?'
command = functools.partial(self.__push, x, y)
button['command'] = command
row.append(button)
self.__buttons.append(row)
def __push(self, x, y):
print('Column = {}\nRow = {}'.format(x, y))
if __name__ == '__main__':
MineSweep.main(10, 10)
If you want a more complete example of a minesweeper game to either borrow ideas from or adapt for your own needs, the following program implements much of the functionality you might want from a finished game.
import tkinter
import functools
import random
from tkinter.simpledialog import askstring, Dialog
from tkinter.messagebox import showinfo
import os.path
################################################################################
class MineSweep(tkinter.Frame):
#classmethod
def main(cls, width, height, mines, scores):
root = tkinter.Tk()
root.resizable(False, False)
root.title('MineSweep')
window = cls(root, width, height, mines, scores)
root.protocol('WM_DELETE_WINDOW', window.close)
root.mainloop()
################################################################################
def __init__(self, master, width, height, mines, scores):
super().__init__(master)
self.__width = width
self.__height = height
self.__mines = mines
self.__wondering = width * height
self.__started = False
self.__playing = True
self.__scores = ScoreTable()
self.__record_file = scores
if os.path.isfile(scores):
self.__scores.load(scores)
self.__build_timer()
self.__build_buttons()
self.grid()
def close(self):
self.__scores.save(self.__record_file)
self.quit()
def __build_timer(self):
self.__secs = tkinter.IntVar()
self.__timer = tkinter.Label(textvariable=self.__secs)
self.__timer.grid(columnspan=self.__width, sticky=tkinter.EW)
self.__after_handle = None
def __build_buttons(self):
self.__reset_button = tkinter.Button(self)
self.__reset_button['text'] = 'Reset'
self.__reset_button['command'] = self.__reset
self.__reset_button.grid(column=0, row=1,
columnspan=self.__width, sticky=tkinter.EW)
self.__reset_button.blink_handle = None
self.__buttons = []
for y in range(self.__height):
row = []
for x in range(self.__width):
button = tkinter.Button(self, width=2, height=1,
text='?', fg='red')
button.grid(column=x, row=y+2)
command = functools.partial(self.__push, x, y)
button['command'] = command
row.append(button)
self.__buttons.append(row)
def __reset(self):
for row in self.__buttons:
for button in row:
button.config(text='?', fg='red')
self.__started = False
self.__playing = True
self.__wondering = self.__width * self.__height
if self.__after_handle is not None:
self.after_cancel(self.__after_handle)
self.__after_handle = None
self.__secs.set(0)
def __push(self, x, y, real=True):
button = self.__buttons[y][x]
if self.__playing:
if not self.__started:
self.__build_mines()
while self.__buttons[y][x].mine:
self.__build_mines()
self.__started = True
self.__after_handle = self.after(1000, self.__tick)
if not button.pushed:
self.__push_button(button, x, y)
elif real:
self.__blink(button, button['bg'], 'red')
elif real:
self.__blink(button, button['bg'], 'red')
def __blink(self, button, from_bg, to_bg, times=8):
if button.blink_handle is not None and times == 8:
return
button['bg'] = (to_bg, from_bg)[times & 1]
times -= 1
if times:
blinker = functools.partial(self.__blink, button,
from_bg, to_bg, times)
button.blink_handle = self.after(250, blinker)
else:
button.blink_handle = None
def __tick(self):
self.__after_handle = self.after(1000, self.__tick)
self.__secs.set(self.__secs.get() + 1)
def __push_button(self, button, x, y):
button.pushed = True
if button.mine:
button['text'] = 'X'
self.__playing = False
self.after_cancel(self.__after_handle)
self.__after_handle = None
self.__blink(self.__reset_button, button['bg'], 'red')
else:
button['fg'] = 'SystemButtonText'
count = self.__total(x, y)
button['text'] = count and str(count) or ' '
self.__wondering -= 1
if self.__wondering == self.__mines:
self.after_cancel(self.__after_handle)
self.__after_handle = None
self.__finish_game()
def __finish_game(self):
self.__playing = False
score = self.__secs.get()
for row in self.__buttons:
for button in row:
if button.mine:
button['text'] = 'X'
if self.__scores.eligible(score):
name = askstring('New Record', 'What is your name?')
if name is None:
name = 'Anonymous'
self.__scores.add(name, score)
else:
showinfo('You did not get on the high score table.')
HighScoreView(self, 'High Scores', self.__scores.listing())
def __total(self, x, y):
count = 0
for x_offset in range(-1, 2):
x_index = x + x_offset
for y_offset in range(-1, 2):
y_index = y + y_offset
if 0 <= x_index < self.__width and 0 <= y_index < self.__height:
count += self.__buttons[y_index][x_index].mine
if not count:
self.__propagate(x, y)
return count
def __propagate(self, x, y):
for x_offset in range(-1, 2):
x_index = x + x_offset
for y_offset in range(-1, 2):
y_index = y + y_offset
if 0 <= x_index < self.__width and 0 <= y_index < self.__height:
self.__push(x_index, y_index, False)
def __build_mines(self):
mines = [True] * self.__mines
empty = [False] * (self.__width * self.__height - self.__mines)
total = mines + empty
random.shuffle(total)
iterator = iter(total)
for row in self.__buttons:
for button in row:
button.mine = next(iterator)
button.pushed = False
button.blink_handle = None
################################################################################
class ScoreTable:
def __init__(self, size=10):
self.__data = {999: [''] * size}
def add(self, name, score):
assert self.eligible(score)
if score in self.__data:
self.__data[score].insert(0, name)
else:
self.__data[score] = [name]
if len(self.__data[max(self.__data)]) == 1:
del self.__data[max(self.__data)]
else:
del self.__data[max(self.__data)][-1]
def eligible(self, score):
return score <= max(self.__data)
def listing(self):
for key in sorted(self.__data.keys()):
for name in self.__data[key]:
yield name, key
def load(self, filename):
self.__data = eval(open(filename, 'r').read())
def save(self, filename):
open(filename, 'w').write(repr(self.__data))
################################################################################
class HighScoreView(Dialog):
def __init__(self, parent, title, generator):
self.__scores = generator
super().__init__(parent, title)
def body(self, master):
self.__labels = []
for row, (name, score) in enumerate(self.__scores):
label = tkinter.Label(master, text=name)
self.__labels.append(label)
label.grid(row=row, column=0)
label = tkinter.Label(master, text=str(score))
self.__labels.append(label)
label.grid(row=row, column=1)
self.__okay = tkinter.Button(master, command=self.ok, text='Okay')
self.__okay.grid(ipadx=100, columnspan=2, column=0, row=row+1)
return self.__okay
def buttonbox(self):
pass
################################################################################
if __name__ == '__main__':
MineSweep.main(10, 10, 10, 'scores.txt')
Reference: ActiveState Code » Recipes » MineSweep

Pygame displays black screen [duplicate]

This question already has answers here:
Why is nothing drawn in PyGame at all?
(2 answers)
Why is my PyGame application not running at all?
(2 answers)
Closed 2 years ago.
I'm trying to write a simple sokoban game in python 3.5 using Pygame, however when I run the code I just get a black background. I'm sure I'm just doing something wrong with the blit but still learning so not too sure.
Any help anyone can give would be greatly appreciated :)
import random, pygame, sys
from pygame.locals import *
from Classes import Maze, Move, Player, Box
maze = Maze()
WHITE = (255, 255, 255)
FPS = 30
WINWIDTH = 750
WINHEIGHT = 750
HALFHEIGHT = int(WINWIDTH/2)
HALFWIDTH = int(WINWIDTH/2)
#BASICFONT = pygame.font.Font('freesansbold.tff',100)
#Tile height and width in pixels
TILEWIDTH = 30
TILEHEIGHT = 30
TILEFLOORHEIGHT = 30
IMAGESDICT = {"WALL": pygame.image.load("C:/Users/Trail/Documents/College 2/Object Oriented Programming/Sokoban Implement/images/wall.bmp"),
"FLOOR": pygame.image.load(""C:/Users/Trail/Documents/College 2/Object Oriented Programming/Sokoban Implement/images/floor.bmp"),
"CRATE": pygame.image.load(""C:/Users/Trail/Documents/College 2/Object Oriented Programming/Sokoban Implement/images/object.bmp"),
"TARGET": pygame.image.load("C:/Users/Trail/Documents/College 2/Object Oriented Programming/Sokoban Implement/images/wall.bmp"object_store),
"PLAYER": pygame.image.load("C:/Users/Trail/Documents/College 2/Object Oriented Programming/Sokoban Implement/images/mover_left.bmp")}
TILEMAPPING = {"#":IMAGESDICT["WALL"],
" ":IMAGESDICT["FLOOR"],
"$":IMAGESDICT["CRATE"],
"#":IMAGESDICT["TARGET"],
"P":IMAGESDICT["PLAYER"]}
#Display surface
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAY = pygame.display.set_mode((WINWIDTH,WINHEIGHT))
pygame.display.set_caption("Sokoban")
def Build(maze):
maze.walls(10)
maze.targets(5)
maze.startPos()
mapSurfWidth = maze.getWidth() * TILEWIDTH
mapSurfHeight = maze.getHeight() * TILEHEIGHT
mapSurf = pygame.Surface((mapSurfWidth,mapSurfHeight))
mapSurf.fill(WHITE)
for h in range(maze.getHeight()):
for w in range(maze.getWidth()):
tile = pygame.Rect((w * TILEWIDTH, h * TILEFLOORHEIGHT, TILEWIDTH, TILEHEIGHT))
if maze.getPos(h,w) in TILEMAPPING:
baseTile = TILEMAPPING[maze.getPos(h,w)]
#Draw
mapSurf.blit(baseTile,tile)
return mapSurf
def main():
Build(maze)
main()
And my Maze class (This is indented in my code but not here for formatting):
class Maze:
def __init__(self):
self.width = 20
self.height = 10
#init
width = 20
height = 10
#Create 2D array for maze
self.maze = [[0 for i in range(width)] for j in range(height)]
#Create square grid
for i in range(width):
for j in range(height):
if j == 0 or j == height - 1:
self.maze[j][i] = "#"
elif i == 0 or i == width - 1:
self.maze[j][i] = "#"
else:
self.maze[j][i] = " "
def crates(self,level):
self.level = level
for i in range(0,level):
#Don't spawn here if wall is already generated
if self.maze[i+2][i+5] == "#":
self.maze[i+3][i+6] = "$"
else:
self.maze[i+2][i+5] = "$"
return self.maze
def walls(self,level):
self.level = level
#Semi working, needs randomised for play
for i in range(0,level):
for j in range(0,level):
#Shitty random gen
y = level / 2
x = randint(0,level)
y = randint(0,y)
#Shitty test random wall gen
if x % 3 == 0:
self.maze[y][x] = "#"
"""if (j % 3 == 0) and (i < 4):
self.maze[j][i] = "#"
elif (j % 2 == 0) and (i > 8):
self.maze[i][j] = "#"""
return self.maze
def targets(self,level):
self.level = level
#Test
for i in range(0,level):
self.maze[i+2][i+10] = "#"
return self.maze
def startPos(self):
x = randint(1,5)
y = randint(1,5)
self.maze[x][y] = "P"
return self.maze
def getWidth(self):
return self.width
def getHeight(self):
return self.height
def getPos(self,row,col):
return self.maze[row][col]

Categories