山楂串求解器

最近很火的山楂串小游戏,游戏链接http://www.wesane.com/game/848/,是一个合成类的小游戏,游戏截图如下所示。这个游戏我曾经打到过31串。作为一名程序员,一个自然而然的问题就是,能否写一个山楂串求解器打出更高的分数。编写这样一个求解器大概相当于leetcode中等难度的题目,但是我想从更多的角度来看这个问题。

111.jpg
222.jpg

我的第一版代码是用python写的,算法就是简单的暴力求解+剪枝,包括测试代码在内也就200行出头。但是我遇到了第一个问题:程序的性能太低了,完成一次4步运算需要的时间为20s左右。这个时间是不可忍受的,我的期望值是做到秒的量级。于是我进行了第一步改进:多线程。但出乎我意料的是,python多线程的性能反而降低了。性能数据显示,python并没有完全做到多线程。在网上搜索之后,我发现问题出在python解释器的GIL上。这是一个全局锁,每个线程只有抢到这个锁之后才能执行,从而造成了运行时间不降反升。于是我开始尝试突破GIL,一个直观的方法就是换一个支持多线程的python解释器,我选择了jython,Jython是用java写的python解释器。实际测试结果不理想,除了要忍受jython较长的启动时间,实际运算时间在12s左右,这离我的期望还是很远。

随后我开始考虑换用其他编程语言来完成这件事,我想到了lua,号称具有python的便利性和接近C的性能。于是我用lua语言重写了相关代码。Lua的单线程测试结果为4s,这个结果到达了我的接受范围。在此基础,我再次尝试编写多线程的代码。但是我惊奇的发现,lua也不支持多线程,而是支持所谓的协程,其效果与python类似,也是抢占式的执行。

事已至此,我决定编写C++的代码,此前觉得C++的代码有些难写,因此一直回避。但为了性能,还是需要C++的帮助。我用C++重写了单线程代码,在使用了-O2的编译选项之后,C++的测试结果达到0.2s。这个结果反而再次令我陷入了沉思,因为在这个基础上进行多线程扩展,可能已经没有多少性能可以继续挖掘了。

在实现CPP的多线程版本时,发了几个问题。一个是thread对象不能被push进vector,只好用thread数组加flag的方式实现。二是多线程的时间测量是个问题,测出来的时间是所有子线程时间的总和,这里用std::chrono::system_clock::now()来统计墙上时间。三是直接启动了30个线程,如果能控制系统中一直有8个线程可能性能会更好的一点。最终可以在0.05s内计算4步。

这个项目到此并没有结束,我还想继续挖掘。

  1. 能否实现在python中调用该C++代码?

  2. 能否实现OCR和鼠标点击自动打游戏?

  3. 使用强化学习或者深度学习效果如何?

  4. 能够完成图形界面,提供更好的游戏体验?

相关代码已经在github开源https://github.com/ExquisiteFunction/shanzhachuan ,希望有大佬一起来继续挖掘这个小游戏带来的技术力。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容