1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/usr/bin/env python

import Tkinter as tk
import tkMessageBox as mb

class ttt:
    turn = 0
    players = ['Spieler 2', 'Spieler 1']
    colors = [ 'orange', 'cyan']
    signs = ['O', 'X' ]
    fields = [ [ [] for i in range (3) ] for i in range (3) ]
    hitten = [ [ [] for i in range (3) ] for i in range (3) ]

    def next_turn ( self ):
        '''Prepares next turn

        Sets turn counter and title widget'''
        self.turn += 1
        self.title.configure ( text = '%d. Zug\n%s' % (self.turn, self.players[self.turn%2]), bg =  self.colors[self.turn%2] )

    def check_win_cond ( self ):
        '''Validates win conditions

        Test diagonals, rows and columns for three identical, valid values'''
        # win conditions: diagonals
        if self.hitten[0][0] == self.hitten[1][1] and self.hitten[0][0] == self.hitten[2][2] and self.hitten[0][0] in self.signs:
            return True
        if self.hitten[0][2] == self.hitten[1][1] and self.hitten[0][2] == self.hitten[2][0] and self.hitten[0][2] in self.signs:
            return True
        # win conditions: lines
        for i in range ( 3 ):
            if self.hitten[0][i] == self.hitten[1][i] and self.hitten[0][i] == self.hitten[2][i] and self.hitten[0][i] in self.signs:
                return True
        # win conditions: columns
        for i in range ( 3 ):
            if self.hitten[i][0] == self.hitten[i][1] and self.hitten[i][0] == self.hitten[i][2] and self.hitten[i][0] in self.signs:
                return True
        return False

    def hit_field ( self, event ):
        '''Callback function

        Tests whether a field has previously been hitten and
        marks the field as hitten, if not hitten before, with
        the player's sign.

        Afterwards next_turn is called or the game is won'''
        widget = event.widget
        a, b = 0, 0
        for i in range ( len ( self.fields ) ):
            if widget in self.fields[i]:
                a = i
                b = self.fields[i].index ( widget )

        if not self.hitten[a][b] in self.signs:
            self.hitten[a][b] = self.signs[self.turn%2]
            self.fields[a][b].configure ( text = self.signs[self.turn%2], bg = self.colors[self.turn%2] )

            if not self.check_win_cond():
                self.next_turn()
            else:
                mb.showinfo ( 'Winner', 'And the winner is\n%s' % self.players[self.turn%2] )
                self.root.destroy()

    def __init__ ( self, root ):
        '''Main Window'''
        self.root = root

        self.title_frame = tk.Frame ( self.root, bg = 'red' )
        self.title_frame.pack ( side = 'top', fill = 'x' )

        self.title = tk.Label ( self.title_frame, text = '' )
        self.title.pack ( side = 'top' )

        self.game_frame = tk.Frame ( self.root )
        self.game_frame.pack ( side = 'top', fill = 'both' )

        for i in range ( len ( self.fields ) ):
            for j in range ( len ( self.fields[i] ) ):
                self.fields[i][j] = tk.Label ( self.game_frame, text = ' ', width = 10, height = 5, relief = 'ridge' )
                self.fields[i][j].grid ( row = i, column = j )
                self.fields[i][j].bind ( '<Button-1>', self.hit_field )

        self.q_frame = tk.Frame ( self.root, relief = 'ridge' )
        self.q_frame.pack ( side = 'bottom', fill = 'x' )

        qbutton = tk.Button ( self.q_frame, text = "Quit", command = self.root.destroy )
        qbutton.pack ( side = 'right' )

        self.next_turn()

if __name__ == '__main__':
    root = tk.Tk ( className = 'Tic Tac Toe' )
    window = ttt ( root )
    root.mainloop()