您的位置:首页 > 编程语言

关灯游戏 Lights out (一)(极速求解)

2017-01-12 08:35 926 查看
关灯游戏(Lights Out)

      关灯游戏是Tiger Electronics在1995年发行的一款电子游戏,Parker Brothers在上世纪70年代发布过一款规则与此类似的3×3的游戏, Vulcan Electronics在1983年也生产过与此类似的游戏,名称为XL-25。

      目前这款游戏的中文名很混乱,网上可见“开关灯游戏”、“灭灯游戏”、“开灯游戏”、“熄灯游戏”、“点灯游戏”、“灯阵游戏”、“地板游戏”...虽然意思都差不多,但名称不统一,不利于学术研究和搜索。在维基百科里(https://en.wikipedia.org/wiki/Lights_Out_(game)),这款游戏的英文名称为:“Lights
Out”,可翻译为“关灯游戏”。

      关灯游戏规则非常简单,在一个M×N阵列里,有若干盏灯亮着(可以全部都亮着),点击任意一盏灯(不管此灯是亮着还是灭着,都可以点),那么该灯以及与该灯相邻的上、下、左、右共五盏灯都同时会变成与自身相反状态,即亮的变灭,灭的变亮(由于边角的特殊性,点击边上的灯,只有四盏灯一起变化;点击角上的灯,只有三盏灯一起变化)。

      游戏的目标是:通过点击灯阵一些灯,使得灯阵上所有灯都熄灭。

      来看维基的一张游戏示意图:



      上图是一个5×5正方形灯阵,初始状态只有左上角一盏灯亮着;第一次点击右下角灯,则右下角三盏灯全部变亮;第二次点击右下角斜边第二个盏灯,结果如最后一个图所示(此时局面还有灯亮着,游戏并未结束)。
      关灯游戏规则虽然简单,但玩起来颇有难度。于是众多程序猿想到用计算机求解。常规解法是线性代数解法,这个有点数学含量。
      线性代数解法的优点很多,不单可以求解M×N任意阵列灯阵,而且对灯阵任意初始状态也能求解,是个不错的方法。不过,线性代数解法的缺点也是明显的,代码比较复杂,时间复杂度也降不下来,当灯数量很多时,就很难在有限时间内求解了。

      线性代数解法原理,网上已经有了,在这里就不介绍了。这里介绍笔者找到了一个速度超快的算法,求解511×511灯阵(初始状态全亮)耗时不到1秒,速度极快!算法很简单,就是只点击局面未亮的灯,一直找到解法为止。但笔者这个解法缺点也很明显,就是无法求解任意阵列关卡。
     代码如下(C/C++):

#include<stdio.h>  /*关灯游戏求解代码(只求解初始状态全亮灯阵)*/
#define M 15       /*M等于灯阵行数*/
#define N 31       /*N等于灯阵列数*/
int main(void)
{/*M、N值须符合1, 2, 3, 5, 7, 11, 15, 23, 31, 47, 63, 95, 127, 191, 255, 383, 511...数列规律*/
int a[M+2][N+2]={0},b[M+2][N+2]={0},i,j,k=1;
while (k)
{
for(i=0;++i<=M;)
for(j=0;++j<=N;)
if(!a[i][j])b[i][j]^=1,a[i][j]^=1,a[i][j+1]^=1,a[i][j-1]^=1,a[i+1][j]^=1,a[i-1][j]^=1;
for(i=k=0;++i<=M;)
for(j=0;++j<=N;)if(!a[i][j])k=1;
}
for(i=0;++i<=M;printf("\n"))
for(j=0;++j<=N;)printf("%2d",b[i][j]);
return 0;
}


例如调整M=N=11,程序输出为:



      笔者这个解法只求解初始状态全都亮的灯阵,可以求解的正方形灯阵阶数为:
      1, 2, 3, 5, 7, 11, 15, 23, 31, 47, 63, 95, 127, 191, 255, 383, 511, 767, 1023, 1535, 2047, 3071, 4095, 6143, 8191, 12287...

      这个数列的通项公式为:a(2n) = 2*2^n - 1,a(2n+1) = 3*2^n - 1

      符合这个数列阶数的正方形灯阵,都可以求解,另外,4阶也可以求解。
      在“整数数列线上大全”(https://oeis.org/)网站上,这个数列编号为:A052955

      具体网址:
      https://oeis.org/search?q=7%2C11%2C15%2C23%2C31%2C47%2C63%2C95%2C127%2C191%2C255%2C383%2C511+&sort=number&language=&go=Search
      上面程序还可以求解一些矩形灯阵,对矩形的边有如下要求:

      1、当M等于1时,N值等于上面数列任意一个数值的矩阵均可求解;

      2、当M和N的关系为下面规律数值时,M×N矩阵均可求解:

M值137153163127255...
N值37153163127255511...
      对上面程序点评:
      优点:程序简单,速度极快
       缺点:只能求解特殊规格矩阵,作用有限。       
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息