Python Forum
Tic-Tac game (Beginner's coding)
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Tic-Tac game (Beginner's coding)
#1
I have tried to code Tic-Tac game.
I think my code needs lots of optimization but can't figure that out.
FYI: I haven't studied maths/matrix after schooling that is 15years ago.
That's why I used list and dict operations to create this game.

def status_print(game):
    print(game[0])
    print(game[1])
    print(game[2])


new_game = [
    [111, 222, 333],
    [444, 555, 666],
    [777, 888, 999]
]
game_dict = {111: (0, 0), 222: (0, 1), 333: (0, 2),
             444: (1, 0), 555: (1, 1), 666: (1, 2),
             777: (2, 0), 888: (2, 1), 999: (2, 2)}

status_print(new_game)
result_pending = True
game = new_game.copy()
entry_count = 0
while result_pending or entry_count < 5:
    
    player_1 = int(input("Player 1, enter positional number of X: "))
    
    entry_count += 1
    x, y = game_dict.get(player_1)
    game[x].pop(y)
    game[x].insert(y, 'X')
    status_print(game)
    any_rowX = list((game[0].count('X'), game[1].count('X'), game[2].count('X')))
    column1 = list((game[0][0], game[1][0], game[2][0]))
    column2 = list((game[0][1], game[1][1], game[2][1]))
    column3 = list((game[0][2], game[1][2], game[2][2]))
    any_columnX = list((column1.count('X'), column2.count('X'), column3.count('X')))
    diagonal1 = list((game[0][0], game[1][1], game[2][2]))
    diagonal2 = list((game[2][0], game[1][1], game[0][2]))
    any_diagonalX = list((diagonal1.count('X'), diagonal2.count('X')))

    if 3 in any_rowX or 3 in any_columnX or 3 in any_diagonalX:
        print("Player 1 won (X-X-X)!!")
        print("Congratulations!!")
        break
    if entry_count == 5:
        print("Drawn")
        result_pending = False
        break
    
    player_2 = int(input("Player 2, enter positional number of O: "))

    x, y = game_dict.get(player_2)
    game[x].pop(y)
    game[x].insert(y, 'O')
    status_print(game)
    any_rowO = list((game[0].count('O'), game[1].count('O'), game[2].count('O')))
    column1 = list((game[0][0], game[1][0], game[2][0]))
    column2 = list((game[0][1], game[1][1], game[2][1]))
    column3 = list((game[0][2], game[1][2], game[2][2]))
    any_columnO = list((column1.count('O'), column2.count('O'), column3.count('O')))
    diagonal1 = list((game[0][0], game[1][1], game[2][2]))
    diagonal2 = list((game[2][0], game[1][1], game[0][2]))
    any_diagonalO = list((diagonal1.count('O'), diagonal2.count('O')))

    if 3 in any_rowO or 3 in any_columnO or 3 in any_diagonalO:
        print("Player 2 won (O-O-O)!!")
        print("Congratulations!!")
        break
print("Thank you for playing")
Your even little bit tip/suggestion is appreciated.
Thank you
Professional Dentist(32years) fell in love with Python during COVID-19 Lockdown.

"Nothing can stop you from learning new things except your own will"

Reply
#2
Hi,

This seems to work.
What exactly do you want to fix?
Montesquieu said: better is the enemy of good. :-)

Paul
Reply
#3
I tried to column1, 2, 3 and diagonal1, 2 variables in starting of while loop instead of repeating after each player's input entry.
But doing that, diagonal and column win condition never work out.
Professional Dentist(32years) fell in love with Python during COVID-19 Lockdown.

"Nothing can stop you from learning new things except your own will"

Reply
#4
Go through this page. It will be helpful
pyzyx3qwerty
"The greatest glory in living lies not in never falling, but in rising every time we fall." - Nelson Mandela
Need help on the forum? Visit help @ python forum
For learning more and more about python, visit Python docs
Reply
#5
I'm not an expert by any means, but here is my quick version of tic-tac-toe:
board = [[" ", " ", " "], [" ", " ", " "], [" ", " ", " "]]
lines = (((0,0), (0,1), (0,2)), ((1,0), (1,1), (1,2)), ((2,0), (2,1), (2,2)),
         ((0,0), (1,0), (2,0)), ((0,1), (1,1), (2,1)), ((0,2), (1,2), (2,2)),
         ((0,0), (1,1), (2,2)), ((0,2), (1,1), (2,0)))
players = ["X", "O"]

def print_board():
    for row in board:
        print(row)

def check_winner():
    for line in lines:
        piece = list(set([board[line[0][0]][line[0][1]], board[line[1][0]][line[1][1]], board[line[2][0]][line[2][1]]]))
        if len(piece) == 1 and piece[0] != ' ':
            return piece[0]
    return ' '

def tic_tac_toe():
    winner = ' '
    turn = 0
    while turn < 9:
        player = players[turn % 2]
        print_board()
        row = -1 # Python needs a do-while loop
        while row == -1 or board[row][column] != ' ':
            row = int(input("Select row: ")) - 1
            column = int(input("Select column: ")) - 1
        board[row][column] = player
        winner = check_winner()
        if winner != ' ':
            break
        turn += 1
    print_board()
    if winner == ' ':
        print("Draw")
    else:
        print("Winner:", winner)
        
tic_tac_toe()
I think mine's pretty optimized.

I do not understand the need for a dictionary and a list as on lines 7 & 12, and you repeat 29-36 on 53-60 with only one minor change. I would look to combine some of those to slim down your code and improve readability. Clues on how to do this are in my code.
Reply
#6
I like your idea of using markers or keys to help the player make a selection, but I would make them characters instead of numbers. This makes it really easy to test if the input is valid.
board = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
while not (choice := input(f'Place {marker} at ')) in board:
   print(f'{choice} is not a valid choice')
board[board.index(choice)] = marker
I see no reason to use rows and columns. The first row is board[0] through board[2]. The first column is board[0], board[3], board[6]. If you want to print the second row of the board it's as simple as
print(f'{board[3]} {board[4]} {board[5]}')
Do three prints and you have a board.
Output:
X|O|3 X|O|6 7|8|9 Place X at 7
Since there are only 8 possible ways to win tic-tac-toe, testing for a win is a managable if statement.
def check_win(board):
    return board[0] == board[1] == board[2] or \
           ...
           board[0] == board[3] == board[6] or \
           ...
           board[0] == board[4] == board[8] or \
           board[6] == board[4] == board[2]
And the most important thing to remember about tic-tac-toe is; there is only one player. I cannot think of any multi-player board games. There are games where multiple players take turns at the board, but all the games are single player games and in many of those games only the last player can win. Your game will ask players to place an 'X' or an 'O', but there should not be separate code for each player. The game should only care about the current player. Draw the board, ask where to place the marker, check for the win. Repeat 9 times or until one of the players win.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Beginner Higher Lower Game wallytan 2 1,541 Sep-29-2022, 05:14 PM
Last Post: deanhystad
Question Beginner Boolean question [Guessing game] TKB 4 2,227 Mar-22-2022, 05:34 PM
Last Post: deanhystad
  Beginner Coding Help calpro 3 1,357 Oct-30-2021, 02:01 PM
Last Post: Yoriz
  Beginner Code, how to print something after a number of turns (guessing game) QTPi 4 2,683 Jun-18-2020, 04:59 PM
Last Post: QTPi
  Need help with rpsls game(Beginner corner) Bulxy88 1 1,624 Jun-01-2020, 02:42 PM
Last Post: pyzyx3qwerty
  coding a 2-player die game Pepper887 3 2,402 Mar-17-2019, 04:02 PM
Last Post: ichabod801
  Guessing Game with .WAV Files - Python Coding NonEntity 8 4,297 Nov-20-2018, 12:53 AM
Last Post: NonEntity
  Coding Problems With Mr.Stickman Game SheeppOSU 2 4,111 Jun-29-2018, 08:12 PM
Last Post: volcano63
  (beginner) How do I insert a restart game option? hshe2 1 4,954 Jan-18-2017, 11:47 AM
Last Post: j.crater

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020