我试图创建一个蟒蛇游戏,玩家可以点击棋盘以填充它们的颜色直到它完成,赢得任何有更多填充框的人。 如果你点击一个框并且任何相邻的框用另一个玩家颜色填充,它会改变你的颜色,我发现这个板代码,但我不能让它填充相邻的框。
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()
问题:如果玩家点击一个方框,那么已经充满敌人颜色的相邻方框也会变成红色/绿色?另外,我如何计算具有特定颜色的填充盒数量来确定谁赢了?谢谢你的帮助。
答案 0 :(得分:2)
如果您将标签存储在board
中,则可以使用
board[i][j]['bg']
您可以使用
更改背景颜色board[i][j].config(bg=...)
甚至
board[i][j]['bg'] = ...
由于您想要访问board
上某个点的邻居,因此很自然地使用for-loop
,例如:
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]
访问邻居,请注意ii
或jj
可能是一个越界索引。我们可以使用if
语句来处理越界索引:
if ii<0 or ii>=rows or jj<0 or jj>=cols: continue
使用上面的两个想法, 您可以使用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()
答案 1 :(得分: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)