连连看(南航2022数据结构课设第十二题)

[问题描述]

建立一个10*20的矩形方格图,其中有10种不同的图案,每种图案个数为偶数,填满矩形方格图。

[基本要求]

(1)随机产生原始数据;

(2)输入两个位置,如果两者图案相同,并且可以用小于等于3条直线相连,即可消除该两个图案。

[基本思路和代码实现]

图的建立:首先建立如下图所示的矩阵,再将系统时间作为种子将矩阵进行随机打乱,得到最后的连连看地图。

void creat()
{
	int row = 10;
	int col = 20;
	int num = 0;
	for (int i = 0; i < row; ++i)
	{
		for (int j = 0; j < col; ++j)
		{
			gamedata[i][j] = (num / 2 + 1) % 10;//0到10的建立
			++num;
		}
	}
	//print();
	//随机打乱数组里面的数据
	srand((unsigned)time(NULL));	//使用当前的系统时间作为随机数种子
	for (int count = 0; count < (row * col) / 2; ++count)
	{
		int x1 = rand() % col;	//生成 0 -- (col - 1) 的数据
		int y1 = rand() % row;	//生成 0 -- (row - 1) 的数据
		int x2 = rand() % col;	//生成 0 -- (col - 1) 的数据
		int y2 = rand() % row;	//生成 0 -- (row - 1) 的数据
		swap(gamedata[y1][x1], gamedata[y2][x2]);
	}
	//print();
}

相连消除:四种情况

1.一条直线:直接判断是否在同一行或同一列,在判断中间是否有障碍即可。

bool judge_x(int x1, int y1, int x2, int y2)//同行判断
{
	if (x1 == x2)
	{
		int flag = 1;
		for (int i = (y1 < y2 ? y1 : y2) + 1; i < (y1 > y2 ? y1 : y2); i++)
		{
			if (gamedata[x1][i] != -1)
			{
				flag = 0;
				break;
			}
		}
		if (flag == 1)
			return true;
	}
	return false;
}
bool judge_y(int x1, int y1, int x2, int y2)//同列判断
{
	if (y1 == y2)
	{
		int flag = 1;
		for (int i = (x1 < x2 ? x1 : x2) + 1; i < (x1 > x2 ? x1 : x2); i++)
		{
			if (gamedata[i][y1] != -1)
			{
				flag = 0;
				break;
			}
		}
		if (flag == 1)
			return true;
	}
	return false;
}
bool judge_1(int x1, int y1, int x2, int y2)//一条直线判断
{
	if (judge_x(x1, y1, x2, y2) == 1 || judge_y(x1, y1, x2, y2) == 1)
	{
		return true;
	}
	return false;
}

 2.两条直线:两条可能通的道路,各有一个拐点,根据拐点进行两次单条直线联通判断,只要有一个拐点通,则通。这个判断有点长,要是理不过来,画个图就很好理解(我就是这么干的)。

bool judge_2(int x1, int y1, int x2, int y2)//两条直线判断
{
	if ((judge_x(x1, y1, x1, y2) == 1 && judge_y(x1, y2, x2, y2) == 1 && gamedata[x1][y2] == -1) || (judge_x(x2, y1, x2, y2) == 1 && judge_y(x1, y1, x2, y1) == 1 && gamedata[x2][y1] == -1))
	{
		return true;
	}
	return false;
}

3.三条直线:没想到太好的方法,就直接遍历图,看是否能找到与一个点单条直线相连,与另一点两条直线相连,小数据,也很快。

bool judge_3(int x1, int y1, int x2, int y2)
{
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 20; j++)
		{
			if ((i == x1 && j == y1) || i == x2 && j == y2)
				continue;
			if ((judge_1(x1, y1, i, j) == 1 && judge_2(i, j, x2, y2) == 1) || (judge_2(x1, y1, i, j) == 1 && judge_1(i, j, x2, y2) == 1))
			{
				return true;
			}
		}
	}
	return false;
}

4.再就是消除不了,要么是连不上,要么是数字不同,数字不同提前判断一下就行。

[源代码]

#include<iostream>
#include<iomanip>
using namespace std;
int gamedata[11][21] = { 0 };
typedef pair<int, int>position;
void print()
{
	cout << setw(4) << ' ';
	for (int i = 0; i < 20; i++)
		cout << setw(4) << i;
	cout << endl << "--------------------------------------------------------------------------------------------" << endl;
	for (int i = 0; i < 10; i++)
	{
		cout << setw(3) << i << '|';
		for (int j = 0; j < 20; ++j)
		{
			if (gamedata[i][j] != -1)
				cout << setw(4) << gamedata[i][j];
			else
				cout << setw(4) << ' ';
		}
		cout << endl;
	}
}
void creat()
{
	int row = 10;
	int col = 20;
	int num = 0;
	for (int i = 0; i < row; ++i)
	{
		for (int j = 0; j < col; ++j)
		{
			gamedata[i][j] = (num / 2 + 1) % 10;//0到1的建立
			++num;
		}
	}
	//print();
	//2.随机打乱数组里面的数据
	srand((unsigned)time(NULL));	//使用当前的系统时间作为随机数种子
	for (int count = 0; count < (row * col) / 2; ++count)
	{
		int x1 = rand() % col;	//生成 0 -- (col - 1) 的数据
		int y1 = rand() % row;	//生成 0 -- (row - 1) 的数据
		int x2 = rand() % col;	//生成 0 -- (col - 1) 的数据
		int y2 = rand() % row;	//生成 0 -- (row - 1) 的数据
		swap(gamedata[y1][x1], gamedata[y2][x2]);
	}
	//print();
}
bool judge_x(int x1, int y1, int x2, int y2)
{
	if (x1 == x2)
	{
		int flag = 1;
		for (int i = (y1 < y2 ? y1 : y2) + 1; i < (y1 > y2 ? y1 : y2); i++)
		{
			if (gamedata[x1][i] != -1)
			{
				flag = 0;
				break;
			}
		}
		if (flag == 1)
			return true;
	}
	return false;
}
bool judge_y(int x1, int y1, int x2, int y2)
{
	if (y1 == y2)
	{
		int flag = 1;
		for (int i = (x1 < x2 ? x1 : x2) + 1; i < (x1 > x2 ? x1 : x2); i++)
		{
			if (gamedata[i][y1] != -1)
			{
				flag = 0;
				break;
			}
		}
		if (flag == 1)
			return true;
	}
	return false;
}
bool judge_1(int x1, int y1, int x2, int y2)//一条直线判断
{
	if (judge_x(x1, y1, x2, y2) == 1 || judge_y(x1, y1, x2, y2) == 1)
	{
		return true;
	}
	return false;
}
bool judge_2(int x1, int y1, int x2, int y2)//两条直线判断
{
	if ((judge_x(x1, y1, x1, y2) == 1 && judge_y(x1, y2, x2, y2) == 1 && gamedata[x1][y2] == -1) || (judge_x(x2, y1, x2, y2) == 1 && judge_y(x1, y1, x2, y1) == 1 && gamedata[x2][y1] == -1))
	{
		return true;
	}
	return false;
}
bool judge_3(int x1, int y1, int x2, int y2)
{
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 20; j++)
		{
			if ((i == x1 && j == y1) || i == x2 && j == y2)
				continue;
			if ((judge_1(x1, y1, i, j) == 1 && judge_2(i, j, x2, y2) == 1) || (judge_2(x1, y1, i, j) == 1 && judge_1(i, j, x2, y2) == 1))
			{
				return true;
			}
		}
	}
	return false;
}
int is_conected(position p1, position p2)
{
	int x1 = p1.first;
	int x2 = p2.first;
	int y1 = p1.second;
	int y2 = p2.second;
	if (judge_1(x1, y1, x2, y2))
		return 1;
	if (judge_2(x1, y1, x2, y2))
		return 2;
	if (judge_3(x1, y1, x2, y2))
		return 3;
	return -1;
}
void run()
{
	int time = 100;
	while (time >= 0)
	{
		position p1;
		position p2;
		print();
		while (1)
		{
			cout << "输入第一个选择的坐标(eg:1 2):";
			cin >> p1.first;
			cin >> p1.second;
			if (p1.first < 0 || p1.first>10 || p1.second < 0 || p1.second>20)
			{
				cout << "坐标不合法!!!" << endl;
				system("pause");
				continue;
			}
			if (gamedata[p1.first][p1.second] == -1)
			{
				cout << "该位置已销除!!!" << endl;
				system("pause");
				continue;
			}
			break;
		}
		while (2)
		{
			cout << "输入第二个选择的坐标(eg:1 2):";
			cin >> p2.first;
			cin >> p2.second;
			if (p2.first < 0 || p2.first>10 || p2.second < 0 || p2.second>20)
			{
				cout << "坐标不合法!!!" << endl;
				system("pause");
				continue;
			}
			if (gamedata[p2.first][p2.second] == -1)
			{
				cout << "该位置已销除!!!" << endl;
				system("pause");
				continue;
			}
			break;
		}
		if (gamedata[p1.first][p1.second] != gamedata[p2.first][p2.second])
		{
			cout << "两位置图像不同!!!" << endl;
			system("pause");
			system("cls");
			continue;
		}
		if (p1.second == p2.second && p1.first == p2.first)
		{
			cout << "请输入两个不相同的坐标" << endl;
			system("pause");
			system("cls");
			continue;
		}
		int n = is_conected(p1, p2);
		if ( n != -1)
		{
			gamedata[p1.first][p1.second] = -1;
			gamedata[p2.first][p2.second] = -1;
			cout << n << "条直线连接" << endl << "消除成功!" << endl;
			system("pause");
			system("cls");
		}
		else
		{
			cout << "连不上!!!" << endl;
			system("pause");
			system("cls");
		}
	}
	cout << "游戏成功!!!" << endl;
}
int main()
{
	creat();
	run();
}

[运行结果]

 

虽然我没有写保障必定有解的程序,但是大概率应该也是有解的,但是我也没消完过,毕竟得消除100次,谁要是消完了可以发我看看。

再就是这个代码连线只能满足图内的连线,不能从图外连线,改起来也简单,扩大一圈就可以了,在此不作过多演示了。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值