2014-12-04 108 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