Home > Back-end >  Selenium Webdriver module: Keys.UP does not work as expected
Selenium Webdriver module: Keys.UP does not work as expected

Time:02-17

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)
        # ^^^^^^^^^^^

  • Related