Tic Tac Toe Game

Joined
Mar 10, 2024
Messages
1
Reaction score
1
Hi, I'm a Python beginner; here is one of my first projects (Tic-Tac-Toe game with an option of boards from 1x1 to 6x6 (it could be extended later).

Next step I have in mind is to make a bot to play with, but right now don't know fully how to begin doing it.
I'll be grateful for any tips in optimizing the code more or adding some extras to the game :)

Python:
"""
Created on Wed Mar  6 12:03:44 2024

@author: jakubziom
"""

def Title():
    #prints title
    print(' ===============')
    print('   TIC-TAC-TOE')
    print(' ===============')
    print('type a1, b3, etc.')
    return

Title()

#defines size of the side of the board
while True:
    try:
        BoardSize=int(input('Board Size? 1-6?'))        
    except:
        continue    
    if  1 > BoardSize >6:
        continue
    elif 0 < BoardSize <7:
        break
         
#horizontal lines
Board0=[]
Board1=[]
Board2=[]
Board3=[]
Board4=[]
Board5=[]

'Player 1 = x'
'Player 2 = o'

#column letters transation to numbers
col={'a':0,'b':1,'c':2,'d':3,'e':4,'f':5}

BoardList=[Board0,Board1,Board2,Board3,Board4,Board5]

#number of marks in vertical lines (after player input)
Vx=[]
Vo=[]
#putting it together
V={'x':Vx,'o':Vo}

#number of marks in vertical lines (before player input)
OldVx=[]
OldVo=[]
#putting it together
OldV={'x':Vx,'o':Vo}

for i in range(0,BoardSize):
    #filling the lists to create the board
    for i in range(0,BoardSize):
        BoardList[i].insert(0,' ')
    #filling the lists to make vertical mark counters
    Vx.insert(0,0)
    Vo.insert(0,0)
    OldVx.insert(0,0)
    OldVo.insert(0,0)
    continue

def PrintBoard():
    #displays the board with separator lines (what player sees)
    BoardLetter=['    a','   b','   c','   d','   e','   f']
    #lists to put the horizontal line elements together
    LINE1=['1 │ ',]
    LINE2=['2 │ ',]
    LINE3=['3 │ ',]
    LINE4=['4 │ ',]
    LINE5=['5 │ ',]
    LINE6=['6 │ ',]

    BOARD=[LINE1,LINE2,LINE3,LINE4,LINE5,LINE6]

    for i in range(0,BoardSize):
        Letters=BoardLetter[slice(0,BoardSize)]
        lineSep='  ┼'+i*('───┼')+'───┼'
        for n in range(0,BoardSize):
                BOARD[n].append(BoardList[n][i])
                BOARD[n].append(' │ ')
    #lists for making final look of the horizontal lines
    line1=''
    line2=''
    line3=''
    line4=''
    line5=''
    line6=''
    letters=''
    lines=[line1,line2,line3,line4,line5,line6]
    for i in range(0,BoardSize):
        for a in BOARD[i]:
            #creates final looking lines with marks
            lines[i] += a
    for a in Letters:
        letters += a
    print(letters)
    print(lineSep)
    for i in range(0,BoardSize):
        print(lines[i])
        print(lineSep)
    return

def PrintCredits():
    #it prints credits after the game
    print('')
    print('')
    print('')
    print('')
    print('')
    print('')
    print('Created by jakubziom 2024')
    print('')
    print('')
    print('')
    print('')
    print('')
    print('')
    
    return

PrintBoard()

def Player(mark):
    #putting the mark
    while True:
        #player input
        player=input(mark+'?') 
        try:
            r=(int(player[1:])-1)
        except:
            continue    
        c_input=player[0]
        if r >= BoardSize or r <=-1:
            continue
        #column translation from letter to number
        try:
            c=col[c_input]
        except:
            continue
        if c >= BoardSize or c <=-1:
            continue
        #condition to prevent from putting the mark again in same place
        if not (BoardList[r][c]=='x' or BoardList[r][c]=='o'):
                BoardList[r].pop(c)
                BoardList[r].insert(c, mark)
                PrintBoard()
                break       
        else:  
            continue  
    return

i=0

def Congratulations(win,mark):
    #if one of the players wins
    win=True
    print(mark+' wins!')
    PrintCredits()
    input('press Enter to exit!')
    return win,mark

def PlayerWinsD1(mark,D1,win):
    #diagonal win 1
    for i in range(0,BoardSize):
        if BoardList[i][i]==mark:
            D1+=1   
    #this is for testing
    '''
    print('D1',mark,D1)
    '''
    if D1==BoardSize:
        Congratulations(win,mark)
    return D1,win

def PlayerWinsD2(mark,D2,win):
    #diagonal win 2
    for i in range(0,BoardSize):
        if BoardList[BoardSize-1-i][i]==mark:
            D2+=1 
    #this is for testing
    '''
    print('D2',mark,D2)
    '''
    if D2==BoardSize:
        Congratulations(win,mark)
    return D2,win

def OldMarkV(n,i,mark,OldV):
    #counting marks from previous round in vertical lines
    for i in range(0,BoardSize):
        for n in range(0,BoardSize):
            if BoardList[n][i]==mark:
                OldV[mark][i]+=1
    return OldV

def PlayerWinsV(n,i,mark,V):
    #vertical win
    for i in range(0,BoardSize):
        #substracting marks from previous round in vertical lines
        V[mark][i]-=(OldV[mark][i])
        #counting marks x or o in vertical lines
        for n in range(0,BoardSize):
            if BoardList[n][i]==mark:
                V[mark][i]+=1
                if V[mark][i]==BoardSize:
                    Congratulations(win,mark)
    #this is for testing
    '''
    print('V',mark,V)
    '''
    return V,win

#diagonal or horizontal win
def PlayerWinsDH(mark,win,n,i):
    #diagonal win
    PlayerWinsD1(mark,D1,win)
    PlayerWinsD2(mark, D2, win)
    for i in range(0,BoardSize):
        # horizontal win
        if BoardList[i].count(mark)==BoardSize:
            Congratulations(win,mark)
    return win

#values for checking draw
#is x in diagonal line 1?
D1Drawx=False
#is o in diagonal line 1?
D1Drawo=False
#is x in diagonal line 2?
D2Drawx=False
#is o in diagonal line 2?
D2Drawo=False
#putting it together
D1Draw={'x':D1Drawx,'o':D1Drawo}
D2Draw={'x':D2Drawx,'o':D2Drawo}

def Draw(win,mark):
    #diagonal draw 1
    for i in range(0,BoardSize):
        if BoardList[i][i]==mark:
            D1Draw[mark]=True   
    #this is for testing 
    '''
    print('D1Draw',D1Draw)
    '''
    #diagonal draw 2
    for i in range(0,BoardSize):
        if BoardList[BoardSize-1-i][i]==mark:
            D2Draw[mark]=True 
    #this is for testing
    '''
    print('D2Draw',D2Draw)
    '''
    VDrawCount=0
    HDrawCount=0
    #vertical draw
    for i in range(0,BoardSize):
        if V['x'][i]>=1 and V['o'][i]>=1:
            VDrawCount+=1
    #horizonal draw
    for i in range(0,BoardSize):
        if BoardList[i].count('x')>=1 and BoardList[i].count('o')>=1:
            HDrawCount+=1
    #this is for testing
    '''    
    print('VDrawCount',VDrawCount)
    print('HDrawCount',HDrawCount)
    '''
    #draw conditions
    if (D1Draw['x']==True and D1Draw['o']==True
        and D2Draw['x']==True and D2Draw['o']==True
        and VDrawCount==BoardSize
        and HDrawCount==BoardSize):      
        win=True
        print('DRAW!')
        input('press Enter to exit!')
        exit()
    return win,mark

#number of horizontal and verical lines with x and o in them
HDrawCount=0
VDrawCount=0
#this just counts the loop
n=0
#number of x or o in diagonal line 1 and 2
D1=0
D2=0
#number of rounds (obsolete)
game=0
#if true the game ends (player wins or draw)
win=False

while not win:
    #loop until the player wins or draw
    #x
    OldMarkV(n, i, 'x', OldV)
    Player('x')  
    PlayerWinsV(n,i,'x',V)
    PlayerWinsDH('x',win,n,i)
    Draw(win,'x')
    game+=1
    #o
    OldMarkV(n, i, 'o', OldV)
    Player('o')  
    PlayerWinsV(n,i,'o',V)
    PlayerWinsDH('o',win,n,i)
    Draw(win,'o')
    game+=1
 
Last edited:
Joined
Sep 21, 2022
Messages
122
Reaction score
15
I had an interesting bug when I wrote my first board game program.

It was connect 4, which is like tic tac toe, the players drop yellow and red counters into a vertical 7 by 6 grid.

Sometimes, the program would not block me when I was one move away from 4 in a line, and let me win.

There are 7 columns, so only 7 possible moves (unless a column is full), the program would look ahead in the game and score each move as a fraction from 0 to 1.

It played the move with the highest score. If more than one move had the highest score, it selected one of the best moves at random.

Seems logical, so why was it throwing the game?

I'm a poor player, the program was looking many moves ahead, and I was looking about 2 moves ahead.

Sometimes I got into a position where I could not lose, if I played perfectly.

The program saw that, and I could not. It scored all 7 moves as 0, and played one at random.

That was an interesting bug.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,285
Latest member
CryptoTaxxSoftware

Latest Threads

Top