【问题标题】:How to determine a certain pattern with canvas created shapes?如何用画布创建的形状确定某种图案?
【发布时间】:2017-07-30 23:21:29
【问题描述】:

在 tkinter、python 中,我目前正在开发一款类似于“井字游戏”的游戏,玩家在面对对手时点击一个框并连续获得 3 个。我一直在用 python 做这个,但我不确定如何在连续 3 个框被填充时获得输出。这是我的代码:

# Tic Tac Toe

# --------------------------- #
import random           
from tkinter import *  
# --------------------------- #

root = Tk()
root.title("Tic Tac Toe")
root.geometry("800x800")

canvas = Canvas(root, height = 700, width=700)
canvas.pack()

movesd = 0
done = False

rec1 = canvas.create_rectangle(100, 0, 200, 100, fill='white', tags="r1")
canvas.move(rec1, 100, 150)
rec2 = canvas.create_rectangle(100, 0, 200, 100, fill='white', tags="r2")
canvas.move(rec2, 200, 150)
rec3 = canvas.create_rectangle(100, 0, 200, 100, fill='white', tags="r3")
canvas.move(rec3, 300, 150)
rec4 = canvas.create_rectangle(100, 0, 200, 100, fill='white', tags="r4")
canvas.move(rec4, 100, 250)
rec5 = canvas.create_rectangle(100, 0, 200, 100, fill='white', tags="r5")
canvas.move(rec5, 200, 250)
rec6 = canvas.create_rectangle(100, 0, 200, 100, fill='white', tags="r6")
canvas.move(rec6, 300, 250)
rec7 = canvas.create_rectangle(100, 0, 200, 100, fill='white', tags="r7")
canvas.move(rec7, 100, 350)
rec8 = canvas.create_rectangle(100, 0, 200, 100, fill='white', tags="r8")
canvas.move(rec8, 200, 350)
rec9 = canvas.create_rectangle(100, 0, 200, 100, fill='white', tags="r9")
canvas.move(rec9, 300, 350)

rec1md = False
rec2md = False
rec3md = False
rec4md = False
rec5md = False
rec6md = False
rec7md = False
rec8md = False
rec9md = False

firstmovedone = False
secondgo = False
secondmovedone = False
thirdgo = False
thirdmovedone = False
fourthgo = False
fourthmovedone = False

def combinations():
    global done
    if movesd == 3:
        done = True
        label = Label(root, text="Congratulations! You Win!", font='Verdana, 50')
        label.pack()
    root.after(1, combinations)

def thirdmove():
    global fourthgo
    global thirdmovedone
    thirdmovedone = True
    global rec1md
    moves = ["rm1", "rm2", "rm3", "rm4", "rm5", "rm6"]
    firstrandom = random.choice(moves)
    if firstrandom == "rm1":
        if rec1md:
            thirdmove()
        else:
            rec1mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec1mf, 100, 150)
    if firstrandom == "rm2":
        if rec2md:
            thirdmove()
        else:
            rec2mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec2mf, 200, 150)
    if firstrandom == "rm3":
        if rec3md:
            thirdmove()
        else:
            rec3mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec3mf, 300, 150)
    if firstrandom == "rm4":
        if rec4md:
            thirdmove()
        else:
            rec4mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec4mf, 100, 250)
    if firstrandom == "rm5":
        if rec5md:
            thirdmove()
        else:
            rec5mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec5mf, 200, 250)
    if firstrandom == "rm6":
        if rec6md:
            thirdmove()
        else:
            rec6mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec6mf, 300, 250)
    if firstrandom == "rm7":
        if rec7md:
            thirdmove()
        else:
            rec7mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec7mf, 100, 350)
    if firstrandom == "rm8":
        if rec8md:
            thirdmove()
        else:
            rec8mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec8mf, 200, 350)
    if firstrandom == "rm9":
        if rec9md:
            thirdmove()
        else:
            rec9mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec9mf, 300, 350)
    fourthgo = True

def secondmove():
    global thirdgo
    global secondmovedone
    secondmovedone = True
    global rec1md
    moves = ["rm1", "rm2", "rm3", "rm4", "rm5", "rm6"]
    firstrandom = random.choice(moves)
    if firstrandom == "rm1":
        if rec1md:
            secondmove()
        else:
            rec1mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec1mf, 100, 150)
    if firstrandom == "rm2":
        if rec2md:
            secondmove()
        else:
            rec2mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec2mf, 200, 150)
    if firstrandom == "rm3":
        if rec3md:
            secondmove()
        else:
            rec3mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec3mf, 300, 150)
    if firstrandom == "rm4":
        if rec4md:
            secondmove()
        else:
            rec4mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec4mf, 100, 250)
    if firstrandom == "rm5":
        if rec5md:
            secondmove()
        else:
            rec5mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec5mf, 200, 250)
    if firstrandom == "rm6":
        if rec6md:
            secondmove()
        else:
            rec6mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec6mf, 300, 250)
    if firstrandom == "rm7":
        if rec7md:
            secondmove()
        else:
            rec7mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec7mf, 100, 350)
    if firstrandom == "rm8":
        if rec8md:
            secondmove()
        else:
            rec8mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec8mf, 200, 350)
    if firstrandom == "rm9":
        if rec9md:
            secondmove()
        else:
            rec9mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec9mf, 300, 350)
    thirdgo = True

def firstmove():
    global secondgo
    global firstmovedone
    firstmovedone = True
    global rec1md
    moves = ["rm1", "rm2", "rm3", "rm4", "rm5", "rm6"]
    firstrandom = random.choice(moves)
    if firstrandom == "rm1":
        if rec1md:
            firstmove()
        else:
            rec1mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec1mf, 100, 150)
    if firstrandom == "rm2":
        if rec2md:
            firstmove()
        else:
            rec2mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec2mf, 200, 150)
    if firstrandom == "rm3":
        if rec3md:
            firstmove()
        else:
            rec3mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec3mf, 300, 150)
    if firstrandom == "rm4":
        if rec4md:
            firstmove()
        else:
            rec4mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec4mf, 100, 250)
    if firstrandom == "rm5":
        if rec5md:
            firstmove()
        else:
            rec5mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec5mf, 200, 250)
    if firstrandom == "rm6":
        if rec6md:
            firstmove()
        else:
            rec6mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec6mf, 300, 250)
    if firstrandom == "rm7":
        if rec7md:
            firstmove()
        else:
            rec7mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec7mf, 100, 350)
    if firstrandom == "rm8":
        if rec8md:
            firstmove()
        else:
            rec8mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec8mf, 200, 350)
    if firstrandom == "rm9":
        if rec9md:
            firstmove()
        else:
            rec9mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec9mf, 300, 350)
    secondgo = True

def r1m(event):
    combinations()
    global firstmovedone
    if firstmovedone == False:
        global movesd
        global rec1md
        rec1md = True
        rec1m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
        canvas.move(rec1m, 100, 150)
        canvas.delete(rec1)
        root.after(1000, firstmove)
        movesd += 1
    else:
        if secondgo == True:
            global movesd
            global rec1md
            rec1md = True
            rec1m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
            canvas.move(rec1m, 100, 150)
            canvas.delete(rec1)
            root.after(1000, firstmove)
            movesd += 1


def r2m(event):
    combinations()
    if firstmovedone == False:
        global movesd
        global rec2md
        rec2md = True
        rec2m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
        canvas.move(rec2m, 200, 150)
        canvas.delete(rec2)
        root.after(1000, firstmove)
        movesd += 1
    else:
        if secondgo == True:
            global movesd
            global rec2md
            rec2md = True
            rec2m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
            canvas.move(rec2m, 200, 150)
            canvas.delete(rec2)
            root.after(1000, secondmove)
            movesd += 1

def r3m(event):
    combinations()
    if firstmovedone == False:
        global movesd
        global rec3md
        rec3md = True
        rec3m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
        canvas.move(rec3m, 300, 150)
        canvas.delete(rec3)
        root.after(1000, firstmove)
    else:
        if secondgo == True:
            global movesd
            global rec3md
            rec3md = True
            rec3m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
            canvas.move(rec3m, 300, 150)
            canvas.delete(rec3)
            root.after(1000, secondmove)
            movesd += 1
        else:
            if thirdgo == True:
                global rec3md
                rec3md = True
                rec3m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
                canvas.move(rec3m, 300, 150)
                canvas.delete(rec3)
                root.after(1000, thirdmove)
                movesd += 1

def r4m(event):
    combinations()
    if firstmovedone == False:
        global movesd
        global rec4md
        rec4md = True
        rec4m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
        canvas.move(rec4m, 100, 250)
        canvas.delete(rec4)
        root.after(1000, firstmove)
        movesd += 1
    else:
        if secondgo == True:
            global movesd
            global rec4md
            rec4md = True
            rec4m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
            canvas.move(rec4m, 100, 250)
            canvas.delete(rec4)
            root.after(1000, secondmove)
            movesd += 1
        else:
            if thirdgo == True:
                global movesd
                global rec4md
                rec4md = True
                rec4m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
                canvas.move(rec4m, 300, 250)
                canvas.delete(rec4)
                root.after(1000, fourthmove)
                movesd += 1

def r5m(event):
    combinations()
    if firstmovedone == False:
        global movesd
        global rec5md
        rec5md = True
        rec5m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
        canvas.move(rec5m, 200, 250)
        canvas.delete(rec5)
        root.after(1000, firstmove)
        movesd += 1
    else:
        if secondgo == True:
            global movesd
            global rec5md
            rec5md = True
            rec5m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
            canvas.move(rec5m, 200, 250)
            canvas.delete(rec5)
            root.after(1000, secondmove)
            movesd += 1
        else:
            if thirdgo == True:
                global movesd
                global rec5md
                rec5md = True
                rec5m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
                canvas.move(rec5m, 300, 250)
                canvas.delete(rec5)
                root.after(1000, thirdmove)
                movesd += 1

def r6m(event):
    combinations()
    if firstmovedone == False:
        global movesd
        global rec5md
        rec6md = True
        rec6m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
        canvas.move(rec6m, 300, 250)
        canvas.delete(rec6)
        root.after(1000, firstmove)
        movesd += 1
    else:
        if secondgo == True:
            global movesd
            global rec6md
            rec6md = True
            rec6m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
            canvas.move(rec6m, 300, 250)
            canvas.delete(rec6)
            root.after(1000, secondmove)
            movesd += 1
        else:
            if thirdgo == True:
                global movesd
                global rec6md
                rec6md = True
                rec6m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
                canvas.move(rec6m, 300, 250)
                canvas.delete(rec6)
                root.after(1000, thirdmove)
                movesd += 1

def r7m(event):
    combinations()
    if firstmovedone == False:
        global movesd
        global rec7md
        rec7md = True
        rec7m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
        canvas.move(rec7m, 100, 350)
        canvas.delete(rec7)
        root.after(1000, firstmove)
        movesd += 1
    else:
        if secondgo == True:
            global movesd
            global rec7md
            rec7md = True
            rec7m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
            canvas.move(rec7m, 100, 350)
            canvas.delete(rec7)
            root.after(1000, secondmove)
            movesd += 1
        else:
            if thirdgo == True:
                global movesd
                global rec7md
                rec7md = True
                rec7m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
                canvas.move(rec7m, 100, 350)
                canvas.delete(rec7)
                root.after(1000, thirdmove)
                movesd += 1

def r8m(event):
    combinations()
    if firstmovedone == False:
        global movesd
        global rec8md
        rec8md = True
        rec8m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
        canvas.move(rec8m, 200, 350)
        canvas.delete(rec8)
        root.after(1000, firstmove)
        movesd += 1
    else:
        if secondgo == True:
            global movesd
            global rec8md
            rec8md = True
            rec8m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
            canvas.move(rec8m, 200, 350)
            canvas.delete(rec8)
            root.after(1000, secondmove)
            movesd += 1
        else:
            if thirdgo == True:
                global movesd
                global rec8md
                rec8md = True
                rec8m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
                canvas.move(rec8m, 200, 350)
                canvas.delete(rec8)
                root.after(1000, thirdmove)
                movesd += 1

def r9m(event):
    combinations()
    global movesd
    if firstmovedone == False:
        global rec9md
        rec9md = True
        rec9m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
        canvas.move(rec9m, 300, 350)
        canvas.delete(rec9)
        root.after(1000, firstmove)
        movesd += 1
    else:
        if secondgo == True:
            global rec9md
            rec9md = True
            rec9m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
            canvas.move(rec9m, 300, 350)
            canvas.delete(rec9)
            root.after(1000, secondmove)
            movesd += 1
        else:
            if thirdgo == True:
                global rec9md
                rec9md = True
                rec9m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
                canvas.move(rec9m, 300, 350)
                canvas.delete(rec9)
                root.after(1000, thirdmove)
                movesd += 1

done = False

canvas.tag_bind(rec1, "<ButtonPress-1>", r1m)
canvas.tag_bind(rec2, "<ButtonPress-1>", r2m)
canvas.tag_bind(rec3, "<ButtonPress-1>", r3m)
canvas.tag_bind(rec4, "<ButtonPress-1>", r4m)
canvas.tag_bind(rec5, "<ButtonPress-1>", r5m)
canvas.tag_bind(rec6, "<ButtonPress-1>", r6m)
canvas.tag_bind(rec7, "<ButtonPress-1>", r7m)
canvas.tag_bind(rec8, "<ButtonPress-1>", r8m)
canvas.tag_bind(rec9, "<ButtonPress-1>", r9m)

mainloop()

长代码,是的。在combinations 函数中,我尝试在玩家超过 3 次时将窗口设置为“你赢”,但正如我所怀疑的那样,这不是游戏的运作方式。总而言之,我想知道如何在不输入 120 种可能组合的情况下识别模式。谢谢你的时间:)

【问题讨论】:

  • 是否可以将您的代码最小化到可以重现问题的状态?

标签: python tkinter python-3.5


【解决方案1】:

要在井字游戏游戏中获胜,玩家必须在水平、垂直或对角线上对齐 3 个标记。所提出的算法仅侧重于计算玩家放置的标记数量,并在计数器为 3 时宣布获胜者(函数 combinations() 中的if movesd == 3:)。

要计算每次移动后棋盘的状态,需要将rec1md = False 的使用替换为rec9md = False 切换为True 由recmd = [..] 填充的棋盘的完整视图' '=free, 'R'=红色玩家和'B'=蓝色玩家:

第 1 步 - 使用 board 的新状态 = 9 个单元格的数组

# all cases of the board are initialized to ' '=free
recmd = [ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
#rec1md = False
#rec2md = False
...
#rec9md = False

第 2 步 - 将每个 rec&lt;X&gt;md 更新为 recmd[&lt;X-1&gt;]

firstmove()secondmove()thirdmove() 函数中。

if firstrandom == "rm1":
    if (recmd[0] != ' '): # is the case still marked ?
        firstmove()
    else:
        rec1mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
        canvas.move(rec1mf, 100, 150)
        recmd[0] = 'B' # to mark the case as 'B'=blue player

r1m(event)、...和r9m(event) 函数中。

global recmd # rec1md
if firstmovedone == False:
    recmd[0] = 'R' # instead of  rec1md = True
    rec1m = canvas.create_rectangle(100, 0, 200, 100, fill='red')
    canvas.move(rec1m, 100, 150)
    canvas.delete(rec1)

第三步 - 创建检查函数boardstate(recmd)

函数返回以下状态:'INPROG'= 游戏进行中,'WIN'= 人类(红色玩家)获胜,'LOSE'= 计算机(蓝色玩家)获胜 & @987654344 @= 没有赢家。

1-检查一行是否被RB填充。

for i in range(0,3):
    # rows
    if ((recmd[(i*3)+0]=='R') and (recmd[(i*3)+1]=='R') and (recmd[(i*3)+2]=='R')):
        print("Win in row[%d]." % (i+1))
        return ('WIN')
    if ((recmd[(i*3)+0]=='B') and (recmd[(i*3)+1]=='B') and (recmd[(i*3)+2]=='B')):
        print("Lose in row[%d]." % (i+1))
        return ('LOSE')

2-检查一列是否由RB填充。

for i in range(0,3):
    #column
    if ((recmd[i+0]=='R') and (recmd[i+3]=='R') and (recmd[i+6]=='R')):
        print("Win in col[%d]." % (i+1))
        return ('WIN')
    if ((recmd[i+0]=='B') and (recmd[i+3]=='B') and (recmd[i+6]=='B')):
        print("Lose in col[%d]." % (i+1))
        return ('LOSE')

3-检查一条对角线是否被RB填充。

#diagonal
if ((recmd[0]=='R') and (recmd[4]=='R') and (recmd[8]=='R')):
    print("Win in diagonal.")
    return ('WIN')
if ((recmd[0]=='B') and (recmd[4]=='B') and (recmd[8]=='B')):
    print("Lose in diagonal.")
    return ('LOSE')
if ((recmd[6]=='R') and (recmd[4]=='R') and (recmd[2]=='R')):
    print("Win in diagonal.")
    return ('WIN')
if ((recmd[6]=='B') and (recmd[4]=='B') and (recmd[2]=='B')):
    print("Lose in diagonal.")
    return ('LOSE')

4-检查板子是否已满(未找到' '

if (' ' in recmd):
    return ('INPROG')
return ('NULL')

第 4 步 - 更新函数 combinations() 以管理 boardstate() 函数。

def combinations():
    global done
    global recmd
    iswin = boardstate(recmd)
    print('boardstate = %s' % (iswin))
    # if (movesd >= 3) and (done == False):
    if (iswin != 'INPROG') and (done == False):

新增第 1 个 >>>>

第 5 步 - 在函数末尾移动(或添加)combinations() 的调用。

要计算combinations() 中的正确状态,应在更新函数firstmove()、...、thirdmove() 上的recmd[..] 单元格后调用它。

此外,对于r1m(event)r9m(event) 的每个函数,添加对combinations() 函数的调用以在之后警告玩家。

combinations() 的调用必须添加到每个的 END r1m(event)r9m(event) 函数。

新增第 2 个 >>>>

第 6 步 - 管理游戏结束和其他更新。

当条件if (iswin != 'INPROG') and (done == False) 是 没错,您可以检查谁是获胜者并将done 设置为True

if (iswin != 'INPROG') and (done == False):
    print("test")
    done = True
    if (iswin == 'WIN'):
        print("Congratulation you Win !!!")
    elif (iswin == 'LOSE'):
        print("Sorry you Lose !!!")
    else:
        print("No winner, game over !!!")

那么,为了防止firstmove()函数重试,有必要通过在done == True时覆盖firstrandom来停止random.choice(moves)循环。不要忘记在函数开头声明global done

要保留firstmove() 函数,请通过删除firstmovedone = True 保留firstmovedone == False

def firstmove():
    global secondgo
    global firstmovedone
    # firstmovedone = True
    global recmd
    global done
    moves = ["rm1", "rm2", "rm3", "rm4", "rm5", "rm6", "rm7", "rm8", "rm9"]
    firstrandom = random.choice(moves)
    if (done == True):
        firstrandom = "end" # don't select a move
    if firstrandom == "rm1":
        if (recmd[0] != ' '): # is the case still marked ?
            firstmove()
        else:
            rec1mf = canvas.create_rectangle(100, 0, 200, 100, fill='blue')
            canvas.move(rec1mf, 100, 150)
            recmd[0] = 'B'
    ...

【讨论】:

  • 当我执行这段代码时,我遇到了一个反复出现的错误,告诉我firstmove() 有问题。事情是这样的:link
  • 您能否显示错误的行号之一(与相邻行)或编辑您的问题以附加更新功能firstmove()
  • 是否修改了函数firstmove()中的声明==> global recmd而不是global rec1md
  • 别在意第一个错误,现在我遇到的问题是,在我使用 firstmove 后什么都没有发生。例如,当我点击一个正方形时,蓝色应该会在一个正方形上“点击”,但这不会发生。如果需要,我可以向您发送我的代码链接。
  • @jakethefake,是的,请给我一个指向您的源代码的链接,然后我会更新我的答案(更改列表很长)
猜你喜欢
  • 2011-06-05
  • 2018-12-14
  • 1970-01-01
  • 2020-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多