拉登游戏的C#版本开发功能基本上实现,对于这个游戏而言在没有找到规律或者游戏本身的奥秘之前能够玩到N=15耐心已经很不错了。对于拉登游戏的游戏本意只有一个:通过点击格子,使得格子的颜色全部改变,收集点击的格子进行颜色标志,寻求一种美妙的画面。当然至于画面的中的景物肯能要因人的想象力去发散了。
分布式计算有了解过,没有太多的尝试,有时候时环境限制,也有时候是所接触的问题并不需要超量的计算,对于这个游戏如果想要进行更大的N元格子的寻找结果那么存在的可能性将是2的N次方,使用计算机去寻找花费是时间也是非常巨大的。
尝试用计算机去计算了一组:
计算N=20使用9秒时间,N=26使用1087秒。当然这两个时间仅仅作为参考,应该在运算的过程中计算机运行的状态有很大的不一样,不能比较,但至少能说明一个问题就是N的线性增长带来的是时间上的非线性增长。
上面的图中的[1]表示要点击的格子,如果按照上图的方式去点击则可以一次性完成游戏。对于上述的结果计算可能只是众多结果的中一个,对于N的值不同可能出现不同的结果,比如N为偶数则可能出现对称,N为4的倍数又可能出现不同的情形,还有更多可能例如关于某个点,或者线成中心对称,轴对称。这里的计算结果是第一次出现完成游戏的情形,如果要找出更多的可能性则还需要更多的时间多所有可能性进行计算,面对如此大的计算量(当然这里的计算不存在浮点运算,复杂运算,主要是逻辑判断和循环遍历)。
想要寻找到每种N的取值下关于这样的游戏策略规则下的图案,其程序的算法倒是相当简单然后获取这样的值确实成为了生命障碍,就像密码一样,其实最复杂的还是基于时间上的不可达性。这样的问题摆在面前,而心中对这样的图案充满好奇,这下可好了,欲无止境被发挥到淋漓尽致。
仔细盯着上面的三幅图片还是可以若隐若现的看到一些图案的,1和0的明暗对比还是较为清晰的,想到这不由的赞叹当初将计算机的编码方式基于0和1真是人类历史的重大变革,怎么赞赏都不为过。
对于计算机去计算寻求这个结果的代码如下:
- public class DistributedCompute {
- private int edge;
- private int start;
- private int end;
- private boolean result;
- private boolean[] status;
- private byte[] operator;
- public DistributedCompute(int edge, int start, int end) {
- this.edge = edge;
- this.start = start;
- this.end = end;
- this.result = false;
- }
- /**
- * 初始化变量
- *
- * @return
- */
- public DistributedCompute init() {
- int number = edge * edge;
- status = new boolean[number];
- operator = new byte[number];
- setOriginalValue(number);
- return this;
- }
- private void setOriginalValue(int number) {
- for (int i = 0; i < number; i++) {
- status[i] = false;
- operator[i] = 0;
- }
- }
- /**
- * 根据start和end设置计算策略
- */
- private void setStrategy(int condition) {
- int column = 0;
- int temp = condition;
- while (true) {
- if (temp == 0) {
- break;
- }
- operator[column] = (byte) (temp % 2);
- temp /= 2;
- column++;
- }
- }
- /**
- * 遍历操作实现计算
- */
- private void executeErgodic() {
- //遍历第0行
- for (int column = 0; column < edge; column++) {
- if (operator[column] == 1) {
- changeStatus(column);
- }
- }
- //遍历第[1, edge)行
- for (int row = 1; row < edge; row++) {
- for (int column = 0; column < edge; column++) {
- int index = row * edge + column;
- int top = index - edge;
- if (!status[top]) {
- operator[index] = 1;
- changeStatus(index);
- }
- }
- }
- //设置计算结果
- for (int i = 0, j = status.length; i < j; i++) {
- if (!status[i]) {
- this.result = false;
- break;
- } else {
- this.result = true;
- }
- }
- }
- /**
- * 改变状态数组元素的状态
- *
- * @param index
- */
- private void changeStatus(int index) {
- status[index] = !status[index];
- changeFourSidesStatus(index);
- }
- /**
- * 改变状态数组的上下左右元素转台
- *
- * @param index
- */
- private void changeFourSidesStatus(int index) {
- int row = index / edge;
- int column = index % edge;
- int top = row - 1;
- int buttom = row + 1;
- int left = column - 1;
- int right = column + 1;
- if (top >= 0) {
- int rowcolumn = top * edge + column;
- status[rowcolumn] = !status[rowcolumn];
- }
- if (buttom < edge) {
- int rowcolumn = buttom * edge + column;
- status[rowcolumn] = !status[rowcolumn];
- }
- if (left >= 0) {
- int rowcolumn = index - 1;
- status[rowcolumn] = !status[rowcolumn];
- }
- if (right < edge) {
- int rowcolumn = index + 1;
- status[rowcolumn] = !status[rowcolumn];
- }
- }
- /**
- *
- * 执行计算
- *
- *
- * @return
- */
- public DistributedCompute executeCompute() {
- for (int i = start; i < end; i++) {
- setOriginalValue(edge * edge);
- setStrategy(i);
- executeErgodic();
- if (this.result) {
- break;
- }
- }
- //清理内存
- Runtime.getRuntime().gc();
- return this;
- }
想要获取N取值下的所有可能的结果值则需要将上述代码中的executeCompute()去掉break跳出循环。
面对这样的计算机能够处理,人却没法等待下去的问题正是分布式计算存在的一种体现。维基百科中解释分布式计算:分布式计算是一种把需要进行大量计算的工程数据分区成小块,由多台计算机分别计算,在上传运算结果后,将结果统一合并得出数据结论的科学。目前常见的分布式计算项目通常使用世界各地上千万志愿者计算机的闲置计算能力,通过互联网进行数据传输。面对目前个人计算机资源相对过剩,却利用率不高的情况下去计算寻找这个游戏背后的美丽图案倒是一个非常诱人的想法和做法。在有限的时间,在有限的计算机资源,在有限的占有志愿者的计算机资源的前提下开始行动,希望能够在尽快的看到美丽的想象中的大抵确实存在的图案。
下面贴出JVM摘要图:
写到这里目前的运算结果还没有出来,当然这么短的时间内是不可能出来的,神秘的图案是迟迟的来,必须苦死等待她的人。