摘要:
这阵子造了个轮子,用于方便地入库,项目地址:https://github.com/chncwang/easy2db该写的README上都写了,这里就不废话了~ 阅读全文
摘要:
2048 A.I. 在 stackoverflow 上有个讨论:http://stackoverflow.com/questions/22342854/what-is-the-optimal-algorithm-for-the-game-2048得票最高的回答是基于 Min-Max-Tree + a... 阅读全文
摘要:
随着对FoolGo优化的进行,每次落子时重复计算棋盘的zobrist哈希值成为眼见的性能热点之一,须要修改成增量计算。 需要一个结构来表示落子前后,棋盘状态的变化:class BrdChange{public: template <typename T> struct Change { T origin_, now_; }; struct Pair { PointIndex indx_; Change<Point> pnt_; ... }; ...private: Change<Point... 阅读全文
摘要:
这几天把围棋A.I.最后的部分写好了,9路小棋盘上看上去运行得还不错,更名为FoolGo。先讲一下UCT博弈树的实现。 鉴于FoolGo的MC模拟速度和棋盘对象的大小,如果直接用树结构实现,用不了几分钟,我的MBP的4G内存就会被棋盘挤爆。所以要通过置换表实现博弈树。 哈希算法当然是zobrist哈希。如果哈希值的类型是uint32_t的话,不同棋局哈希冲突的概率就是1 / ~(uint32_t)0——可以认为不同的哈希值意味着不同的棋局。不用自己写哈希表,C++11新增有标准容器unordered_map,很含蓄的名字,就是哈希表。 zobrist哈希值可以增量计算,不过实现起来有... 阅读全文
摘要:
有了棋串的数据结构后,落子就变得很高效了,接下来要生成随机棋步。 以9x9棋盘为例,直接生成0~80的随机数进行模拟会很低效,因为它们并不都是合法落子点——有3类落子点是非法的:1. 非空点 2. 劫争点 3. 自杀点。 自然想在模拟过程中增量维护这3类点集,前两类很容易维护,难点在于自杀点的增量维护。 着手写自杀点的维护后,才发现问题出乎意料的复杂。我先写了个IsSuiside函数,通过试下作为最终的裁决,而这又涉及到对象的拷贝,太过昂贵。于是想尽量少用,通过位运算来判定多数情况。然后随着测试的进行,陆续发现多处的位运算判定不可靠,不得不用IsSuiside函数替代…… 最后的效... 阅读全文
摘要:
Monte Carlo局面评估+UCT博弈树搜索是现代计算机围棋的主流。这种方法对算法的效率有很高要求,因此须要在Mone Carlo模拟过程中保存棋串(直线相连的同色棋子集合)信息,提高落子效率。 棋串须要满足以下需求:频繁查询某棋子所在的“棋串”。频繁创建棋串。频繁查询棋串的“气”。频繁合并两棋串。移除棋串,并枚举其中的棋子。 因此用链表实现的并查集是很合适的数据结构:struct Node { PointIndex next_, list_head_;};struct List { PointIndex tail_, len_; AirSet air_set_;... 阅读全文
摘要:
Lua也可以调用C函数,只是以更加崎岖的方式——通过一个私有栈来传递参数和返回值。提供给Lua API的C函数都是这个样子的:static int sum(lua_State *L){ int a = lua_tonumber(L, -1); int b = lua_tonumber(L... 阅读全文
摘要:
在Lua的官方C API中,Lua与C通过一个虚拟栈来交互数据。例如有个a.lua的文件中有求和函数:function sum(a, b) return a + bend要在C代码中打开lua文件,并调用求和函数,大致要这样写:lua_State *s = luaL_newstate();lu... 阅读全文
摘要:
以前介绍过一些vim插件,有两个插件是方便写iOS程序的,即cocoa和objc_matchbracket(以下称objc_mb)。cocoa插件主要用来补全cocoa框架的API名,objc_mb则用来自动补全中括号。不过这两个插件都不支持后缀.mm的objective-C++文件,需要做一些改动。在vim中运行1 :e $VIMRUNTIME/filetype.vim发现vim收集的文件类型还挺全的,连.mm文件是objcpp都知道……于是让插件支持objcpp类型就行了。1) cocoa插件:打开~/.vim/plugin/cocoa.vim,有如下一段:1 au FileType ob 阅读全文
摘要:
通常而言,ios中涉及IO的操作是多线程的,而不会在主线程中完成,这是为了避免耗时过长IO操作卡住主线程。但某些时候,我们希望让主线程等待IO操作完成——例如主线程创建了一个文件夹后,等待完成,再往文件夹中创建文件。 NSObject类有一个方法performSelectorOnMainThread:withObject:waitUntilDone可以让主线程挂起,但selector至多只能带一个可传参数,这时需要用到NSInvocation类来解决这个问题。 代码如下:- (void)createRecordDirectoryBlockingMainThread{ NSF... 阅读全文