How to know who is winner in Tic Tac Toe in python using guizero

夙愿已清 提交于 2020-01-15 04:11:08

问题


I have created a game called Tic Tac Toe. There are 2 players one of them are Xs one of them are Os all you have to do is get your symbol 3 in a row without the other person blocking you.

The Gui for the game looks like this:

Code:

from guizero import App, TextBox, PushButton, Text, info

empty = '   '
player = "X"
def clicked(z):
    button = buttonlist[int(z)] # Finds out which button was pressed
    global empty, player
    if button.text != empty:
        pass # If button already pushed do nothing
    else:
        # Marks button with user's go
        button.text = player
        # Switches players
        if player == "X":
            player = "O"
        else:
            player = "X"
    return

def instructions():
    info("Instructions","There are 2 players one of them are Xs one of them are Os. All you have to do is you have to try getting your symbol 3 times in a row without the other player blocking you")
def quit_game():
    app.destroy()

app = App(title="Tic Tac Toe", layout="grid", width=200, height=250)
buttonlist = [] # Empty list to contain a list of Buttons

Player1_label = Text(app, text="Player 1",  align="top", grid=[0, 0, 2 , 1])
Player1 = TextBox(app, text=empty, align="top", grid=[2, 0, 3, 1])# Player 1 enters the username

Player2_label = Text(app, text="Player 2",  align="top", grid=[0, 1, 2 , 1])
Player2 = TextBox(app, text=empty, align="top", grid=[2, 1, 3, 1])# Player 2 enters the username

Instructions = PushButton(app, command=instructions, text="Instructions", grid=[0, 5, 3, 1])# Display the instructions

Quit = PushButton(app, command=quit_game ,text="Quit",grid=[10, 0, 3, 2])

# Create Buttons for game, in 3 rows of 3
z=0
for x in range(3):
    for y in range(2, 5):
        buttonlist.append(PushButton(app, text=empty, args=str(z), grid=[x, y], command=clicked))
        z+=1

app.display()

The problem I have is in displaying who is the winner. I know how to make a window appear to show the winner and the line that does this is:

app.info("Tic Tac Toe Winner","The winner is" + Player1.value)

But the problem that i am having is knowing who is the winner at the end of the game so and displaying that they are the winner also I have a feeling that to find out the winner its got something to do with buttonlist list that i made but i just cannot figure out how to do it so I would appriciate if some one could help me.

Thanks


回答1:


Nice game. To work with the game board, I would suggest to create an internal data representation rather than working with the gui elements all the time according to common practice.

The reason is, that if you work with the gui elements everywhere, it might be slower, as it is not the ideal data representation. You could not save the data with pickle etc and you also add a strong dependency to the gui framework you use. E.g. if you later plan to convert it to a web application etc. you will have a very hard time.

So I just created a simple data representation in which I store the field in a two dimensional array.

# check_win checks if there are three markings
# in one row/column or diagonally
def check_win():
    # the checks array is just a trick to
    # reduce the amount of code,
    # you could avoid it by just adding
    # one nested loop where the outer iterates 
    # over y and the inner over x
    # one with the outer on x and the inner on y
    # and then two others with just one loop
    # for the diagonals
    # the body of the inner loops would
    # esentially look the same as for the while
    # loop below
    checks= [(0, 0, 1, 1), (0, 2, 1, -1)]
    for i in range(3):
        checks.append((i, 0, 0, 1))
        checks.append((0, i, 1, 0))
    won= None
    for y, x, incr_y, incr_x in checks:
        player= field[y][x]
        found= player is not None
        while found and x < 3 and y < 3:
            found= (player == field[y][x])
            y+= incr_y
            x+= incr_x
        if found:
            won= player
            break
    return won

# I also changed your clicked method a bit, so
# it calles the check_win method
# and also changed the signature, so
# it gets the y and x coordinate of the
# button which makes maintaining the
# field array inside the clicked method
# a bit simpler and also seems more natural
# to me
def clicked(y, x):
    button = buttonlist[y][x] # Finds out which button was pressed
    global empty, player
    if button.text != empty:
        pass # If button already pushed do nothing
    else:
        # Marks button with user's go
        button.text = player
        field[y][x] = player
        # Switches players
        if player == "X":
            player = "O"
        else:
            player = "X"
    won= check_win()
    if won is not None:
        print(f'Player {won} has won the game')
    return

# now I initialize the field array
# it will contain None for an untouched
# cell and X/O if taken by the corresponding
# user
field= [[None] * 3 for i in range(3)]
buttonlist= list()

# to get the buttons to call the 
# clicked function with the new
# signature and also maintain the
# buttons in a two dimensional array
# I changed the order of your loops
# and the args argument
for y in range(0, 3):
    rowlist= list()
    buttonlist.append(rowlist)
    for x in range(3):
        rowlist.append(PushButton(app, text=empty, args=(y, x), grid=[x, y+2], command=clicked))
        z+=1

app.display()


# a plain vanilla version of check_win would look something like:

def check_win():
    for start in range(3):
        x= start
        mark= field[0][x]
        for y in range(1, 3):
            if field[y][x] != mark:
                # the sequence is not complete
                mark= None
        if mark is not None:
            # player who set the mark won
            return mark
        y= start
        mark= field[y][0]
        for x in range(1, 3):
            if field[y][x] != mark:
                # the sequence is not complete
                mark= None
        if mark is not None:
            # player who set the mark won
            return mark
    mark= field[0][0]
    for x in range(1, 3):
        if field[y][x] != mark:
            # the sequence is not complete
            mark= None
    if mark is not None:
        # player who set the mark won
        return mark
    mark= field[0][3]
    for x in range(1, 3):
        if field[y][2-x] != mark:
            # the sequence is not complete
            mark= None
    if mark is not None:
        # player who set the mark won
        return mark
    return None        


来源:https://stackoverflow.com/questions/57744832/how-to-know-who-is-winner-in-tic-tac-toe-in-python-using-guizero

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!