独立钻石棋

独立钻石棋也叫独立钻石

独立钻石棋_第1张图片

独立钻石源于18世纪法国的宫廷贵族,是一种自我挑战的单人棋游戏,可以锻炼逻辑思维能力。游戏玩法似中国跳棋,但不能走步,只能跳。棋子只能跳过相邻的柜子到空位上,并且把被跳过的柜子吃掉。棋子可以沿格线横、纵方向跳,但是不能斜跳,剩下越少棋子越好。它与中国人发明的“华容道”,匈牙利人发明的“魔方”并称智力游戏界的三大不可思议之一。
玩法是在棋盘33孔中,每孔都放下一棋,但是取中心的一孔是空着的。玩的时候是像跳棋一样行子。一棋子依直线在平行或垂直(不能依斜线)的方向跳过一棋子,而放在此棋子之后的一个空格内。故此,棋子后必要有空的孔才可跳过。每次棋子跳去一个空孔,被跳过的棋便移离棋盘。这时棋盘上便少了一只棋子。如此一直玩下去,使剩下来的棋子越少越好。

独立钻石的棋盘有很多种变形,这个棋盘就是最初的样子,走法就是按照跳棋的走法,但是被跳过的棋子全部被吃掉,这样每跳一下棋盘上的棋子就会少一颗,而如果像跳棋那样连跳,每步就可能吃掉很多颗棋子。游戏的目的是要使棋盘上留下来的棋子越少越好。如果最后剩一子,而且正好位于棋盘正中心的第44号洞孔上,那就是最好的结果。此种局势称为“独立(粒)钻石”。之所以把这种游戏取上这一名称,是因为人们喜爱“金鸡独立”,视为祥瑞之故。


APK下载:点击打开链接

代码:

#include<iostream>
using namespace std;

int sum(int list[][7])			//sum函数用来返回最后剩余多少个棋子
{
	int sum = 0;
	for (int i = 0; i < 7; i++)for (int j = 0; j < 7; j++)sum += list[i][j];
	return sum - 33;
}

void up(int list[][7], int i, int j)	//跳过(i,j)往上跳
{
	list[i - 1][j] ++;
	list[i][j] --;
	list[i + 1][j] --;
}

void down(int list[][7], int i, int j)	//跳过(i,j)往下跳
{

	list[i + 1][j] ++;
	list[i][j] --;
	list[i - 1][j] --;
}

void left(int list[][7], int i, int j)	//跳过(i,j)往左跳
{

	list[i][j - 1] ++;
	list[i][j] --;
	list[i][j + 1] --;
}

void right(int list[][7], int i, int j)	//跳过(i,j)往右跳
{

	list[i][j + 1] ++;
	list[i][j] --;
	list[i][j - 1] --;
}

bool move(int list[][7])		//找出任何可以跳的一步,并跳,跳完之后递归调用move(),直到不能再跳
{
	if (sum(list) < 4)return true;		//当得到一种只剩下3颗棋子的方法,程序结束
	for (int i = 1; i < 6; i++)for (int j = 0; j<7; j++)
	{
		if ((i == 3 || j>1 && j < 5) && list[i][j] == 2)
		{
			if (list[i - 1][j] == 1 && list[i + 1][j] == 2)	//满足往上跳的条件
			{
				up(list, i, j);
				if (move(list))
				{
					cout << i << j << "up  ";
					return true;
				}
				down(list, i, j);	//恢复list和result
				list[i][j] += 2;
			}
			else if (list[i - 1][j] == 2 && list[i + 1][j] == 1)//满足往下跳的条件
			{
				down(list, i, j);
				if (move(list))
				{
					cout << i << j << "down  ";
					return true;
				}
				up(list, i, j);
				list[i][j] += 2;
			}
		}
	}
	for (int i = 0; i < 7; i++)for (int j = 1; j < 6; j++)
	{
		if ((j == 3 || i>1 && i < 5) && list[i][j] == 2)
		{
			if (list[i][j - 1] == 1 && list[i][j + 1] == 2)//满足往左跳的条件
			{
				left(list, i, j);
				if (move(list))
				{
					cout << i << j << "left  ";
					return true;
				}
				right(list, i, j);
				list[i][j] += 2;
			}
			else if (list[i][j - 1] == 2 && list[i][j + 1] == 1)//满足往右跳的条件
			{
				right(list, i, j);
				if (move(list))
				{
					cout << i << j << "right  ";
					return true;
				}
				left(list, i, j);
				list[i][j] += 2;
			}
		}
	}
	return false;
}

int main()
{
	int list[7][7];		//list用来表示状态,1表示空格,2表示有棋子,0表示角上的无效格子
	for (int i = 0; i < 7; i++)for (int j = 0; j < 7; j++)
	{
		list[i][j] = 0;
		if (i == 2 || i == 3 || i == 4 || j == 2 || j == 3 || j == 4)list[i][j] = 2;
	}
	list[3][3] = 1;		//初始化list
	move(list);
	cout << endl << "注意,输出的顺序是反着的";
	system("pause>nul");
	return 0;
}

输出:

41right  42left  44left  30down  41right  43right  12down  13left  24up  25left  24right  44up  36up  14down  24up  25left  22right  24down  23up  34left  52up  32up  13down  23up  22down  32right  53up  33up  23down
注意,输出的顺序是反着的


对应的结果:


最后还剩下3个子。

程序如果改成求只剩下2个子的方案,理论上是求的出来的,不过时间估计会很长,反正我运行了10分钟还没有答案输出。

其实,要想最后只剩一个棋子,而且还在最中间,这并不难。

只要自己凭感觉,就能找出一个方案,比如我的方案:独立钻石棋详解

但是独立钻石棋真正难的是,如何在最少的步数达到这一要求。

关于步数,需要解释一下。

并不是所有的方案都需要31步,和跳棋一样,有连跳的现象存在。

实际上,最少的步数是18步。

你可能感兴趣的:(独立钻石棋)