Trò chơi Minesweeper được viết bằng Python sử dụng thư viện Tkinter GUI
nội dung
- /tàu quét mìn. py - Chương trình python thực tế
- /images/ - Ảnh GIF đã sẵn sàng để sử dụng với Tkinter
- /images/ original - Hình ảnh PNG gốc được tạo bằng GraphicsGale
Làm
- Có số lượng mỏ cụ thể, thay vì ngẫu nhiên
- bảng điểm cao
- Lưới có thể điều chỉnh và số lượng mỏ qua giao diện người dùng
Tôi hoàn toàn là người mới bắt đầu học viết mã với cuốn sách "Head First Learn to Code". Tôi vừa hoàn thành cuốn sách và viết mã trò chơi quét mìn bằng python3 trên máy Mac của mình. Tôi hy vọng sẽ nhận được một số lời khuyên về trò chơi tôi đã thực hiện. Nếu bạn cảm thấy mã quá dài để đọc, đây là một số câu hỏi cụ thể mà tôi muốn hỏi
cái này làm gì. cờ = lá cờ. thay đổi kích thước [[12, 12], Hình ảnh. ANTIALIAS] thực sự làm được, tại sao tôi cần gán cho nó một biến thay vì chỉ làm điều này. lá cờ. thay đổi kích thước [[12, 12], Hình ảnh. ANTIALIAS] như tôi làm với các đối tượng khác
Có cách nào tốt hơn để tạo đồng hồ bấm giờ không?
Tôi có phạm sai lầm nào về các quy ước của python không?
Mọi trợ giúp sẽ được đánh giá cao.
Đây là mã của tôi.
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['']
self.tiles[tile].unbind['']
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['']
self.tiles[tile].unbind['']
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['', self.reveal] #bind Tile: reveal[left click], mark[right click]
self.bind['', 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['']
self.unbind['']
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']