Learn to Code via Tutorials on Repl.it!

← Back to all posts
lets make a bot :) (python) series part 2 TIC-TAC-TOE
h
generationXcode (530)

😎💻 bots r cool

intro

Hi and welcome to this tutorial. We are all disturbed kids and adults here who are very lonely and have nothing but coding with us. We are so lonely that we have nobody to play tictactoe with so we are going to code a bot to play it for us

Now I am not going to ruin the surprise as to where we are going with this series (the next part is the final and the toughest bit...)

Today we are making a bot to play tic tac toe. If you guys are confused as of how to build it you can look at the tic tac toe code I wrote and if you want I can make a tutorial on react js (what I used to make the tic tac toe webpage)

We arent giving it any skill or anything NONONO WE CANT LET IT TAKE OVER THE WORLD OH NO WE CANT STOP STOP STOP. We are going to make it play tic tac toe randomly.

I wrote out the webpage at https://tictactoe--generationxcode.repl.co/ if you want to play. if you're lonely like me you will want to continue through this tutorial and make something to play it for you.

the code for tic-tac-toe bot

Lets hit the road and make something OH YEAH!!!!!

importing stuff


Buh this the most repitive bit but for ppl who are new to this series HERE YOU GO! TAKE THAT CODE SMASH IT! CRUSH IT! MAKE IT BETTER :

from selenium import webdriver
import time
from random import randint

Now we have 2 extra imports for this program...
why?

  • time is used so that we can actually see the bot playing tic tac toe or else it will just open the browser play it withing a few seconds and close it. We dont want that so we are going to add some small waiting time between each play and after it ends so we can see the results
  • randint from random - this is for randomly selecting a tile and clicking on it

starting up the driver

this is short for webdriver. If you are new here, go back one tutorial to - https://repl.it/talk/learn/Lets-make-a-python-bot-part-1-for-beginners/43284 if you dint understand a lot of what I'm saying :)

now here the link is different so this is the code you will be putting in:

URL = "https://tictactoe--generationxcode.repl.co/"

driver = webdriver.Firefox(executable_path = '[path]/geckodriver-v0.26.0-win64/geckodriver.exe')

driver.get(URL)

ok now we have got the page up and running

get the tic tac toe elements

Last tutorial I didnt explain the getting the path of the elements very well so I mean to patch that gap in this one. This is how:

right click on the element and click on "inspect element", then right click on the element in the devtools that just opened. then hover on copy, that opens a list of actions, click on "copy xpath".

For this one I have yall covered and I copied all the xpaths for you, but if you want you can do that yourself :)

row1_cell1=driver.find_element_by_xpath('//*[@id="root"]/div/div[1]/div[1]')
row1_cell2=driver.find_element_by_xpath('//*[@id="root"]/div/div[1]/div[2]')
row1_cell3=driver.find_element_by_xpath('//*[@id="root"]/div/div[1]/div[3]')

row2_cell1=driver.find_element_by_xpath('//*[@id="root"]/div/div[2]/div[1]')
row2_cell2=driver.find_element_by_xpath('//*[@id="root"]/div/div[2]/div[2]')
row2_cell3=driver.find_element_by_xpath('//*[@id="root"]/div/div[2]/div[3]')

row3_cell1=driver.find_element_by_xpath('//*[@id="root"]/div/div[3]/div[1]')
row3_cell2=driver.find_element_by_xpath('//*[@id="root"]/div/div[3]/div[2]')
row3_cell3=driver.find_element_by_xpath('//*[@id="root"]/div/div[3]/div[3]')

Now that thats done we need these in an array. This is what I did:

elements = [row1_cell1,row1_cell2,row1_cell3,row2_cell1,row2_cell2,row2_cell3,row3_cell1,row3_cell2,row3_cell3]

getting the cell that tells us when to leave

Once X or O has won we got to yeet(leave) out of the browser
here is the element for winning:

winner=driver.find_element_by_xpath('//*[@id="root"]/p/b')

now that we got that lets go to the fun stuff

clicking a random element

We have to randomly click an element, however we cant click one thats been clicked before so this is how we are going to do it:
we are going to write a function for clicking the element and call it random_click. If the element has already been clicked (we will know this by going through a list of already clicked element indexes(their positions in the element array we just created)) we will run the function again from inside the function. We are going to call the subroutine from itself.

My computer teacher has told me not to do this cus it reduces the speed of the program but Ima do it anyway lol.

here is the code:

def random_click():
    random_element = randint(0,8) 
    for i in clicked:
        if i == random_element:
            random_click()
        else:
            clicked.append(random_element)
    elements[random_element].click()

oki now we done with that bit lets get to the MOST BORING BIT

clicking it

now we are going to run a loop to click on the tic tac toe randomly using the function we created before
This seems quite straightforward right? IT ISNT NOTHING IN LIFE IS OK? SO JUST STOP THINKING IT IS EVERYONE IS MEAN AND EVERYTHING IS BAD... jkjk lololol
the bad bit is that we have to stop the program when one of the players win (X or 0)
that we will understand by checking whether the text in the winner element (look up in the tutorial) is the same or is saying that X or O has won

Any normal person will run this loop for 8 times but me? I am a disturbed and dumb idiotic coder so me do it for 20 times because why not?

here is the code:

for i in range(0,20):
    if(winner.text == "X"):
        time.sleep(2)
        print("x won")
        winning="x"
        break
    elif(winner.text == "O"):
        time.sleep(2)
        print("O won")
        winning = "O"
        break
    else:
        time.sleep(0.25)       
        random_click()

now we got that done

printing out the winner:

we already do this but for any winner to make the loser feel uncomfortable and hurt and sad and make them sob till they quit they have to say they have won many, many , many more times than any sane human. So this is how we do it:

print(winner.text)

this gets the text inside the winner element

closing the browser

all insane idiotic things must end even if they are bots - me(graph egg)

we got to finish this sickness now after we have made it. BUT HOW? AND WHY? to the second question I answer - why not? (checkmate) and to the first , here the code:

time.sleep(3)
driver.close()

we need some time for the browser to sleep before dying. GOVE IT SOME REST BEFORE ETERNAL REST OK?

THATS IT!!!

the end

I hope you learnt something from this tutorial and I hope all yall are safe in your homes away from the madness of 2020. And thats the end of my disturbing tutorial. You must be thinking, when WILL this mad idiot STOP? to be honest idk rlly. But I hope not very soon.

also do all this locally, doesnt work in replit

https://youtu.be/WFjz-NEP7WY

the bot in action ^

all the code:

from selenium import webdriver
import time
from random import randint
URL = "https://tictactoe--generationxcode.repl.co/"

driver = webdriver.Firefox(executable_path = '[path]/geckodriver-v0.26.0-win64/geckodriver.exe')
driver.get(URL)

row1_cell1=driver.find_element_by_xpath('//*[@id="root"]/div/div[1]/div[1]')
row1_cell2=driver.find_element_by_xpath('//*[@id="root"]/div/div[1]/div[2]')
row1_cell3=driver.find_element_by_xpath('//*[@id="root"]/div/div[1]/div[3]')

row2_cell1=driver.find_element_by_xpath('//*[@id="root"]/div/div[2]/div[1]')
row2_cell2=driver.find_element_by_xpath('//*[@id="root"]/div/div[2]/div[2]')
row2_cell3=driver.find_element_by_xpath('//*[@id="root"]/div/div[2]/div[3]')

row3_cell1=driver.find_element_by_xpath('//*[@id="root"]/div/div[3]/div[1]')
row3_cell2=driver.find_element_by_xpath('//*[@id="root"]/div/div[3]/div[2]')
row3_cell3=driver.find_element_by_xpath('//*[@id="root"]/div/div[3]/div[3]')

winner=driver.find_element_by_xpath('//*[@id="root"]/p/b')
print(winner.text)

elements = [row1_cell1,row1_cell2,row1_cell3,row2_cell1,row2_cell2,row2_cell3,row3_cell1,row3_cell2,row3_cell3]
clicked = []
winning = ""
time.sleep(10)
def random_click():
    random_element = randint(0,8) 
    for i in clicked:
        if i == random_element:
            random_click()
        else:
            clicked.append(random_element)
    elements[random_element].click()

for i in range(0,20):
    if(winner.text == "X"):
        time.sleep(2)
        print("x won")
        winning="x"
        break
    elif(winner.text == "O"):
        time.sleep(2)
        print("O won")
        winning = "O"
        break
    else:
        time.sleep(0.25)       
        random_click()
time.sleep(2)        
print(winning)
print(winner.text)

time.sleep(3)
driver.close()

Thats it for today and happy coding


^ that's me right there, no a bit to the side now a bit right - yes! Right there in the middle!

Comments
hotnewtop
adl212 (172)

@generationxcode will selenium work on this because I'm pretty sure selenium doesn't work on repl.it

generationXcode (530)

@adl212 it wont work on repl.it I wuld reccoment doing it all locally. Its shown in the last tutorial how to set it up :) and error you're getting is probs one that I've got too, so ask if you dont understand something

generationXcode (530)

wait... someone just told me that there is a browser in replit let me check up on it, then I'll share the repl link here :)

adl212 (172)

@generationXcode Yeah, webbot on repl.it works.

generationXcode (530)

@adl212 can you link the repl? thanks!

adl212 (172)

@generationXcode I can do this sometime tomorrow

adl212 (172)

@generationXcode I'm not really sure how to use webbot to do it though. The documentation for webbot is here.

adl212 (172)

@generationXcode I have created a script that will work for tic tac toe. It is usable on repl.it so that anyone that finds this page can use it on repl.it. the link is tictactoebot. The code is

from webbot import Browser
from bs4 import BeautifulSoup
import time
from random import randint
#connect to the browser
driver = Browser()
URL = "https://tictactoe--generationxcode.repl.co/"
#go_to function to open a tab to the url
driver.go_to(URL)
#the xpaths of all the buttons to click
row1_cell1 = '//*[@id="root"]/div/div[1]/div[1]'
row1_cell2 = '//*[@id="root"]/div/div[1]/div[2]'
row1_cell3 = '//*[@id="root"]/div/div[1]/div[3]'
row2_cell1 = '//*[@id="root"]/div/div[2]/div[1]'
row2_cell2 = '//*[@id="root"]/div/div[2]/div[2]'
row2_cell3 = '//*[@id="root"]/div/div[2]/div[3]'
row3_cell1 = '//*[@id="root"]/div/div[3]/div[1]'
row3_cell2 = '//*[@id="root"]/div/div[3]/div[2]'
row3_cell3 = '//*[@id="root"]/div/div[3]/div[3]'
#list to call to get all the buttons to click
elements = [row1_cell1,row1_cell2,row1_cell3,row2_cell1,row2_cell2,row2_cell3,row3_cell1,row3_cell2,row3_cell3]
def random_click():
    while True:
        try:#try to check if elements exist
            element = randint(0, len(elements))
            driver.click(xpath=elements[element], classname="cell", id='', tag='div')
            del elements[element]
            break
        except IndexError:#if there is an IndexError, keep get another number for the element
            continue
for x in range(0, 9):
    random_click()
    time.sleep(0.05)
#get html of the site to get who won
winner = driver.get_page_source()
#use BeautifulSoup to parse the info 
soup = BeautifulSoup(winner, 'html.parser')
print(soup.p.text)
print(soup.b.text)
generationXcode (530)

@adl212 ooooh nice... I cant use this for the next part of my tutorial tho. You'll see why then. But this is very helpful. Thanks!

adl212 (172)

@generationXcode Ok, I'll look forward to looking at your next tutorial!

generationXcode (530)

@adl212 me too. The program is crashing everything I run it on. Now me going industrial grade. Using aws. Lets hope it works there

generationXcode (530)

@adl212 yup nope. It seems to have crashed everything I put it on. So its really of no use. Sad. I worked on this for the whole of this week. I guess I can move to julia now.

generationXcode (530)

Thats the tutorial for today!