2013-07-02 238 views
1

我試圖創建一個python遊戲,玩家將點擊棋盤填充它的顏色直到它完成,贏得誰擁有更多的填充框。 如果你點擊一個盒子,任何相鄰的盒子都裝滿了其他玩家的顏色,它會改變你的顏色,我發現這個板子代碼,但我不能讓它填充相鄰的盒子。與tkinter Python的棋盤遊戲

import Tkinter as tk 

board = [ [None]*10 for _ in range(10) ] 

counter = 0 

root = tk.Tk() 

def on_click(i,j,event): 
    global counter 
    color = "green" if counter%2 else "red" 
    event.widget.config(bg=color) 
    board[i][j] = color 
    counter += 1 


for i,row in enumerate(board): 
    for j,column in enumerate(row): 
     L = tk.Label(root,text=' ',bg='grey') 
     L.grid(row=i,column=j,padx='3',pady='3') 
     L.bind('<Button-1>',lambda e i=i,j=j: on_click(i,j,e)) 

root.mainloop() 

問題:我怎樣才能使它所以當玩家點擊一個箱子相鄰的箱子,都已經充滿了敵人的顏色也變爲紅色/綠色的嗎?另外我怎樣才能計算具有某種顏色的填充框的數量,以確定誰贏了?謝謝你的幫助。

回答

1

這花了一段時間!這裏是我的版本:

import Tkinter as tk 
import TkMessageBox as messagebox 

board = [ [None]*10 for _ in range(10) ] 

counter = 0 
root = tk.Tk() 

def check_board(): 
    freespaces = 0 
    redspaces = 0 
    greenspaces = 0 
    for i,row in enumerate(board): 
     for j,column in enumerate(row): 
      if board[i][j] == "red": 
       redspaces += 1 
      elif board[i][j] == "green": 
       greenspaces += 1 
      elif board[i][j] == None: 
       freespaces += 1 

    if freespaces == 0: 
     if greenspaces > redspaces: 
      winner = "green" 
     elif greenspaces < redspaces: 
      winner = "red" 
     else: 
      winner = "draw" 

     if winner != "draw": 
      messagebox.showinfo("Game Over!",winner+" wins!") 
     else: 
      messagebox.showinfo("Game Over!","The game was a draw!") 




def on_click(i,j,event): 
    global counter 
    if counter < 100: 
     if board[i][j] == None: 
      color = "green" if counter%2 else "red" 
      enemycolor = "red" if counter%2 else "green" 
      event.widget.config(bg=color) 
      board[i][j] = color 
      for k in range(-1,2): 
       for l in range(-1,2): 
        try: 
         if board[i+k][j+l] == enemycolor: 
          board[i+k][j+l] = color 
        except IndexError: 
         pass 
      counter += 1 
      global gameframe 
      gameframe.destroy() 
      redraw() 
      root.wm_title(enemycolor+"'s turn") 
     else: 
      messagebox.showinfo("Alert","This square is already occupied!") 
     check_board() 


def redraw(): 
    global gameframe 
    gameframe = tk.Frame(root) 
    gameframe.pack() 

    for i,row in enumerate(board): 

     for j,column in enumerate(row): 
      name = str(i)+str(j) 
      L = tk.Label(gameframe,text=' ',bg= "grey" if board[i][j] == None else board[i][j]) 
      L.grid(row=i,column=j,padx='3',pady='3') 
      L.bind('<Button-1>',lambda e,i=i,j=j:on_click(i,j,e)) 


redraw() 
root.mainloop() 

我重繪每次整板,因爲沒有存儲的參考部件。我無法在創建完成後訪問每個窗口小部件,因爲它們都被稱爲「L」,所以我檢查了電路板上的顏色值,並根據是否着色創建了窗口小部件。通過查看廣場周圍的3x3網格中的顏色進行檢查。

我添加了一個函數來檢查正方形,然後檢測它們是否全部滿了,如果有任何問題讓我知道,您應該可以通過研究代碼來計算出發生了什麼。我添加的一個很好的觸摸是根據輪到誰來改變標題欄!

編輯:要添加通知當前播放器顏色的標籤,請將以下內容添加到重繪功能的末尾!

global counter 
whosturn = "Green" if counter%2 else "Red" 
turnLbl = tk.Label(gameframe,text=color+"'s Turn") 
turnLbl.grid(row=11,column = 0,columnspan = 10) 
+0

感謝您的幫助!我有個問題。將可能發出的警告是什麼玩家把它作爲標籤而不是在窗口中作爲標籤在板上,或者它需要對板重新編碼並創建一個類?我混淆董事會的創建方式。 –

+0

是!更新的答案,將最後一部分添加到重繪功能。理想情況下,您應該從頭開始重新創建整個程序,並在課程中正確編碼以瞭解更多信息。使用self來傳遞變量會更好。和Tk變量而不是使用凌亂的全局變量。 – mbdavis

2

如果您存儲在board的標籤,那麼你就可以

board[i][j]['bg'] 

訪問它的背景顏色,你可以用

board[i][j].config(bg=...) 

甚至

board[i][j]['bg'] = ... 
改變背景顏色

既然你要訪問的board一個點的鄰居,很自然地使用for-loop S,從而爲:

for ii in range(i - 1, i + 2): 
    for jj in range(j - 1, j + 2): 

或等價但較少的嵌套使用itertools.product

import itertools as IT 
for ii, jj in IT.product(range(i - 1, i + 2), range(j - 1, j + 2)): 

現在您可以通過board[ii][jj]訪問鄰居,但請注意,iijj可能是超出界限的索引。

if ii<0 or ii>=rows or jj<0 or jj>=cols: continue 

把使用上述兩種思路, 您使用可以指望的紅色,綠色和灰色方塊的數量:我們可以通過使用if語句來處理出界外指標collections.Counter

import collections 
collections.Counter(
     board[i][j]['bg'] for i, j in IT.product(range(rows), range(cols))) 

import Tkinter as tk 
import itertools as IT 
import collections 

cols, rows = 3, 3 
board = [[None] * cols for _ in range(rows)]  
other = {'green': 'red', 'red': 'green'} 

player = 'red' 

def on_click(event, i, j): 
    global player 
    board[i][j]['bg'] = player 
    for ii, jj in IT.product(range(i - 1, i + 2), range(j - 1, j + 2)): 
     if ii<0 or ii>=rows or jj<0 or jj>=cols: continue 
     neighbor = board[ii][jj] 
     if neighbor['bg'] != 'grey' and (ii, jj) != (i, j): 
      neighbor['bg'] = other[neighbor['bg']] 
    check_for_winner() 
    player = other[player] 

def check_for_winner(): 
    s = score() 
    if s['red'] + s['green'] == cols*rows: 
     # every box filled 
     winner = max(s, key=s.get) 
     print('Winner is: {}'.format(winner)) 
     root.after(1, flash_winner, winner, 'blue') 

def score(): 
    return collections.Counter(
     board[i][j]['bg'] for i, j in IT.product(range(rows), range(cols))) 

def flash_winner(winner, altcolor): 
    for i, j in IT.product(range(rows), range(cols)): 
     if board[i][j]['bg'] == winner: 
      board[i][j]['bg'] = altcolor 
    root.after(250, flash_winner, altcolor, winner) 

root = tk.Tk() 
for i, j in IT.product(range(rows), range(cols)): 
    board[i][j] = L = tk.Label(root, text=' ', bg='grey') 
    L.grid(row=i, column=j, padx=3, pady=3) 
    L.bind('<Button-1>', lambda e, i=i, j=j: on_click(e, i, j)) 

root.mainloop() 
+0

非常感謝!現在我必須研究一些你以前瞭解的東西。 –