I have written a python script that should automatically play the game 2048 (https://play2048.co/).
The problem is: keystrokes seem to be ignored by the browser. Or the program runs too fast for having the browser clicking through the game. I have checked the Selenium documentation and I am not sure if I have to include some explicit waits.
Here is my code:
#! python3
#_2048.py - A program that plays the game 2048 (https://play2048.co/)
# automatically.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
def assess_board():
tileContainer = browser.find_element(By.CLASS_NAME, 'tile-container') # finds the
tile container
tiles = tileContainer.find_elements(By.TAG_NAME, "div[class*='tile-position']") #
finds every tile
for tile in tiles: # maps all values in the board
boardvalues.append(tile.get_attribute('class')[10])
def click(): # Performs a click (changes after every click: UP-RIGHT-DOWN-LEFT)
if start % 4 == 1:
print('up')
Keys.UP
elif start % 4 == 2:
print('right')
Keys.RIGHT
elif start % 4 == 3:
print('down')
Keys.DOWN
elif start % 4 == 0:
print('left')
Keys.LEFT
browser = webdriver.Firefox() # Open Firefox
browser.get('https://play2048.co/') # Go to https://play2048.co/
wait = WebDriverWait(browser, 10)
boardvalues =[]
number_of_clicks = 0
start = 1
while '2048' not in boardvalues:
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".game-container")))
click()
number_of_clicks = 1
start = 1
assess_board()
if len(boardvalues) == 16:
print('You lost!')
print('number of clicks: ', number_of_clicks)
print('2048! You won!')
print('number of clicks: ', number_of_clicks)
The goal of the game is reaching the score 2048 by sliding tiles upon eachother by hitting the arrow keys. The game is over when the square is full and you haven't reached a 2048-tile.
I am not sure what happens during my while loop. The browser seems to ignore the keystrokes of the arrow keys. The tiles are not moved. Every simulated click on an arrow key should move the tiles.
What might be the problem here?
Code update
#! python3
#_2048.py - A program that plays the game 2048 (https://play2048.co/)
# automatically.
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
import time
def assess_board():
tileContainer = browser.find_element(By.CLASS_NAME, 'tile-container') # finds the tile container
tiles = tileContainer.find_elements(By.TAG_NAME, "div[class*='tile-position']") # finds every tile
for tile in tiles: # maps all values in the board
boardvalues.append(tile.get_attribute('class')[10])
def click(): # Performs a click (changes after every click: UP-RIGHT-DOWN-LEFT)
if start % 4 == 1:
print('up')
bodyElem.send_keys(Keys.UP)
elif start % 4 == 2:
print('right')
bodyElem.send_keys(Keys.RIGHT)
elif start % 4 == 3:
print('down')
bodyElem.send_keys(Keys.DOWN)
elif start % 4 == 0:
print('left')
bodyElem.send_keys(Keys.LEFT)
browser = webdriver.Firefox() # Open Firefox
browser.get('https://play2048.co/') # Go to https://play2048.co/
bodyElem = browser.find_element(By.TAG_NAME, 'body')
wait = WebDriverWait(browser, 10)
boardvalues =[]
number_of_clicks = 0
start = 1
while '2048' not in boardvalues:
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".game-container")))
click()
time.sleep(2) # do I need this step?
number_of_clicks = 1
start = 1
assess_board()
if len(boardvalues) == 16:
print('You lost!')
print('number of clicks: ', number_of_clicks)
print('2048! You won!')
print('number of clicks: ', number_of_clicks)
CodePudding user response:
Your click()
function doesn't actually click anything:
def click(): # Performs a click (changes after every click: UP-RIGHT-DOWN-LEFT)
if start % 4 == 1:
print('up')
Keys.UP
# ^^^^^^
...
Your code here is just referencing Keys.UP
object. Instead, you need to find an element and send that key to it:
def click(): # Performs a click (changes after every click: UP-RIGHT-DOWN-LEFT)
# main <body> tag acts as your element that controls the keys
board = browser.find_element_by_css_selector('body')
if start % 4 == 1:
print('up')
board.send_keys(Keys.UP)
# ^^^^^^^^^^^