📜 ⬆️ ⬇️

Creation of a sapper with the Tkinter module

Good afternoon. Almost every novice programmer seeks to create his first game. After half a year of lazy, painstaking training, I decided to write a sapper. The writing language was chosen by Python, the module for adding the tkinter interface, because I already had experience with it. This post will be useful sooner for novice coders, but if you already know everything, you can write your own tips for improving the code in the comments.

Let's get started The first thing to do was decide what the cell would be like. The most profitable solution is to create a field class:

class pole(object): #  ,   Object def __init__(self,master,row, column): # . master -  Tk(). self.button = Button(master, text = ' ') #     'button' self.mine = False #     self.value = 0 #-   self.viewed = False #/  self.flag = 0 #0 -  , 1 -  , 2 -  "?" self.around = [] #,     self.clr = 'black' #  self.bg = None #  self.row = row # self.column = column # 

Now you need to create an interface to customize the game:

 settings = Tk() #  settings.title('') #   settings.geometry('200x150') #  mineText = Text(settings, width = 5, height = 1) #       mineLabe = Label(settings, height = 1, text = ':') highText = Text(settings, width = 5, height = 1) highLabe = Label(settings, height = 1, text = ':') lenghtText = Text(settings, width = 5, height = 1) lenghtLabe = Label(settings, height = 1, text = ':') mineBut = Button(settings, text = ':', command = bombcounter) #  mineBut.place(x = 70, y = 90) #   mineText.place(x = 75, y = 5) mineLabe.place(x = 5, y = 5) highText.place(x = 75, y = 30) highLabe.place(x = 5, y = 30) lenghtText.place(x = 75, y = 55) lenghtLabe.place(x = 5, y = 55) settings.mainloop() 

As a result, we get this window:
')
image

Now you need to register the function bombcounter

 def bombcounter(): global bombs if mineText.get('1.0', END) == '\n': #   bombs = 10 #  ,    -  - 10 else: bombs = int(mineText.get('1.0', END)) #  ,     -  if highText.get('1.0', END) == '\n': high = 9 else: high = int(highText.get('1.0', END)) if lenghtText.get('1.0', END) == '\n': lenght = 9 else: lenght = int(lenghtText.get('1.0', END)) game(high,lenght) # ,  -  

Now we proceed to the main part, writing the function of the game:

 def game(high,lenght): #  root = Tk() root.title('') global buttons global mines global flags flags = [] #,    ,    mines = [] #,    ,    buttons = [[pole(root,j,i) for i in range(high)] for j in range(lenght)] # ,     for i in range(len(buttons)): #   for j in range(len(buttons[i])): #    buttons[i][j].button.grid(column = j, row = i, ipadx = 7, ipady = 1) #       grid buttons[i][j].button.bind('<Button-1>', buttons[i][j].view) #   buttons[i][j].button.bind('<Button-3>', buttons[i][j].setFlag) #  buttons[i][j].setAround() #   self.around buttons[0][0].button.bind('<Control-Button-1>', cheat) #      root.resizable(False,False) #   root.mainloop() 

We have three functions to write. Let's start with .setAround ():

  def setAround(self): if self.row == 0: self.around.append([self.row+1,self.column]) if self.column == 0: self.around.append([self.row,self.column+1]) self.around.append([self.row+1,self.column+1]) elif self.column == len(buttons[self.row])-1: self.around.append([self.row,self.column-1]) self.around.append([self.row+1,self.column-1]) else: self.around.append([self.row,self.column-1]) self.around.append([self.row,self.column+1]) self.around.append([self.row+1,self.column+1]) self.around.append([self.row+1,self.column-1]) elif self.row == len(buttons)-1: self.around.append([self.row-1,self.column]) if self.column == 0: self.around.append([self.row,self.column+1]) self.around.append([self.row-1,self.column+1]) elif self.column == len(buttons[self.row])-1: self.around.append([self.row,self.column-1]) self.around.append([self.row-1,self.column-1]) else: self.around.append([self.row,self.column-1]) self.around.append([self.row,self.column+1]) self.around.append([self.row-1,self.column+1]) self.around.append([self.row-1,self.column-1]) else: self.around.append([self.row-1,self.column]) self.around.append([self.row+1,self.column]) if self.column == 0: self.around.append([self.row,self.column+1]) self.around.append([self.row+1,self.column+1]) self.around.append([self.row-1,self.column+1]) elif self.column == len(buttons[self.row])-1: self.around.append([self.row,self.column-1]) self.around.append([self.row+1,self.column-1]) self.around.append([self.row-1,self.column-1]) else: self.around.append([self.row,self.column-1]) self.around.append([self.row,self.column+1]) self.around.append([self.row+1,self.column+1]) self.around.append([self.row+1,self.column-1]) self.around.append([self.row-1,self.column+1]) self.around.append([self.row-1,self.column-1]) 

All that is happening here is filling the self.around array. We consider various cases and at the output we get the right answer. If there are options how to make it easier, I will take them into account.

We write view ()

  def view(self,event): if mines == []: #   seter(0,self.around,self.row,self.column) #  if self.value == 0: # .     6,7  8,      self.clr = 'yellow' self.value = None self.bg = 'lightgrey' elif self.value == 1: self.clr = 'green' elif self.value == 2: self.clr = 'blue' elif self.value == 3: self.clr = 'red' elif self.value == 4: self.clr = 'purple' if self.mine and not self.viewed and not self.flag: #    ,          self.button.configure(text = 'B', bg = 'red') # ,     self.viewed = True #,    for q in mines: buttons[q[0]][q[1]].view('<Button-1>') #      lose() #   elif not self.viewed and not self.flag: #  ,        self.button.configure(text = self.value, fg = self.clr, bg = self.bg) #     self.viewed = True if self.value == None: #    for k in self.around: buttons[k[0]][k[1]].view('<Button-1>') #    

So. Now we have written functions: opening a cell, filling an array around, starting a game and getting a value about the size of the playing field and the number of min. But there is still no function to set min. Corrected:

 def seter(q, around,row,column): #        if q == bombs: # -   = -  for i in range(len(buttons)): #   for j in range(len(buttons[i])): #     i for k in buttons[i][j].viewAround(): #      j if buttons[k[0]][k[1]].viewMine(): #     k  buttons[i][j].setValue(buttons[i][j].viewValue()+1) #    j return a = choice(buttons) #   b = choice(a) #  if [buttons.index(a),a.index(b)] not in mines and [buttons.index(a),a.index(b)] not in around and [buttons.index(a),a.index(b)] != [row,column]: #,        ,         (   ) b.setMine() #  mines.append([buttons.index(a),a.index(b)]) #    seter(q+1,around,row,column) # , ,      else: seter(q,around,row,column) #    

And the second important function for us is: setValue ()

  def setValue(self,value): self.value = value 

This ends the main part. The game can work right now, but without checking the box and determining the victory / loss. It's simple. Checkbox setting:

  def setFlag(self,event): if self.flag == 0 and not self.viewed: #       self.flag = 1 #  self.button.configure(text = 'F', bg = 'yellow') #  flags.append([self.row,self.column]) #    elif self.flag == 1: #   self.flag = 2 #  '?' self.button.configure(text = '?', bg = 'blue') #  flags.pop(flags.index([self.row,self.column])) #     elif self.flag == 2: #  self.flag = 0 #    self.button.configure(text = ' ', bg = 'white') #  if sorted(mines) == sorted(flags) and mines != []: #      winer() #   

The lose () and winer () functions are simple and require no explanation. If need be, I will write in the comments.

Final View:

image

Write your questions, suggestions and criticism in the comments, I will try to answer, discuss and think.

Source: https://habr.com/ru/post/326358/


All Articles