2014-12-04 111 views
0

我試圖用Python來構建一個簡單的井字遊戲,幾乎沒有現在除了遊戲崩潰時,它是一個領帶Python的井字遊戲界面遊戲崩潰時,領帶

所以當它是平局,最後的空方點擊不會變色像別人那樣,窗口凍結,點擊禁用....我不知道原因是

我的整個代碼是在這裏:

import tkinter 
import random 


class Game(object): 
    """ 
    Enter the class docstring here 
    """ 
    block_size = 100 
    def __init__(self, parent): 
     parent.title('Tic Tac Toe') 
     self.parent = parent 

     self.initialize_game() 

    def initialize_game(self): 
     # These are the initializations that need to happen 
     # at the beginning and after restarts 
     self.board = [None, None, None, None, None, None, None, None, None] # game board as a instance variable 
     self.map = {(0, 0): 0, (0, 1): 1, (0, 2): 2, (1, 0): 3, (1, 1): 4, (1, 2): 5, (2, 0): 6, (2, 1): 7, 
        (2, 2): 8} # map to self.board 
     self.top_frame = tkinter.Frame(self.parent) 
     self.top_frame.pack(side=tkinter.TOP) 

     # add restart button on top frame 
     restart_button = tkinter.Button(self.top_frame, text='Restart', width=20, 
             command=self.restart) 
     restart_button.pack() # register restart_button with geometry manager 

     # create bottom frame for group the label below 
     self.bottom_frame=tkinter.Frame(self.parent) 
     self.bottom_frame.pack(side=tkinter.BOTTOM) 

     # create label for displaying game result text 
     self.my_lbl=tkinter.Label(self.bottom_frame,text=None) 
     self.my_lbl.pack() 

     # create a canvas to draw our board on the top frame 
     self.canvas = tkinter.Canvas(self.top_frame, 
            width=self.block_size * 3, 
            height=self.block_size * 3) 

     # draw 3x3 visible blocks on the canvas 
     for ro in range(3): 
      for col in range(3): 

       self.canvas.create_rectangle(self.block_size * col, 
              self.block_size * ro, 
              self.block_size * (col + 1), 
              self.block_size * (ro + 1),fill='white') 

     # bind entire canvas with left click handler (play function) 
     self.canvas.bind("<Button-1>", self.play) 
     self.canvas.pack()     # register canvas with a geometry manager 

    def board_full(self): 
     if None not in self.board: 
      return True   # true for full 
     else: 
      return False   # false for not full 


    def possible_moves(self): 
     """return: list of possible moves""" 
     possible_moves = []     # list for possible moves 
     for i in range(0, 9): 
      if self.board[i] is None:  # if cell un-taken 
       possible_moves.append(i) # append the cell number to list 
      else: 
       pass    # cell taken, don't append 
     return possible_moves  # return list of possible moves 

    def pc_move(self): 
     m = True 
     while m: 
      pc_move = random.randint(0, 8) # random generate a number from 0 to 8 
      if pc_move in self.possible_moves(): # if the number is a possible move 
       self.board[pc_move] = 'O'   # mark O 
       self.canvas.itemconfigure(tagOrId=(pc_move+1),fill='blue') 
       m = False      # exit loop 
      else:        # not a possible movie 
       continue       # re-do 
     return self 

    def draw_out(self): 
     """to be deleted""" 
     print(self.board[0:3]) 
     print(self.board[3:6]) 
     print(self.board[6:9]) 

    def play(self, event): # This method is invoked when the user clicks on a square. 
     """ 
     when the player clicks on a un-taken square, this method first translate cursor into cell number, 
     then update game board and check game result based on condition 
     :parameter: click 
     :return: updated game object 
     """ 
     # after the click: part 1  human play first 
     print('clicked', event.y, event.x) # to be deleted show window coordinate 
     cx = self.canvas.canvasx(event.x) # window coordinate to canvas coordinate 
     cy = self.canvas.canvasy(event.y) # window coordinate to canvas coordinate 
     cid = self.canvas.find_closest(cx,cy)[0] # find the closet colored widget by click point 
     my_move = self.map[(cy // self.block_size, cx // self.block_size)] # map cursor 
     if self.board[my_move] is None:   # check if cell is empty 
      self.board[my_move] = 'X'    # if cell empty mark X for my play 
      self.canvas.itemconfigure(cid,fill='green') # fill green color for player 
      #self.canvas.itemconfigure(tagOrId=(my_move+1),fill='green') 
     else:    # if the cell taken, do nothing until click on empty square 
      return None 
             # check game result and board full: 
     self.draw_out()       # DEBUGGING line 
     if self.check_game()is not None: 
      print(self.check_game())    # DEBUGGING line 
     else: 
      pass 
     # part 2: while not filled, PC make one move right after my move: 
     self.possible_moves()      # check possible moves for PC 
     self.pc_move()       # pc make move 
     self.draw_out()       # DELETE LATER 
     # part3: check game result and board full 
     if self.check_game()is not None: 
      print(self.check_game())    # DEBUGGING line 
     else: 
      pass 
     return self # when board is filled, return 

    def check_game(self): 
     """ 
     Check if the game is win or lost or a tie 
     Return: win, lose, tie, none """ 
     result=None 
     if (self.board[0] == self.board[1] == self.board[2] == 'X') or (
          self.board[3] == self.board[4] == self.board[5] == 'X') or (
          self.board[6] == self.board[7] == self.board[8] == 'X') or (
          self.board[0] == self.board[3] == self.board[6] == 'X') or (
          self.board[1] == self.board[4] == self.board[7] == 'X') or (
          self.board[2] == self.board[5] == self.board[8] == 'X') or (
          self.board[0] == self.board[4] == self.board[8] == 'X') or (
          self.board[2] == self.board[4] == self.board[6] == 'X'): 
      result = 'You win!' # player win 
      self.my_lbl.configure(text=result) 
     elif (self.board[0] == self.board[1] == self.board[2] == 'O') or (
          self.board[3] == self.board[4] == self.board[5] == 'O') or (
          self.board[6] == self.board[7] == self.board[8] == 'O') or (
          self.board[0] == self.board[3] == self.board[6] == 'O') or (
          self.board[1] == self.board[4] == self.board[7] == 'O') or (
          self.board[2] == self.board[5] == self.board[8] == 'O') or (
          self.board[0] == self.board[4] == self.board[8] == 'O') or (
          self.board[2] == self.board[4] == self.board[6] == 'O'): 
      result = 'You lost!' # player lose 
      self.my_lbl.config(text=result) 
     elif self.board_full()is True: 
       result = 'A tie!' # tie 
       self.my_lbl.configure(text=result) 
     else: 
      pass 
     return result 


    def restart(self): 
     """ Reinitialize the game and board after restart button is pressed """ 
     self.top_frame.destroy() 
     self.bottom_frame.destroy() 
     self.initialize_game() 


def main(): 
    root = tkinter.Tk() # Instantiate a root window 
    my_game = Game(root) # Instantiate a Game object 
    root.mainloop() # Enter the main event loop 


if __name__ == '__main__': 
    main() 
+0

顯示給你的錯誤。 – 2014-12-04 07:40:00

+0

我沒有錯誤信息(呃..這裏的問題之一)在整個程序上運行調試器,什麼都沒有出現....有點卡住在這...哦,忘了提及崩潰總是發生在那裏船上只剩下一個空的廣場。 – 2014-12-04 07:44:58

回答

2

嘗試更換

def pc_move(self): m = True while m:

隨着

while not self.board_full():

你在哪裏設置m回假break,來代替。

的原因,你的代碼沒有工作,是因爲如果if pc_move in self.possible_moves():返回false,你跑:

else: continue

,直到時間的盡頭。

+0

試過這個,不行。它只會一舉結束遊戲,因爲在我的移動之後,程序會立即佔用所有其他位置,結果將永遠丟失。 – 2014-12-04 07:52:10

+0

@shadow,我爲監督道歉,請看看我的編輯,看看它是否有幫助。 – MeetTitan 2014-12-04 07:57:46

+1

事實上,問題在於,當玩家佔據最後一個方塊時,計算機也會嘗試選擇一個方塊,但由於沒有剩下的空方塊,因此會以無限循環結束。你使用m的循環很好,但需要額外檢查一個完整的棋盤。也許更好:如果電路板不滿,只調用該函數,並在pc_move()開始時斷言,如果不滿足此前提條件,則會發出錯誤消息。 – physicalattraction 2014-12-04 08:08:36