python - 我用 tkinter 做了一个扫雷游戏
问题描述
我是一个完全的初学者,刚刚开始通过“Head First Learn to Code”一书开始学习编码。我刚刚读完这本书,并在我的 mac 上用 python3 编写了一个扫雷游戏。我希望得到一些关于我制作的游戏的建议。如果您觉得代码太长而无法阅读,这里有一些我想问的具体问题:
这是做什么的:flag = flag.resize((12, 12), Image.ANTIALIAS) 实际上是做什么的,为什么我需要为它分配一个变量而不是仅仅这样做: flag.resize((12, 12), Image.resize((12, 12), Image. ANTIALIAS)就像我对其他对象所做的那样
有没有更好的方法来制作秒表?我的是函数 update_time。
我对python的约定有什么错误吗?请为我指出一些。
任何帮助将非常感激!
这是我的代码:
from tkinter import *
import random as rd
from tkinter import messagebox
from PIL import ImageTk, Image
import sys
class GameGrid(Frame): #the game
def __init__(self, master, height, width, mines_count, player):
Frame.__init__(self, master)
self.grid(row=0)
self.master = master
if sys.platform == 'win32': #checking os
self.platform = 'windows'
else:
self.platform = 'macos'
self.height = height #storing height, width, mines_count, and player's name
self.width = width
self.mines_count = mines_count
self.player_name = player
self.play_time = 0 #initiating play_time and other values
self.lost = False
self.won = False
self.notmine = height * width - mines_count #calculate the number of tiles that are not mines
flag = Image.open('flag.png') #creating and storing flag and bomb images
flag = flag.resize((12, 12), Image.ANTIALIAS)
bomb = Image.open('bomb.png')
bomb = bomb.resize((12, 12), Image.ANTIALIAS)
self.flag = ImageTk.PhotoImage(flag)
self.bomb = ImageTk.PhotoImage(bomb)
grid_model = [[0]*width for item in [0]*height] #creating a list to hold 1's and 0's
while mines_count > 0: #1 is mine, 0 is normal
randi = rd.randint(0, height-1) #putting mines into the list by generating random coordinates
randj = rd.randint(0, width-1) #and storing mine in the corresponding place
if grid_model[randi][randj] == 0:
grid_model[randi][randj] = 1
mines_count -= 1
self.tiles = {} #creating Tiles and storing them using dictionary
for i in range(height):
for j in range(width):
if grid_model[i][j] == 1:
self.tiles[i, j] = Tile(self, i, j, True)
else:
mine_neighbors = 0 #counting nearby mines if Tile in creation is not a mine
if i - 1 >= 0:
if grid_model[i-1][j] == 1:
mine_neighbors += 1
if i - 1 >= 0 and j - 1 >= 0:
if grid_model[i-1][j-1] == 1:
mine_neighbors += 1
if i - 1 >= 0 and j + 1 < width:
if grid_model[i-1][j+1] == 1:
mine_neighbors += 1
if j - 1 >= 0:
if grid_model[i][j-1] == 1:
mine_neighbors += 1
if j + 1 < width:
if grid_model[i][j+1] == 1:
mine_neighbors += 1
if i + 1 < height:
if grid_model[i+1][j] == 1:
mine_neighbors += 1
if i + 1 < height and j - 1 >= 0:
if grid_model[i+1][j-1] == 1:
mine_neighbors += 1
if i + 1 < height and j + 1 < width:
if grid_model[i+1][j+1] == 1:
mine_neighbors += 1
self.tiles[i, j] = Tile(self, i, j, False, mine_neighbors)
def reveal_surroundings(self, i, j): #reveal nearby tiles
revealing = []
width = self.width
height = self.height
if i - 1 >= 0:
revealing.append(self.tiles[i-1, j])
if i - 1 >= 0 and j - 1 >= 0:
revealing.append(self.tiles[i-1, j-1])
if i - 1 >= 0 and j + 1 < width:
revealing.append(self.tiles[i-1, j+1])
if j - 1 >= 0:
revealing.append(self.tiles[i, j-1])
if j + 1 < width:
revealing.append(self.tiles[i, j+1])
if i + 1 < height:
revealing.append(self.tiles[i+1, j])
if i + 1 < height and j - 1 >= 0:
revealing.append(self.tiles[i+1, j-1])
if i + 1 < height and j + 1 < width:
revealing.append(self.tiles[i+1, j+1])
for tile in revealing:
tile.reveal()
def lose(self): #show if lost, stop the clock
global stp
stp = True
self.lost = True
if self.platform == 'windows':
for tile in self.tiles:
if self.tiles[tile].mine:
self.tiles[tile].config(bg='red')
else:
for tile in self.tiles:
if self.tiles[tile].mine:
self.tiles[tile].config(image=self.bomb, padx=9, pady=4, bg='red')
self.tiles[tile].unbind('<Button-1>')
self.tiles[tile].unbind('<Button-2>')
messagebox.showerror(message='Boom, Game Over!!')
self.score = ScoreBoard(self.master)
def win(self): #show if won, stop the clock, creating a window recording scores
global mn, sc, stp
stp = True
self.won = True
for tile in self.tiles:
if self.tiles[tile].mine:
self.tiles[tile].config(image=self.bomb, padx=9, pady=4, bg='red')
self.tiles[tile].unbind('<Button-1>')
self.tiles[tile].unbind('<Button-2>')
messagebox.showinfo(message='Congrats, You Survived ;)')
play_time = str(m) + ' mins, ' + str(s) + ' secs'
self.score = ScoreBoard(self.master, self.player_name, play_time)
class ScoreBoard(Toplevel): #for score recording
def __init__(self, master, name=None, time=None):
Toplevel.__init__(self, master)
self.title('Hall of Fame')
fin_text = ''
if name != None: #writing in the record if there is one
self.board = open('ScoreBoard.txt', 'r') #assigning the text inside ScoreBoard.txt to board_text
board_text = '' #and writing it into ScoreBoard.txt
for line in self.board:
board_text = board_text + line
self.board = open('ScoreBoard.txt', 'w')
self.record = name + ' ' + time
self.board.write(board_text + '\n' + self.record)
self.board = open('ScoreBoard.txt', 'r') #reading text in ScoreBoard and put it on the window
for line in self.board:
fin_text = fin_text + line
self.lbl = Label(self, text=fin_text)
self.lbl.pack()
self.geometry('300x300')
self.board.close()
class Tile(Label): #the Tile
def __init__(self, master, i, j, mine, mine_neighbors=None):
Label.__init__(self, master, width=2, relief=RAISED)
self.grid(row=i, column=j)
self.game = master #storing row, column, is mine or not, count of nearby mines
self.mine = mine
self.row = i
self.col = j
self.mine_neighbors = mine_neighbors
self.revealed = False
self.marked = False
self.bind('<Button-1>', self.reveal) #bind Tile: reveal(left click), mark(right click)
self.bind('<Button-2>', self.mark)
def reveal(self, event=None): #revealing tile
if self.mine:
self.game.lose()
return
else:
if not self.revealed:
self.revealed = True
self.mark()
self.unbind('<Button-1>')
self.unbind('<Button-2>')
if self.mine_neighbors == 0: #if no nearby mines, reveal nearby tiles
self.config(text='', relief=SUNKEN, bg='lightgrey', image='', padx=1, pady=1)
self.game.reveal_surroundings(self.row, self.col)
else:
self.config(text=self.mine_neighbors, relief=SUNKEN, bg='lightgrey', image='', padx=1, pady=1)
self.game.notmine -= 1
if self.game.notmine == 0:
self.game.win()
def mark(self,event=None): #marking tile
if self.game.platform == 'windows':
if not self.marked:
self.config(text='*')
self.marked = True
else:
self.config(text='')
self.marked = False
else:
if not self.marked:
self.config(image=self.game.flag, padx=9, pady=4)
self.marked = True
else:
self.config(image='', padx=1, pady=1)
self.marked = False
stp = False #used to stop the clock when lost or won
def update_time(): #a stopwatch
global m, s, timer, stp
if stp != True:
s = s + 1
if s == 60:
m = m + 1
s = 0
mn = str(m) #making the clock look better by adding a 0 when the number
sc = str(s) #of second or minute is just one digit, e.g. 01, 06, 09..
if len(sc) == 1 and len(mn) == 1:
sc = '0' + sc
mn = '0' + mn
timer.config(text=mn+':'+sc)
elif len(mn) == 1 and len(sc) != 1:
mn = '0' + str(m)
timer.config(text=mn+':'+str(s))
elif len(sc) == 1 and len(mn) != 1:
sc = '0' + sc
timer.config(text=mn+':'+sc)
timer.after(1000, update_time)
def play(height, width, mines_count, player): #initiating the game
global s, m, timer
m = 0
s = -1
time = str(m) + ':' + str(s)
root = Tk()
root.title('MineSweeper')
root.resizable(False, False)
timer = Label(root, text='%i:%i'%(m,s)) #creating stopwatch and update it every second
timer.grid(row=1)
update_time()
game = GameGrid(root, height, width, mines_count, player)
root.mainloop()
if __name__ == '__main__':
play(10, 10, 10, 'Harley')
解决方案
推荐阅读
- google-cloud-dataflow - 来自工作人员的错误消息:generic::aborted: SDK 线束 sdk-0-1 已断开连接
- node.js - 节点获取 API 请求
- c# - 使用 DataContractJsonSerializer 转换为对象时,Serilog JSon 抛出异常
- ios - 有没有办法在 `UIApplication` 或 `UIWindow` 级别检测 VoiceOver 焦点更改/用户交互?
- windows-server-2019 - Server 2019 v1809 StandardEvaluation 无法使用 KMS 客户端设置密钥升级到标准
- google-chrome - Google Apps 脚本我想将组织中的所有用户添加到组
- datatables - 具有多个查询的数据表服务器端处理
- javascript - 如何将数据放入 ayncStorage?
- java - 在 tomcat 8 中,如何在 setenv.bat 中提供文件路径以从 java 类中读取
- sql-server - 跟踪数据库中的更改(更新、插入)