3
\$\begingroup\$

`I made this Tic-Tac-Toe game first, by using user input in the console here:https://pastebin.com/6zLjrWcf, and now new and improved using Tkinter:

import tkinter as tkfrom tkinter import ttkimport timedef create_button(relx, rely):    button = tk.Button(width=10, height=2, command=lambda: callback(button))    button.place(relx=relx, rely=rely)    return buttondef check_win():                         if (buttons[0]['text'] == buttons[1]['text'] == buttons[2]['text'] != '') or \            (buttons[3]['text'] == buttons[4]['text'] == buttons[5]['text'] != '') or \            (buttons[6]['text'] == buttons[7]['text'] == buttons[8]['text'] != '') or \            (buttons[0]['text'] == buttons[3]['text'] == buttons[6]['text'] != '') or \            (buttons[1]['text'] == buttons[4]['text'] == buttons[7]['text'] != '') or \            (buttons[2]['text'] == buttons[5]['text'] == buttons[8]['text'] != '') or \            (buttons[2]['text'] == buttons[4]['text'] == buttons[6]['text'] != '') or \            (buttons[0]['text'] == buttons[4]['text'] == buttons[8]['text'] != ''):        return True    else:        return Falsedef callback(button):    global turn, x    if x == 1:        time.sleep(1)        game.quit()    invalid['text'] = ''    if button['text'] != '':        invalid['text'] = 'Invalid space try again'        return    button['text'] = turn    if check_win():        invalid['text'] = 'Player ' + turn + ' WINS!!!!!'        x = 1    turn = ('0' if turn == 'X' else 'X')    label_button['text'] = 'PLAYER ' + turn + '\'S TURN.'x = 0turn = 'X'game = tk.Tk()game.title('TicTacToe')game.geometry('700x500')buttons = []for i in range(1, 10):    button_created = create_button(0.25 if i / 3 <= 1 else 0.45 if i / 3 <= 2 else 0.65, 0.2 if i in [1, 4, 7] else                                   0.4 if i in [2, 5, 8] else 0.6)    buttons.append(button_created)label_button = ttk.Button(game, text='PLAYER ' + turn + '\'S TURN.', style='Fun.TButton', width=20, state='disabled')label_button.pack(pady=30)invalid = tk.Label(text='')invalid.place(relx=0.4, rely=0.12)game.mainloop()

My main question is if there is a way to compact check_win()?Also please review the rest of the code.

askedAug 1, 2019 at 11:48
Manusman's user avatar
\$\endgroup\$

2 Answers2

1
\$\begingroup\$

Let us begin with some layout. This is a typical grid use case so that you won't have to manually manage grid. At the lowest level, a grid structure essentially places buttons by calculating coordinates. But this gets tedious over time, that's why a grid layout is provided. Also, it was a clever way of cheking win by being symbol agnostic. A normal tic tac toe game would have used checkwin(symbol) to determine win.

On strings

To escape' within' ' you can use" instead. From

'\'S TURN.'

to

"'S TURN."

and you can also use string formatting to clear up some clutter.

"PLAYER {}'S TURN.".format(turn)

On layout

Modifying yourcreate_button function to this allows a grid structure

def create_button(x, y):    button = tk.Button(width=10, height=2, command=lambda: callback(button))    button.grid(row=x, column=y)    return button

Then we modify others since different layouts can't be mixed

label_button = ttk.Button(                        game,                         text="PLAYER {}'S TURN.".format(turn),                         style='Fun.TButton', width=20,                         state='disabled')label_button.grid(row=0, column=1)invalid = tk.Label(text='')invalid.grid(row=4, column=1)

adding the buttons can be then done as

buttons = []buttons.append(create_button(1, 0))buttons.append(create_button(1, 1))buttons.append(create_button(1, 2))buttons.append(create_button(2, 0))buttons.append(create_button(2, 1))buttons.append(create_button(2, 2))buttons.append(create_button(3, 0))buttons.append(create_button(3, 1))buttons.append(create_button(3, 2))

You can use a loop for the row anditertools.cycle for the0, 1, 2 if you want to simplify it.

Thecheck_win function

  • Simplifying if

Adding a() to if statements allows you to writeor without\

if ... :    ...toif (...):    ...

thus the win_function can be simplified from

if (buttons[0]['text'] == buttons[1]['text'] == buttons[2]['text'] != '') or \(buttons[3]['text'] == buttons[4]['text'] == buttons[5]['text'] != '') or \

to

def check_win():    if (        (buttons[0]['text'] == buttons[1]['text'] == buttons[2]['text'] != '') or        (buttons[3]['text'] == buttons[4]['text'] == buttons[5]['text'] != '') or        ...        ):        return True    else:        return False
  • Simplifying values write-up

This can also be further simplified by defining a function to replacebuttons[0]['text']

def btext(i):    return buttons[i]['text']

and using it

def check_win():    if (        (btext(0) == btext(1) == btext(2) != '') or        (btext(3) == btext(4) == btext(5) != '') or        (btext(6) == btext(7) == btext(8) != '') or        (btext(0) == btext(3) == btext(6) != '') or        (btext(1) == btext(4) == btext(7) != '') or        (btext(2) == btext(5) == btext(8) != '') or        (btext(2) == btext(4) == btext(6) != '') or        (btext(0) == btext(6) == btext(8) != '')        ):        return True    else:        return False

On architecture

A common pattern is the MVC (Model, View, Controller). While checking and updating gui directly works here, you might consider adding states in a structure like this:

board = [    ['', '', ''],    ['', '', ''],    ['', '', '']]

Operations are done on this and the gui is updated according to this.

answeredAug 3, 2019 at 5:16
Abdur-Rahmaan Janhangeer's user avatar
\$\endgroup\$
-1
\$\begingroup\$

From :Python Tic Tac Toe Game

    win_commbinations = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7), (2, 5, 8), (0, 4, 8), (2, 4, 6))for a in win_commbinations:            if board[a[0]] == board[a[1]] == board[a[2]] == "X":                print("Player 1 Wins!\n")                print("Congratulations!\n")                return True            if board[a[0]] == board[a[1]] == board[a[2]] == "O":                print("Player 2 Wins!\n")                print("Congratulations!\n")                return True        for a in range(9):            if board[a] == "X" or board[a] == "O":                count += 1            if count == 9:                print("The game ends in a Tie\n")                return True

This alternative solution is a bit cleaner + includes a "Tie" check, which your original solution doesn't check ( just remove if you consider it irrelevant ofc )

answeredAug 1, 2019 at 15:28
spYder's user avatar
\$\endgroup\$
1
  • \$\begingroup\$You have not reviewed the code, but instead presented your own solution. While the code may improve some aspects, it does not have a tkinter GUI like the original code does.\$\endgroup\$CommentedAug 1, 2019 at 16:11

You mustlog in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.