2016-12-20 22 views
0

我想編碼連接4遊戲使用tkinter在計算機使隨機移動。我對Python非常陌生,所以我的代碼非常低效且笨重。我的主要問題是,當用戶點擊一列以在其中放置一塊碎片時,tkinter窗口崩潰。這似乎是由第二個while循環引起的,但沒有它,程序不會等待用戶在使計算機移動之前選擇列。這裏是我的代碼:連接4和tkinter的問題

import random 
from tkinter import * 


def setUpStacks(): 
    return [[],[],[],[],[],[],[]] 

def getStack(prompt,allStacks): 
    validInput=False 
    while validInput==False: 
     stack=int(input(prompt))-1 
     if len(allStacks[stack])<6: 
      if stack in range(7): 
       validInput=True 
      else: 
       print('Please enter a value from 1 to 7.') 
     else: 
      print('That stack is full.') 
    return stack 

def putInStack(stack,allStacks,player): 
    allStacks[stack]+=[player] 
    return allStacks 

def changePlayer(player): 
    if player=='red': 
     player='blue' 
    elif player=='blue': 
     player='red' 
    return player 

def checkForWin(stack,allStacks): 
    play=True 
    pos=len(allStacks[stack])-1 
    if len(allStacks[stack])>3: 
     if allStacks[stack][-1]==allStacks[stack][-2]==allStacks[stack][-3]==allStacks[stack][-4]: 
      play=False 
    if stack>2: ##XXXO 
     if len(allStacks[stack-1])>=pos+1 and len(allStacks[stack-2])>=pos+1 and len(allStacks[stack-3])>=pos+1: 
      if diagonalCheck(0,-1,pos,stack,allStacks)==False: 
       play=False 
     if len(allStacks[stack-1])>=pos+2 and len(allStacks[stack-2])>=pos+3 and len(allStacks[stack-3])>=pos+4: 
      if diagonalCheck(1,-1,pos,stack,allStacks)==False: 
       play=False 
     if 2<len(allStacks[stack-1])>=pos and 1<len(allStacks[stack-2])>=pos-1 and 0<len(allStacks[stack-3])>=pos-2: 
      if diagonalCheck(-1,-1,pos,stack,allStacks)==False: 
       play=False 
    if 1<stack<6: ##XXOX 
     if len(allStacks[stack-1])>=pos+1 and len(allStacks[stack-2])>=pos+1 and len(allStacks[stack+1])>=pos+1: 
      if middleCheck(0,-1,pos,stack,allStacks)==False: 
       play=False 
     if len(allStacks[stack-1])>=pos+2 and len(allStacks[stack-2])>=pos+3 and 1<=len(allStacks[stack+1])>=pos: 
      if middleCheck(1,-1,pos,stack,allStacks)==False: 
       play=False 
     if 2<=len(allStacks[stack-1])>=pos and 1<=len(allStacks[stack-2])>=pos-1 and 4<=len(allStacks[stack+1])>=pos+2: 
      if middleCheck(-1,-1,pos,stack,allStacks)==False: 
       play=False 
    if stack<4: ##OXXX 
     if len(allStacks[stack+1])>=pos+1 and len(allStacks[stack+2])>=pos+1 and len(allStacks[stack+3])>=pos+1: 
      if diagonalCheck(0,1,pos,stack,allStacks)==False: 
       play=False 
     if len(allStacks[stack+1])>=pos+2 and len(allStacks[stack+2])>=pos+3 and len(allStacks[stack+3])>=pos+4: 
      if diagonalCheck(1,1,pos,stack,allStacks)==False: 
       play=False 
     if 2<len(allStacks[stack+1])>=pos and 1<len(allStacks[stack+2])>=pos-1 and 0<len(allStacks[stack+3])>=pos-2: 
      if diagonalCheck(-1,1,pos,stack,allStacks)==False: 
       play=False 
    if 0<stack<5: ##XOXX 
     if len(allStacks[stack+1])>=pos+1 and len(allStacks[stack+2])>=pos+1 and len(allStacks[stack-1])>=pos+1: 
      if middleCheck(0,1,pos,stack,allStacks)==False: 
       play=False 
     if len(allStacks[stack+1])>=pos+2 and len(allStacks[stack+2])>=pos+3 and len(allStacks[stack-1])>=pos: 
      if middleCheck(1,1,pos,stack,allStacks)==False: 
       play=False 
     if 2<=len(allStacks[stack+1])>=pos and 1<=len(allStacks[stack+2])>=pos-1 and 4<=len(allStacks[stack-1])>=pos+1: 
      if middleCheck(-1,1,pos,stack,allStacks)==False: 
       play=False 
    return play 

def diagonalCheck(dirUp,dirAcross,pos,stack,allStacks): 
    if allStacks[stack][pos]==allStacks[stack+dirAcross][pos+dirUp]==allStacks[stack+(2*dirAcross)][pos+(2*dirUp)]==allStacks[stack+(3*dirAcross)][pos+(3*dirUp)]: 
     return False 
    else: 
     return True 

def middleCheck(dirUp,dirAcross,pos,stack,allStacks): 
    if allStacks[stack][pos]==allStacks[stack-dirAcross][pos-dirUp]==allStacks[stack+dirAcross][pos+dirUp]==allStacks[stack+(2*dirAcross)][pos+(2*dirUp)]: 
     return False 
    else: 
     return True 

def compMove(): 
    return random.randint(0,6) 

def c1Click(click): 
    global num 
    num=0 
def c2Click(click): 
    global num 
    num=1 
def c3Click(click): 
    global num 
    num=2 
def c4Click(click): 
    global num 
    num=3 
def c5Click(click): 
    global num 
    num=4 
def c6Click(click): 
    global num 
    num=5 
def c7Click(click): 
    global num 
    num=6 

window=Tk() 
window.title("Connect 4") 
c1=Canvas(window,width=100,height=600,background='gray') 
c2=Canvas(window,width=100,height=600,background='gray') 
c3=Canvas(window,width=100,height=600,background='gray') 
c4=Canvas(window,width=100,height=600,background='gray') 
c5=Canvas(window,width=100,height=600,background='gray') 
c6=Canvas(window,width=100,height=600,background='gray') 
c7=Canvas(window,width=100,height=600,background='gray') 

circ11=c1.create_oval(0,500,100,600,fill="white") 
circ12=c1.create_oval(0,400,100,500,fill="white") 
circ13=c1.create_oval(0,300,100,400,fill="white") 
circ14=c1.create_oval(0,200,100,300,fill="white") 
circ15=c1.create_oval(0,100,100,200,fill="white") 
circ16=c1.create_oval(0,0,100,100,fill="white") 

circ21=c2.create_oval(0,500,100,600,fill="white") 
circ22=c2.create_oval(0,400,100,500,fill="white") 
circ23=c2.create_oval(0,300,100,400,fill="white") 
circ24=c2.create_oval(0,200,100,300,fill="white") 
circ25=c2.create_oval(0,100,100,200,fill="white") 
circ26=c2.create_oval(0,0,100,100,fill="white") 

circ31=c3.create_oval(0,500,100,600,fill="white") 
circ32=c3.create_oval(0,400,100,500,fill="white") 
circ33=c3.create_oval(0,300,100,400,fill="white") 
circ34=c3.create_oval(0,200,100,300,fill="white") 
circ35=c3.create_oval(0,100,100,200,fill="white") 
circ36=c3.create_oval(0,0,100,100,fill="white") 

circ41=c4.create_oval(0,500,100,600,fill="white") 
circ42=c4.create_oval(0,400,100,500,fill="white") 
circ43=c4.create_oval(0,300,100,400,fill="white") 
circ44=c4.create_oval(0,200,100,300,fill="white") 
circ45=c4.create_oval(0,100,100,200,fill="white") 
circ46=c4.create_oval(0,0,100,100,fill="white") 

circ51=c5.create_oval(0,500,100,600,fill="white") 
circ52=c5.create_oval(0,400,100,500,fill="white") 
circ53=c5.create_oval(0,300,100,400,fill="white") 
circ54=c5.create_oval(0,200,100,300,fill="white") 
circ55=c5.create_oval(0,100,100,200,fill="white") 
circ56=c5.create_oval(0,0,100,100,fill="white") 

circ61=c6.create_oval(0,500,100,600,fill="white") 
circ62=c6.create_oval(0,400,100,500,fill="white") 
circ63=c6.create_oval(0,300,100,400,fill="white") 
circ64=c6.create_oval(0,200,100,300,fill="white") 
circ65=c6.create_oval(0,100,100,200,fill="white") 
circ66=c6.create_oval(0,0,100,100,fill="white") 

circ71=c7.create_oval(0,500,100,600,fill="white") 
circ72=c7.create_oval(0,400,100,500,fill="white") 
circ73=c7.create_oval(0,300,100,400,fill="white") 
circ74=c7.create_oval(0,200,100,300,fill="white") 
circ75=c7.create_oval(0,100,100,200,fill="white") 
circ76=c7.create_oval(0,0,100,100,fill="white") 

circs=[[circ11,circ12,circ13,circ14,circ15,circ16],[circ21,circ22,circ23,circ24,circ25,circ26],[circ31,circ32,circ33,circ34,circ35,circ36],[circ41,circ42,circ43,circ44,circ45,circ46],[circ51,circ52,circ53,circ54,circ55,circ56],[circ61,circ62,circ63,circ64,circ65,circ66],[circ71,circ72,circ73,circ74,circ75,circ76]] 
bottomCirc=[0,0,0,0,0,0,0] 

c1.grid(row=1,column=1) 
c2.grid(row=1,column=2) 
c3.grid(row=1,column=3) 
c4.grid(row=1,column=4) 
c5.grid(row=1,column=5) 
c6.grid(row=1,column=6) 
c7.grid(row=1,column=7) 

c1.bind("<Button-1>",c1Click) 
c2.bind("<Button-1>",c2Click) 
c3.bind("<Button-1>",c3Click) 
c4.bind("<Button-1>",c4Click) 
c5.bind("<Button-1>",c5Click) 
c6.bind("<Button-1>",c6Click) 
c7.bind("<Button-1>",c7Click) 

play=True 
player='red' 
stacks=setUpStacks() 
num=8 
chooseStack=num 
while play==True: 
    player=changePlayer(player) 
    while chooseStack==8: 
     window.update_idletasks() 
     window.update() 
     if player=="blue": 
      chooseStack=num 
     else: 
      chooseStack=compMove() 
    if chooseStack==0: 
     if bottomCirc[0]<6: 
      c1.itemconfig(circs[0][(bottomCirc[0])], fill=player) 
      bottomCirc[0]+=1 
    if chooseStack==1: 
     if bottomCirc[1]<6: 
      c2.itemconfig(circs[1][(bottomCirc[1])], fill=player) 
      bottomCirc[1]+=1 
    if chooseStack==2: 
     if bottomCirc[2]<6: 
      c3.itemconfig(circs[2][(bottomCirc[2])], fill=player) 
      bottomCirc[2]+=1 
    if chooseStack==3: 
     if bottomCirc[3]<6: 
      c4.itemconfig(circs[3][(bottomCirc[3])], fill=player) 
      bottomCirc[3]+=1 
    if chooseStack==4: 
     if bottomCirc[4]<6: 
      c5.itemconfig(circs[4][(bottomCirc[4])], fill=player) 
      bottomCirc[4]+=1 
    if chooseStack==5: 
     if bottomCirc[5]<6: 
      c6.itemconfig(circs[5][(bottomCirc[5])], fill=player) 
      bottomCirc[5]+=1 
    if chooseStack==6: 
     if bottomCirc[6]<6: 
      c7.itemconfig(circs[6][(bottomCirc[6])], fill=player) 
      bottomCirc[6]+=1 
    print(chooseStack) 
    num=8 
## stacks=putInStack(chooseStack,stacks,player) 
## play=checkForWin(chooseStack,stacks) 

就像我說的,我很新的Python,所以我從有限的知識工作,但我希望你能理解和幫助我:)

+0

你能提供錯誤堆棧嗎?並可能提供與您的問題相關的簡約代碼示例(您應該能夠從錯誤堆棧中查明)? – glls

+0

不要使用while循環。你應該使用'c1Click','c2Click'等完成所有工作。並使用for-loop來創建畫布和其他元素 - 使用列表來保留元素 - 「畫布[0]」而不是「c1」 - 然後您可以使用'for'循環縮短代碼。 – furas

+0

,在','和'='附近使用空格使代碼更具可讀性 - [PEP 8 - Python代碼樣式指南](https://www.python.org/dev/peps/pep-0008/) – furas

回答

0

你不應該」 t使用while -loops。你可以做任何事情,沒有這個循環 - 裏面c1Clickc2Click

這是示例如何使用按鈕單擊來做到這一點。它還顯示瞭如何使用for -loops和列表來縮短代碼。

代碼沒有完成但它已經爲人機和計算機繪製板並改變了顏色。

import random 
import tkinter as tk 

def make_move(player, choose_stack): 
    print('[DEBUG] make_move:', player, choose_stack) 

    if bottom_circles[choose_stack] >= 6: 
     return False # can't make move 

    col = choose_stack 
    row = bottom_circles[col] 
    circle = circles[col][row] 
    print('[DEBUG] col/row/circles:', col, row, circle) 

    canvases[col].itemconfig(circle, fill=player) 
    bottom_circles[col] += 1 

    return True # move was OK 

def on_click(event, number): 
    global player 

    # --- human --- 

    player = 'red' 

    choose_stack = number 

    if not make_move(player, choose_stack): 
     print("Wrong move - full stack") 
     return # skip computer move 

    # TODO: check if human wins 

    #if sum(bottom_circles) == 7*6: 
    if all(x == 6 for x in bottom_circles): 
     print("Board is full") 
     return # skip computer move 

    # --- computer --- 

    player = 'blue' 

    while True: 
     choose_stack = random.randint(0, 6) 

     if not make_move(player, choose_stack): 
      print("Wrong move - full stack") 
     else: 
      break 

    # TODO: check if computer wins 

    #if sum(bottom_circles) == 7*6: 
    if all(x == 6 for x in bottom_circles): 
     print("Board is full") 

# --- main --- 

window = tk.Tk() 
window.title("Connect 4") 

player = 'blue' 
bottom_circles = [0]*7 

canvases = [] 
circles = [] 

for col in range(7): 
    canvas = tk.Canvas(window, width=100, height=600, background='gray') 
    canvas.grid(row=0, column=col) 
    canvas.bind("<Button-1>", lambda event, number=col:on_click(event, number)) 

    canvases.append(canvas) 

    circles_column = [] 
    for row in range(5, -1, -1): 
     circle = canvas.create_oval(0, row*100, 100, (row+1)*100, fill="white") 
     circles_column.append(circle) 

    circles.append(circles_column) 

window.mainloop()