4

Good day all,

I have been working on creating a GUI for my Tic Tac Toe game using PySimpleGUI. My code is as follow:

import PySimpleGUI as sg
import random 

board_layout1 = {(2,0):" ", (2,1):" ", (2,2): " ", (1,0): " ", (1,1): " ", (1,2): " ", (0,0): " ", (0,1): " ", (0,2): " "}

Board layout is based on:

Diagram

I then created an interface to take in user input (i.e. name and choosing X or O symbol).

layout = [      
        [sg.Text("Please enter your Name and your opponent's name")],    
        [sg.Text('Name', size=(15, 1)), sg.InputText('')],      
        [sg.Text('Name of opponent', size=(15, 1)), sg.InputText('')],
        [sg.Frame(layout=[
        [sg.Radio('X', "RADIO1", default=True, size=(10,1)), sg.Radio('O', "RADIO1")]], title='Options',title_color='red', relief=sg.RELIEF_SUNKEN, tooltip='Use these to set flags')],
        [sg.Submit(), sg.Cancel()]      
        ]

window = sg.Window('Tic Tac Toe Game').Layout(layout)         
button, events = window.Read() 
print(events)
window.close()     


player1, player2, player1_event, player2_event = events[0], events[1], events[2], events[3]

player1 and player2 will return their names. Player1_event and player2_event will return True or False. As I am using a checkbox, events2 will be True if I checked it while events[3] will be False.

I then assign the marker respectively.

if player1_event == True:
    player1_marker, player2_marker = ("X", "O")
else:
    player1_marker, player2_marker = ("O", "X")

Now, I will create the GUI for the board.

def board_gui():    
    max_row = max_col = 3

    layout =  [[sg.Button(' ', size=(8, 4), key=(i,j), pad=(0,0)) for j in range(max_col)] for i in range(max_col)]

    window = sg.Window('Tictactoe', layout)
    button, events = window.Read()
    return button 
    window.close()

Next (where the problem is), I created the function to update the board accordingly. So let's say if play1 starts first and he decided to choose 'X' as his marker. He picked the first grid and click on it. It marks 'X'. So the next click should belong to play2, whose marker is 'O'. My code seems to have issue updating the marker for the second click.

What I did:

def board_gui_update(marker):   
    max_row = max_col = 3

    layout =  [[sg.Button(' ', size=(8, 4), key=(i,j), pad=(0,0)) for j in range(max_col)] for i in range(max_col)]
    window = sg.Window('Tictactoe', layout)
    while True:
        button, events = window.Read()
        if button in (None, 'Exit'):
            break
        window[button].update(marker)

    window.close()

What I have tried:

def board_gui_update(marker):   
    max_row = max_col = 3
    layout =  [[sg.Button(' ', size=(8, 4), key=(i,j), pad=(0,0)) for j in range(max_col)] for i in range(max_col)]
    window = sg.Window('Tictactoe', layout)
    while True:
        button, events = window.Read()
        if button in (None, 'Exit'):
            break
        if marker == player1_marker:
            turn = player1
            if turn == player1:
                window[button].update(player1_marker)
                turn = player2
            else:
                window[button].update(player2_marker)
        else:
            if marker == player2_marker:
                turn = player2
                if turn == player2:
                    window[button].update(player2_marker)
                turn = player1
            else:
                window[button].update(player1_marker)

    window.close()

Doesn't seem to work here as well. I have looked into the documentations and also solutions that involved tkinter but nothing seems to be able to update the marker.

You can view the issue in this snapshot.

Dwight
  • 124
  • 2
  • 12
  • It would be helpful if you posted your code somewhere in full. You may want to file an Issue on the PySimpleGUI GitHub to get some help. Updating the text on a button works fine last I tried. I'm not exactly sure of the problem you're describing. Are you saying you are unable to change the button text? If so, try making a tiny program to see that's a problem or not. – Mike from PSG Feb 22 '20 at 21:52
  • It would be helpful to follow the coding conventions in the PySimpleGUI examples and documentation. This line of code is misleading and incorrect - button, events = window.Read(). It should read event, values = window.Read(). The second parameter is not events, it is the dictionary of values from the window. The first parameter is the event. Sometimes that can be a button, but it can be other things too so labeling it as a button is potentially confusing. – Mike from PSG Feb 22 '20 at 23:52

2 Answers2

1

See if this does what you're after. Every time you click on a square, it will change to a new marker. I think you're saying you cannot change the value shown on the button. This program shows you how to do it.

import PySimpleGUI as sg

layout = [[sg.B(' ', size=(8,4), key=(i,j)) for i in range(3)] for j in range(3)]

window = sg.Window('Tic Skeleton', layout)

while True:             # Event Loop
    event, values = window.read()
    print(event, values)
    if event in (None, 'Exit'):
        break
    current_marker = window[event].get_text()
    window[event].update('X' if current_marker == ' ' else 'O' if current_marker == 'X' else ' ')
window.close()

enter image description here

Mike from PSG
  • 5,312
  • 21
  • 39
  • Hi @MikeyB , thanks for the reply. I have copied the exact script provided from you and I'm still facing the same issue. Thanks for the advice, I have swapped button,events = Window.read() as I treated each output from the grid as a button. I will take your advice to not change it. I have include the [link] (https://repl.it/repls/NavyApprehensiveLevel) to my code. Thanks again. – Dwight Feb 23 '20 at 02:51
  • When you copy and paste the code provided, what happens when you click the buttons? Do they not change like in the image? If you need further support or believe there's a PySimpleGUI problem, post an issue on the project's github. http://www.PySimpleGUI.com. The problem with trying to do it here is that important information about versions, what os, etc, aren't posted. There's a form to fill in when you file an issue that will gather the needed info. – Mike from PSG Feb 23 '20 at 15:50
  • When I copied the code above and ran it, on repl.it, it works fine. Maybe there is a disconnect as to what "facing the same issue" means. I'm still confused. Here's my program on repl.it like yours. https://repl.it/@PySimpleGUI/Buttons – Mike from PSG Feb 23 '20 at 15:56
  • Was able to run your code and click on squares that changed to X. It looks like a logic problem in your code, not an error of some kind in PySimpleGUI. Keep working at it. Combined with the fact that the demo code presented worked and was able to modify the button labels at will means you've got a bug somewhere. – Mike from PSG Feb 23 '20 at 16:04
  • I apologise for my poor wording that caused this misunderstanding. I was expecting something like this [link](https://media.giphy.com/media/hrAIBly5Lw4iP0UYr8/giphy.gif) – Dwight Feb 24 '20 at 03:11
  • You should be able to do that with no problem. The code above shows you how to change the symbols and you can change the colors using the same update method. I guess I don't see the problem. Your program was able to change both the color (to black) and the symbol on the button. It seems like you've got the capabilities you need from PySimpleGUI. It's a matter of getting them to work together with the correct logic for the game. – Mike from PSG Feb 24 '20 at 13:49
0

Based on the samples above, I made this code wich can alternate between the 'O' and 'X'. I used a variable that alternates between False and True, and two ifs that identifies the values inside window[event].get_text(), analysis it and changes the variable.

import PySimpleGUI as sg

layout = [[sg.Button(' ', size=(8,4)), sg.Button(' ', size=(8,4)), 
           sg.Button(' ', size=(8,4))],
          [sg.Button(' ', size=(8,4)), sg.Button(' ', size=(8,4)), 
           sg.Button(' ', size=(8,4))],
          [sg.Button(' ', size=(8,4)), sg.Button(' ', size=(8,4)), 
           sg.Button(' ', size=(8,4))]]

turn = True
window = sg.Window('Tic Tac Toe', layout)

while True:    # Event Loop
    event, values = window.read()
    print(event, values) #Just for development purposes.
    if event in (None, 'Exit'):
        break
    current_marker = window[event].get_text()
    # I placed all updates conditionals inside this, works better than 
    # individuals 'ifs' for each of they.
    window[event].update('X' if current_marker == ' ' and 
                         turn == True else 'O' if current_marker == ' ' and 
                         turn == False else 'X' if current_marker == 'X' 
                         else 'O' if current_marker == 'O' else ' ') 
    # The conditionals that change which value should be inserted.
    if window[event].get_text() == 'X':
        turn = False                       
    elif window[event].get_text() == 'O':
        turn = True

window.close()
William Miller
  • 9,839
  • 3
  • 25
  • 46