Advertisement
Guest User

Untitled

a guest
May 24th, 2019
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 15.47 KB | None | 0 0
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Wed Nov 21 18:53:53 2018
  4.  
  5. @author: Eric
  6. """
  7.  
  8. import tkinter as tk
  9. import random
  10.  
  11. class Grid:
  12.     def __init__(self, n):
  13.         self.size = n
  14.         self.cells = self.generate_empty_grid()
  15.         """設定標誌,用來判斷是否壓縮、合併、移動"""
  16.         self.compressed = False
  17.         self.merged = False
  18.         self.moved = False
  19.    
  20.     """生成空的棋盤"""
  21.     def generate_empty_grid(self):
  22.         #建立一個儲存整個二維串列
  23.         emptyGrid = []
  24.         """用二維巢狀迴圈建立二維串列"""
  25.         for i in range():
  26.             #建立一個儲存"列"的串列
  27.             rowGrid = []
  28.             for j in range():
  29.                 rowGrid.append()
  30.                
  31.             emptyGrid.append()
  32.                
  33.         return
  34.    
  35.     """取得所有空的格子"""
  36.     def retrieve_empty_cells(self):
  37.         #建立一個儲存所有空格子的串列
  38.         empty_cells = []
  39.         """用二維朝狀迴圈掃過網格"""
  40.         for i in range(self.size):
  41.             for j in range(self.size):
  42.                 """如果該格子等於0,則在empty_cells新增"""
  43.                 if self.cells[i][j] == :
  44.                     empty_cells.append((i, j))
  45.                    
  46.         return
  47.    
  48.     """隨機選一個空的棋格生成數字2"""
  49.     def random_cell(self):
  50.         cell = random.choice()
  51.         """把取到的元祖資料分別存入i和j"""
  52.         i =
  53.         j =
  54.         self.cells[i][j] = 2
  55.        
  56.     """直接設定格子"""
  57.     def set_cells(self, col , row , num):
  58.         """直接設定格子的數值"""
  59.        
  60.     """清除標誌"""
  61.     def clear_flags(self):
  62.         self.compressed = False
  63.         self.merged = False
  64.         self.moved = False
  65.        
  66.     """向左壓縮"""
  67.     def left_compress(self):
  68.         self.compressed = False
  69.         """重新生成一個空的二為串列網格,儲存至new_grid"""
  70.         new_grid = self.generate_empty_grid()
  71.        
  72.         """用二維網格掃過網格"""
  73.         for i in range(self.size):
  74.             count = 0
  75.             for j in range(self.size):
  76.                 """如果該格子的值不等於0,則進行壓縮"""
  77.                 if self.cells[i][j] != 0:
  78.                     new_grid[i][count] = self.cells[i][j]
  79.                     """如果count不等於j,則表示有進行過壓縮"""
  80.                     if count != j:
  81.                         self.compressed = True
  82.                     """若成功進行壓縮,count值加一"""
  83.                     count += 1
  84.         """全部壓縮完後,將舊的網格取代成新的網格"""
  85.         self.cells = new_grid
  86.    
  87.     """向上壓縮"""
  88.     def up_compress(self):
  89.         self.compressed = False
  90.         """重新生成一個空的二為串列網格,儲存至new_grid"""
  91.         new_grid =
  92.        
  93.         """用二維網格掃過網格"""
  94.         for i in range():
  95.             count = 0
  96.             for j in range():
  97.                 """如果該格子的值不等於0,則進行壓縮"""
  98.                 if :
  99.                     new_grid[count][i] =
  100.                     """如果count不等於j,則表示有進行過壓縮"""
  101.                     if :
  102.                         self.compressed =
  103.                     """若成功進行壓縮,count值加一"""
  104.                     count
  105.         """全部壓縮完後,將舊的網格取代成新的網格"""
  106.         self.cells =
  107.  
  108.     """向右壓縮"""
  109.     def right_compress(self):
  110.         self.compressed = False
  111.         """重新生成一個空的二為串列網格,儲存至new_grid"""
  112.         new_grid =
  113.        
  114.         """用二維網格掃過網格"""
  115.         for i in range():
  116.             count = self.size -1
  117.             for j in range(self.size -1,-1,-1):
  118.                 """如果該格子的值不等於0,則進行壓縮"""
  119.                 if :
  120.                     new_grid[i][count] =
  121.                     """如果count不等於j,則表示有進行過壓縮"""
  122.                     if :
  123.                         self.compressed =
  124.                     """若成功進行壓縮,count值減一"""
  125.                     count
  126.         """全部壓縮完後,將舊的網格取代成新的網格"""
  127.         self.cells =
  128.        
  129.     """向下壓縮"""
  130.     def down_compress(self):
  131.         self.compressed = False
  132.         """重新生成一個空的二為串列網格,儲存至new_grid"""
  133.         new_grid =
  134.        
  135.         """用二維網格掃過網格"""
  136.         for i in range():
  137.             count =
  138.             for j in range():
  139.                 """如果該格子的值不等於0,則進行壓縮"""
  140.                 if :
  141.                     new_grid[][] = self.cells[][]
  142.                     """如果count不等於j,則表示有進行過壓縮"""
  143.                     if :
  144.                         self.compressed =
  145.                     """若成功進行壓縮,count值減一"""
  146.                     count
  147.         """全部壓縮完後,將舊的網格取代成新的網格"""
  148.         self.cells =
  149.  
  150.     """向左合併"""
  151.     def left_merge(self):
  152.         self.merged = False
  153.         """用二維網格掃過網格(須注意range範圍及串列索引值)"""
  154.         for i in range(self.size):
  155.             """由於cells[i][j+1]會超出索引值,因而此處range放size-1"""
  156.             for j in range(self.size - 1):
  157.                
  158.                 """如果數字相同,且不為0則合併"""
  159.                 if self.cells[i][j] == self.cells[i][j + 1] \
  160.                 and  self.cells[i][j] != 0:
  161.                     """左方數字*2,右方數值等於0"""
  162.                     self.cells[i][j] *= 2
  163.                     self.cells[i][j + 1] = 0
  164.                     self.merged = True
  165.                    
  166.    
  167.     """向上合併"""            
  168.     def up_merge(self):
  169.         self.merged = False
  170.         """用二維網格掃過網格(須注意range範圍及串列索引值)"""
  171.         for i in range():
  172.             for j in range():
  173.                
  174.                 """如果數字相同,且不為0則合併"""
  175.                 if :
  176.                     """上方數字*2,下方數值等於0"""
  177.                     self.cells[j][i]
  178.                     self.cells[j+1][i]
  179.                     self.merged = True
  180.                    
  181.     """向右合併"""              
  182.     def right_merge(self):
  183.         self.merged = False
  184.         """用二維網格掃過網格(須注意range範圍及串列索引值)"""
  185.         for i in range():
  186.             for j in range():
  187.                
  188.                 """如果數字相同,且不為0則合併"""
  189.                 if :
  190.                     """右方數字*2,左方數值等於0"""
  191.                     self.cells[i][j]
  192.                     self.cells[i][j - 1]
  193.                     self.merged = True
  194.                    
  195.     """向下合併"""            
  196.     def down_merge(self):
  197.         self.merged = False
  198.         """用二維網格掃過網格(須注意range範圍及串列索引值)"""
  199.         for i in range():
  200.             for j in range():
  201.                
  202.                 """如果數字相同,且不為0則合併"""
  203.                 if :
  204.                     """下方數字*2,上方數值等於0"""
  205.                     self.cells[][]
  206.                     self.cells[][] =
  207.                     self.merged = True
  208.                    
  209.         """找到2048這個數字"""
  210.     def found_2048(self):
  211.         """用二維網格掃過網格,如果有任一格數值等於2048回傳True,否則為False"""
  212.        
  213.  
  214.     """有沒有空的格子"""
  215.     def has_empty_cells(self):
  216.         """用二維網格掃過網格,如果有任一格數值為0回傳True,否則為False"""
  217.        
  218.  
  219.     """是否可以合併"""
  220.     def can_merge(self):
  221.         """用二維網格掃過網格"""
  222.         for i in range():
  223.             for j in range():
  224.                 """判斷水平方向是否有相鄰且相同的兩個數字,若有回傳True"""
  225.                 if :
  226.                     return True
  227.         """用二維網格掃過網格"""
  228.         for j in range():
  229.             for i in range():
  230.                 """判斷垂直方向是否有相鄰且相同的兩個數字,若有回傳True"""
  231.                 if :
  232.                     return True
  233.         """如果都找不到則回傳False"""
  234.         return False
  235.    
  236.  
  237. class GamePanel():
  238.    
  239.     """整體背景顏色"""
  240.     BACKGROUND_COLOR = '#92877d'
  241.    
  242.     """空格子顏色"""
  243.     EMPTY_CELL_COLOR = '#9e948a'
  244.    
  245.     """數字背景顏色"""
  246.     CELL_BACKGROUND_COLOR_DICT = {
  247.         '2': '#eee4da',
  248.         '4': '#ede0c8',
  249.         '8': '#f2b179',
  250.         '16': '#f59563',
  251.         '32': '#f67c5f',
  252.         '64': '#f65e3b',
  253.         '128': '#edcf72',
  254.         '256': '#edcc61',
  255.         '512': '#edc850',
  256.         '1024': '#edc53f',
  257.         '2048': '#edc22e',
  258.         'default': '3c3a32'
  259.     }
  260.    
  261.     """數字字體顏色 """
  262.     CELL_COLOR_DICT = {
  263.         '2': '#776e65',
  264.         '4': '#776e65',
  265.         '8': '#f9f6f2',
  266.         '16': '#f9f6f2',
  267.         '32': '#f9f6f2',
  268.         '64': '#f9f6f2',
  269.         '128': '#f9f6f2',
  270.         '256': '#f9f6f2',
  271.         '512': '#f9f6f2',
  272.         '1024': '#f9f6f2',
  273.         '2048': '#f9f6f2',
  274.         'default': '#f9f6f2'
  275.     }
  276.    
  277.     FONT = ('Verdana', 24, 'bold')
  278.     UP_KEYS = ('w', 'W', 'Up')
  279.     LEFT_KEYS = ('a', 'A', 'Left')
  280.     DOWN_KEYS = ('s', 'S', 'Down')
  281.     RIGHT_KEYS = ('d', 'D', 'Right')
  282.  
  283.     def __init__(self , grid):
  284.         """將grid放入類別屬性內"""
  285.         self.grid = grid
  286.         self.size = grid.size
  287.         """建立一個tkinter主視窗"""
  288.         self.window = tk.Tk()
  289.         """設定視窗標題"""
  290.         self.window.title('2048')
  291.         """設定遊戲背景"""
  292.         self.background = tk.Frame(self.window, bg=self.BACKGROUND_COLOR)
  293.         """建立空串列,用來儲存格子Label"""
  294.         self.cell_labels = []
  295.        
  296.         """初始化文字"""
  297.         """用二維巢狀迴圈建立二維串列"""
  298.         for i in range(self.size):
  299.             #建立一個儲存"列"的串列
  300.             row_labels = []
  301.             for j in range(self.size):
  302.                 """背景顏色為EMPTY_CELL_COLOR"""
  303.                 """font為剛剛設置的FONT"""
  304.                 label = tk.Label(self.background, text='',
  305.                                  bg=self.EMPTY_CELL_COLOR,
  306.                                  font=self.FONT,
  307.                                  width=4, height=2)
  308.                 """設定label位置"""
  309.                 label.grid(row=i, column=j, padx=10, pady=10)
  310.                 """將新增好的Label放入row_labels內"""
  311.                 row_labels.append(label)
  312.                 """將新增好的row_labels放入cell_labels內"""
  313.             self.cell_labels.append(row_labels)
  314.         self.background.grid()
  315.  
  316.     """把格子和字上色"""
  317.     def paint(self):
  318.         """用兩個迴圈掃過網格"""
  319.         for i in range(self.size):
  320.             for j in range(self.size):
  321.                
  322.                  #如果那個格子數字是0
  323.                 if self.grid.cells[i][j] == 0:
  324.                     """設定該格子的文字為空,背景為MPTY_CELL_COLOR"""
  325.                     self.cell_labels[i][j].configure(
  326.                          text='',
  327.                          bg=GamePanel.EMPTY_CELL_COLOR)
  328.                    
  329.                 #如果不是0,則依照字典顏色上色
  330.                 #bg->background(背景)
  331.                 #fg->foreground(前景)
  332.                 else:
  333.                     """cell_text為該格子的數值,轉為字串型態"""
  334.                     cell_text = str(self.grid.cells[i][j])
  335.                     """如果數字超過2048"""
  336.                     if self.grid.cells[i][j] > 2048:
  337.                         """color等於預設值"""
  338.                         bg_color = GamePanel.CELL_BACKGROUND_COLOR_DICT.get('beyond')
  339.                         fg_color = GamePanel.CELL_COLOR_DICT.get('beyond')
  340.                         """如果數字沒超過2048"""
  341.                     else:
  342.                         """color由字典取值"""
  343.                         bg_color = GamePanel.CELL_BACKGROUND_COLOR_DICT.get(cell_text)
  344.                         fg_color = GamePanel.CELL_COLOR_DICT.get(cell_text)
  345.                        
  346.                     self.cell_labels[i][j].configure(
  347.                         text=cell_text,
  348.                         bg=bg_color, fg=fg_color)
  349.                    
  350.            
  351. """控制整個遊戲流程"""
  352. class Game:
  353.     def __init__(self, grid, panel):
  354.         self.grid = grid
  355.         self.panel = panel
  356.         self.start_cells_num = 2
  357.         self.over = False
  358.         self.won = False
  359.  
  360.     """遊戲停止(輸了或贏了)"""
  361.     def is_game_terminated(self):
  362.         return self.over or self.won
  363.  
  364.     """遊戲開始"""
  365.     def start(self):
  366.         self.add_start_cells()
  367.         self.panel.paint()
  368.         self.panel.window.bind('<Key>', self.key_handler)
  369.         self.panel.window.mainloop()
  370.  
  371.     """開始遊戲後產生的格子"""
  372.     def add_start_cells(self):
  373.         for i in range(self.start_cells_num):
  374.             self.grid.random_cell()
  375.  
  376.     """判斷有沒有辦法移動(合併)"""
  377.     def can_move(self):
  378.         return self.grid.has_empty_cells() or self.grid.can_merge()
  379.  
  380.     """當按下鍵盤時所要做的事情"""
  381.     def key_handler(self, event):
  382.         if self.is_game_terminated():
  383.             return
  384.  
  385.         self.grid.clear_flags()
  386.         key_value = event.keysym
  387.        
  388.         #print('{} key pressed'.format(key_value))
  389.        
  390.         #判斷按下的按鍵是哪個功能
  391.         if key_value in GamePanel.UP_KEYS:
  392.             self.up()
  393.         elif key_value in GamePanel.LEFT_KEYS:
  394.             self.left()
  395.         elif key_value in GamePanel.DOWN_KEYS:
  396.             self.down()
  397.         elif key_value in GamePanel.RIGHT_KEYS:
  398.             self.right()
  399.         else:
  400.             pass
  401.  
  402.         self.panel.paint()
  403.        
  404.         """如果找到2048"""
  405.         if self.grid.found_2048():
  406.             self.you_win()
  407.        
  408.         """如果已經移動完了,則產生一個隨機數字"""
  409.         if self.grid.moved:
  410.             self.grid.random_cell()
  411.  
  412.  
  413.         self.panel.paint()
  414.        
  415.         """如果無法再移動"""
  416.         if not self.can_move():
  417.             self.over = True
  418.             self.game_over()
  419.  
  420.     """遊戲勝利"""
  421.     def you_win(self):
  422.         if not self.won:
  423.             self.won = True
  424.             print('You Win!')
  425.  
  426.     """遊戲失敗"""
  427.     def game_over(self):
  428.         print('Game over!')
  429.  
  430.     def up(self):
  431.         self.grid.up_compress()
  432.         self.grid.up_merge()
  433.         self.grid.moved = self.grid.compressed or self.grid.merged
  434.         self.grid.up_compress()
  435.  
  436.     def left(self):
  437.         self.grid.left_compress()
  438.         self.grid.left_merge()
  439.         self.grid.moved = self.grid.compressed or self.grid.merged
  440.         self.grid.left_compress()
  441.  
  442.     def down(self):
  443.         self.grid.down_compress()
  444.         self.grid.down_merge()
  445.         self.grid.moved = self.grid.compressed or self.grid.merged
  446.         self.grid.down_compress()
  447.  
  448.     def right(self):
  449.         self.grid.right_compress()
  450.         self.grid.right_merge()
  451.         self.grid.moved = self.grid.compressed or self.grid.merged
  452.         self.grid.right_compress()
  453.  
  454. size = 4
  455. grid = Grid(size)
  456. panel = GamePanel(grid)
  457. game2048 = Game(grid, panel)
  458. game2048.start()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement