使用Selenium自动玩2048
前几天看summer师弟玩Selenium感觉挺有意思。便拿着时间风靡一时的游戏“2048”来练手,写了个简单的 AI。甚是欢乐!
Selenium
啥是selenimu,简单的说——Selenium也是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE、Mozilla Firefox、Mozilla Suite等(来自 http://www.51testing.com/zhuanti/selenium.html)。
selenimu这里就不多介绍了,细节请看 selenium 的 python api 文档
2048策略
2048这个游戏地球人都知道就不介绍了。主要介绍下我的AI。我的AI对于每一个方向的评估有三个方面
- 移动导致合并的得分 score:这个就是游戏本身定义的得分,如 4和4合并得8分,128和128合并的256分
- 移动后每一行每一列的单调性 monotone:对于每一行(每一列)如果 line[i] <= line[i+1]则mon+= line[i]+line[i+1]否则,mon-=line[i]+line[i+1],monotone=sum(abs(mon))
- 移动后相邻块值相同的情况 adjoin:任意两个相邻块的值相同,如cells[i][j]=cells[i+1][j],则 adjoin+=cells[i][j]
最后的估值 estimation = score + monotone * 0.3 + adjoin。对于上下左右四个方向取estimation最大的方向操作
这种方法还可以,运气好的话,可以得到2048
程序结构
程序的源代码如下:
from selenium import webdriver from selenium.webdriver.common.keys import Keys import os import time size = 4 class Estimator: def estimate(self, precells, postcells, action, score): for i in range(size): score += self.__estimate_line([postcells[i][j] for j in range(size)]) score += self.__estimate_line([postcells[j][i] for j in range(size)]) return score def __estimate_line(self, line): monotone, adjoin = 0, 0 for i in range(size - 1): if line[i + 1] > line[i]: monotone += line[i + 1] + line[i] else: monotone -= line[i + 1] + line[i] if line[i + 1] == line[i]: adjoin += line[i] return abs(monotone) * .3 + adjoin class Auto2048: def __init__(self, url, estimator): self.browser = webdriver.Firefox() self.browser.get(url) self.estimator = estimator def get_cells(self): tiles = self.browser.find_elements_by_class_name('tile') self.cells = [[0 for i in range(4)] for i in range(4)] for tile in tiles: attr = tile.get_attribute('class').split() value = int(attr[1].split('-')[1]) x = int(attr[2].split('-')[3]) - 1 y = int(attr[2].split('-')[2]) - 1 self.cells[x][y] = value def AI(self): self.get_cells() self.Print(self.cells) action, actionname = '', '' moveable = False strategies = [ {'fun': self.try_up, 'action': Keys.UP, 'name': 'Up'}, {'fun': self.try_down, 'action': Keys.DOWN, 'name': 'Down'}, {'fun': self.try_left, 'action': Keys.LEFT, 'name': 'Left'}, {'fun': self.try_right, 'action': Keys.RIGHT, 'name': 'Right'}] for strategy in strategies: result = strategy['fun']() estimation = self.estimator.estimate(self.cells, result['cells'], strategy['name'], result['score']) if result['moveable'] and (moveable == False or max_estimation < estimation): action = strategy['action'] max_estimation = estimation moveable = True actionname = strategy['name'] if not moveable: return False self.browser.find_element_by_class_name('grid-container').send_keys(action) print 'Action: ', actionname return True def move_left(self, cells): moveable = False score = 0 for x in range(size): pre = 0 for y in range(size): if cells[x][y]: cells[x][pre] = cells[x][y] if y != pre: moveable = True cells[x][y] = 0 pre += 1 for y in range(size - 1): if cells[x][y] and cells[x][y] == cells[x][y + 1]: cells[x][y] += cells[x][y] score += cells[x][y] cells[x][y + 1] = 0 moveable = True pre = 0 for y in range(size): if cells[x][y]: cells[x][pre] = cells[x][y] if y != pre: moveable = True cells[x][y] = 0 pre += 1 return {'moveable': moveable, 'score': score, 'cells': cells} def try_left(self): cells = [[self.cells[i][j] for j in range(size)] for i in range(size)] return self.move_left(cells) def try_right(self): cells = [[self.cells[i][size - 1 - j] for j in range(size)] for i in range(size)] result = self.move_left(cells) result['cells'] = [[result['cells'][i][size - 1 - j] for j in range(size)] for i in range(size)] return result def try_up(self): cells = [[self.cells[j][i] for j in range(size)] for i in range(size)] result = self.move_left(cells) result['cells'] = [[result['cells'][j][i] for j in range(size)] for i in range(size)] return result def try_down(self): cells = [[self.cells[size - 1 - j][i] for j in range(size)] for i in range(size)] result = self.move_left(cells) result['cells'] = [[result['cells'][j][size - 1 - i] for j in range(size)] for i in range(size)] return result def __del__(self): self.browser.close() def Print(self, cells): print for x in range(size): for y in range(size): print '%5d' % cells[x][y], print if __name__ == '__main__': url = 'file://' + os.path.abspath('2048/index.html') # url = "http://gabrielecirulli.github.io/2048/" auto2048 = Auto2048(url, Estimator()) while auto2048.AI(): time.sleep(0.2) time.sleep(10)
源代码中有两个类
主逻辑类 Auto2048
使用 2048的url和估值类(AI逻辑)构造。测试过程中,用 wget 将 "http://gabrielecirulli.github.io/2048/" 的所有页面抓到本地分析(由于不懂js在网页中的工作原理,使用find_elements_by_class_name找当前cells的信息找了好久)
每一次操作调一次AI(),AI() 先获取当前页面的状态保存在 self.cells 中,然后对上下左右四个方向枚举,取估值最大的方向并使用send_keys进行操作。如果能操作则AI()返回True,否则返回False
估值类 Estimator
估值类只要实现 def estimate(self, precells, postcells, action, score): 估值方法即可。其中,precells为操作前状态,postcells为操作后状态,atcion为操作['Left', 'Right', 'Up', 'Down'],score为操作得分。返回值为估值estimation,值越到越好。
虽然我的估值方法运气好的话可以得到2048,但还是很粗糙的。你要有兴趣的话,可以写一个更好的Estimator得到更高的分。
2021年3月02日 20:00
Nice post. I was checking constantly this blog and I am impressed! Extremely helpful information specially the last part I care for such info a lot. I was seeking this particular information for a very long time. Thank you and good luck. 123 movies
2022年9月19日 00:11
Geography is an important subject in Class 10t. However, considerable ambiguities persist in its exact position within academia. AP 10th Geography Question Paper As an inclusive discipline, the content of geography is derived from various subjects in the sciences, social sciences and humanities. This is equally true about the geography syllabus in schools as well.Telugu Medium, English Medium & Urdu Medium Students of the State Board can download the AP 10th Geography Model Paper 2023 Pdf with answers for all exam formats conducted by BSEAP for Part-A, Part-B, Part-C, and Part-D exams of SA-1, SA-2, FA-1, FA-2, FA-3, FA-4 along with Assignments which were designed by subject experts of leading educational institutes.
2023年1月09日 13:06
With Selenium, you can automatically play 2048 by opening up the game in your browser real estate Algona and then using Selenium to control the game. This can be done by opening up the game in your browser, and then using Selenium to click on the tiles and make the moves.
2023年4月23日 14:29
Find the relavant home / business based BSNL high speed broadband plans in UP East telecom delivering the best internet over copper / coaxial/ optical fiber network broadband services at lowest charges, Verify the low cost suitable unlimited. We 99-networks have a different Policy for its services and these are the important Policies concerns that are considered for using the website. Customers can anytime check this Privacy Policy listed on the website so 99-networks.com that they can be assured how their data is being used by the website. In the same manner.