交互式游戏板与Tkinter Python - 标签更新

时间:2016-01-05 19:19:15

标签: python canvas tkinter visualization tkinter-canvas

我对Tkinter来说是全新的,如果我说错了,请道歉。我正在用Python实现游戏十五,我想用Tkinter制作视觉效果。请参见以下2x2板:

4 3
2 x

如果你提示x用3进行swop,那么这些标签应该更新。到目前为止,我初始化了一个画布,并有两个代码片段,一个用于设置电路板:

def visualize():
    for i,row in enumerate(board):
        for j,column in enumerate(row):
            L = Label(root,text='   %s   '%board[i][j],bg='pink')
            if board[i][j] == d*d:
                L = tk.Label(root,text='        ')

对于移动功能:

def move():
    tile = int(raw_input('Which tile would you like to move: '))
    global board, blankx, blanky
    for i in range(d):
        for j in range(d):
            if(board[i][j] == tile):
                if(i - 1 == blanky or i + 1 == blanky or j - 1 == blankx or j + 1 == blankx):
                    board[i][j] = d * d
                    board[blanky][blankx] = tile
                    blanky = i
                    blankx = j
                    return True
    return False

关于如何将标签合并到画布中的任何想法,以及如何将移动作为有效事件合并到画布上?非常感谢

1 个答案:

答案 0 :(得分:1)

如果您不需要移动磁贴的动画,那么您可以使用grid()将标签放在行和列中 - 而不是使用Canvas - 并将文本从标签移动到标签。

您甚至可以使用Button(而不是Label)和command=为按钮分配功能。

-

如果您需要动画,则可以使用create_window()Label添加到Canvasbind(event, function),以便将函数分配给事件调用的标签(例如)。

但您也可以使用place()Frame

中添加标签或按钮

-

您必须将所有标签/按钮保留在全局列表中才能访问它们。

-

编辑:简单而有效的示例(但不是完整版)

import tkinter as tk

# --- functions ---

def move(x, y):
    global empty_x, empty_y, game_running   

    if game_running:        
        # check and move tile
        if (empty_x, empty_y) in [(x+1, y), (x-1, y), (x, y+1), (x, y-1)]:

            board[empty_y][empty_x] = board[y][x]
            board[y][x] = ' '

            buttons[empty_y][empty_x]['text'] = buttons[y][x]['text']
            buttons[y][x]['text'] = ' '

            empty_x = x
            empty_y = y

            if won():
                # show label "Hurray"
                label.lift()
                game_running = False

    else:
        # start game again

        shuffle() # shuffle tiles

        game_running = True

        # hide label
        label.lower() # or frame.lift()


def won():

    number = 0

    for y, row in enumerate(board):
        for x, char in enumerate(row, 1):
            number += 1
            if number == 9 and char == ' ':
                #print('A |%s| %d' % (char, number))
                return True
            elif char != str(number):
                #print('B |%s| %d' % (char, number))
                return False

    return True


def shuffle():
    # TODO: shuffle tiles

    # it can't put tiles in random places
    # because it can create game without solution

    pass

# --- data ---

board = [
    ['1', '2', '3'],
    ['4', '5', '6'],
    ['7', '8', ' '],
]

empty_x = len(board[0])-1
empty_y = len(board)-1

# --- main ---

root = tk.Tk()

# create label hidden behide frame

label = tk.Label(root, text="Hurray!\n\n(click any button to play again)", bg="red")
label.grid(row=0, column=0, ipadx=20, ipady=20)

# create frame with buttons to fast show/hide label

frame = tk.Frame(root)
frame.grid(row=0, column=0) # the same (row,col) to hide label

buttons = []

for y, row in enumerate(board):

    buttons_row = []

    for x, char in enumerate(row):

        b = tk.Button(frame, text=char, width=10, height=5, command=lambda x=x,y=y:move(x,y))
        b.grid(row=y, column=x)

        buttons_row.append(b)

    buttons.append(buttons_row)

# start game

shuffle() # shuffle tiles
game_running = True

# start "the engine"

root.mainloop()

编辑StringVar

的新版本

shuffle中,我将瓷砖放在随机位置,有时我会在没有解决方案的情况下进行游戏。

几乎没有什么小修改 - “Hurray”现在是一个按钮并启动新游戏。

import tkinter as tk
import random

# --- functions ---

def move(x, y):
    global empty_x, empty_y, game_running   

    if game_running:        
        # check and move tile
        if (empty_x, empty_y) in [(x+1, y), (x-1, y), (x, y+1), (x, y-1)]:

            board[empty_y][empty_x].set( board[y][x].get() )
            board[y][x].set(' ')

            empty_x = x
            empty_y = y

            if won():
                # show label "Hurray"
                label.lift()
                game_running = False

    else:
        # start game again

        shuffle() # shuffle tiles


def won():

    number = 0

    for y, row in enumerate(board):
        for x, string_var in enumerate(row, 1):
            number += 1
            if number == 9 and string_var.get() == ' ':
                #print('A |%s| %d' % (char, number))
                return True
            elif string_var.get() != str(number):
                #print('B |%s| %d' % (char, number))
                return False

    return True


def shuffle():
    global empty_x, empty_y, game_running

    # TODO: shuffle tiles

    # it can't put tiles in random places
    # because it can create game without solution


    # clear all tiles to recognize (in next step) empty tiles 
    for row in board:
        for element in row:
            element.set('')

    # put tiles in random places
    for number in range(1, 10):
        while True: 
            row = random.randint(0, 2)
            col = random.randint(0, 2)
            if board[row][col].get() == '':
                board[row][col].set(str(number))
                print('row/col/number:', row, col, number)
                break

    # last number remove:
    print('empty row/col:', row, col)
    board[row][col].set(' ')
    empty_x = col
    empty_y = row

    # hide label
    label.lower() # or frame.lift()

    # start game
    game_running = True

# --- main ---

root = tk.Tk()

# --- data ---

# StringVar needs `root` - it has to be after tk.Tk()

# empty board
board = [   
#    [tk.StringVar(value='1'), tk.StringVar(value='2'), tk.StringVar(value='3')],
    [tk.StringVar(), tk.StringVar(), tk.StringVar()],
    [tk.StringVar(), tk.StringVar(), tk.StringVar()],
    [tk.StringVar(), tk.StringVar(), tk.StringVar()],
]

# create label hidden behide frame

label = tk.Button(root, text="Hurray!\n\n(click here to play again)", command=shuffle)
label.grid(row=0, column=0, ipadx=50, ipady=50)

# create frame with buttons to fast show/hide label

frame = tk.Frame(root)
frame.grid(row=0, column=0) # the same (row,col) to hide label

buttons = []

for y, row in enumerate(board):

    buttons_row = []

    for x, string_var in enumerate(row):

        b = tk.Button(frame, textvariable=string_var, width=10, height=5, command=lambda x=x,y=y:move(x,y))
        b.grid(row=y, column=x)

        buttons_row.append(b)

    buttons.append(buttons_row)

# start game

shuffle() # shuffle tiles

# start "the engine"

root.mainloop()