Thread code in pack style in tkinter

TrustyTony

Here version of TicTacToe demo code by wooeee with packing style, which is more familiar for me. Also fixed indents and made it run also with Python 3.

719 Views
About the Author

IT Pro doing Eng-Fin-Eng translations

from __future__ import print_function

try:
    from Tkinter import *
except ImportError:
    from tkinter import *
    
from functools import partial

class TicTacToe:
    def __init__(self, top):
        self.top = top
        self.button_dic = {}     ## pointer to buttons and StringVar()
        self.top.title('Buttons TicTacToe Test')
        self.top.geometry('400x500+0+0')
        self.top_frame = Frame(self.top, width=400, height=500)
        self.player = True   ## True = "X", False = "O"
        self.buttons()
        Button(self.top_frame, text='Restart', font=("Helvetica", 16),
             command=self.restart).pack(side=BOTTOM, expand=True)
        self.announce = StringVar()
        Label(self.top_frame, textvar=self.announce, font=("Helvetica", 16)).pack(side=BOTTOM, expand=True)
        self.clear_dict()
        top.mainloop()

    def clear_dict(self):
        self.x_o_dict = {"X":[], "O":[]}  ## list of "X" and "O" moves
        self.finnished = False
        for ind in range(1,10):
            self.button_dic[ind].set(str(ind))

    def restart(self):
        self.player = True
        self.announce.set("Restarted. X's turn")
        self.clear_dict()

    def buttons(self):
        """ create 9 buttons, a 3x3 grid """
        for j in range(3):
          f = Frame(self.top_frame)
          for i in range(3):
              ind = j * 3 + i + 1
              self.button_dic[ind] = StringVar()
              self.button_dic[ind].set(str(ind))
              b = Button(f, textvariable = self.button_dic[ind],
                         font=("Helvetica", 16),
                        command=partial(self.cb_handler, ind))
              b.pack(side=LEFT, expand=True, fill='both')
          f.pack(expand=True, fill='both')
        self.top_frame.pack(expand=True, fill='both')

    def cb_handler(self, square_number):
        """ Set button to symbol if not clicked before, announce result in title. """
        player = "X" if self.player else "O"

        if (square_number not in self.x_o_dict["X"] and 
            square_number not in self.x_o_dict["O"]):

            self.button_dic[square_number].set(player)
            self.x_o_dict[player].append(square_number)
            if self.check_for_winner(player):
                self.announce.set('%s is the * Winner *' % player)
            elif sum(len(self.x_o_dict[item]) for item in self.x_o_dict) == 9:
                self.announce.set('** Game was draw **')
            else:
                self.player = not self.player
                player = "X" if self.player else "O"
                self.announce.set("%s's turn" % player)
                return 
            self.clear_dict()
        else:
            self.announce.set("Occupied, pick another")
        

    def check_for_winner(self, player):

        winner_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9], 
                        [1, 4, 7], [2, 5, 8], [3, 6, 9],
                         [1, 5, 9], [3, 5, 7]]

        set_in = set(self.x_o_dict[player])
        for winner in winner_list:
            if set(winner).issubset(set_in):
                return True

if __name__ == '__main__':
    bt = TicTacToe(Tk())
e-papa 13 Posting Pro in Training

Tried it and it works well, even with python3.x
Kudos.

TrustyTony 888 pyMod Team Colleague Featured Poster

It had some slight blemishes, left overs, not updated comments. I fixed those and put the object style according to vegaseats style (but kept the import * from wooeee)

I ran it through pep8 checker to clean up last irregularities in style.

from __future__ import print_function

try:
    from Tkinter import *
except ImportError:
    from tkinter import *

from functools import partial


# vegaseat inheritted from Tk object
class TicTacToe(Tk):
    def __init__(self):
        Tk.__init__(self)
        # pointer to buttons and StringVar()
        self.button_dic = {}
        self.title('Buttons TicTacToe Test')
        self.geometry('400x500+0+0')
        self.top_frame = Frame(self, width=400, height=500)
        # True = "X", False = "O"
        self.player = True
        self.buttons()
        Button(self.top_frame, text='Restart', font=("Helvetica", 16),
             command=self.restart).pack(side=BOTTOM, expand=True)
        self.announce = StringVar()
        Label(self.top_frame,
              textvar=self.announce,
              font=("Helvetica", 16)).pack(side=BOTTOM, expand=True)
        self.clear_dict()

    def clear_dict(self):
        """ clearing the texts in buttons and list of moves """
        # list of "X" and "O" moves
        self.x_o_dict = {"X": [], "O": []}
        for ind in range(1, 10):
            self.button_dic[ind].set(str(ind))

    def restart(self):
        self.player = True
        self.announce.set("Restarted. X's turn")
        self.clear_dict()

    def buttons(self):
        """ create 9 buttons, a 3x3 grid """
        for j in range(3):
            f = Frame(self.top_frame)
            for i in range(3):
                ind = j * 3 + i + 1
                self.button_dic[ind] = StringVar()
                self.button_dic[ind].set(str(ind))
                b = Button(f, textvariable=self.button_dic[ind],
                           font=("Helvetica", 16),
                          command=partial(self.cb_handler, ind))
                b.pack(side=LEFT, expand=True, fill='both')
            f.pack(expand=True, fill='both')
        self.top_frame.pack(expand=True, fill='both')

    def cb_handler(self, square_number):
        """ Set button to symbol if not clicked before,
            announce result in announce label.

        """

        player = "X" if self.player else "O"

        if (square_number not in self.x_o_dict["X"] and
            square_number not in self.x_o_dict["O"]):

            self.button_dic[square_number].set(player)
            self.x_o_dict[player].append(square_number)
            if self.check_for_winner(player):
                self.announce.set('%s is the * Winner *' % player)
            elif sum(len(self.x_o_dict[item]) for item in self.x_o_dict) == 9:
                self.announce.set('** Game was draw **')
            else:
                self.player = not self.player
                player = "X" if self.player else "O"
                self.announce.set("%s's turn" % player)
                return
            self.clear_dict()
        else:
            self.announce.set("Occupied, pick another")

    def check_for_winner(self, player):

        winner_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9],
                        [1, 4, 7], [2, 5, 8], [3, 6, 9],
                         [1, 5, 9], [3, 5, 7]]

        set_in = set(self.x_o_dict[player])
        for winner in winner_list:
            if set(winner).issubset(set_in):
                return True

if __name__ == '__main__':
    bt = TicTacToe()
    bt.mainloop()
e-papa 13 Posting Pro in Training

Okay i think this will help me understand your codes better. i really could learn from this, I've been delving into GUI a bit and want to convert all the programs i wrote initially into GUI.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of 1.19 million developers, IT pros, digital marketers, and technology enthusiasts learning and sharing knowledge.