Lianliankan (DFS)

Lianliankan (picture)

[ problem description ]

Create a 10*20 rectangular grid, in which there are 10 different patterns, and the number of each pattern is an even number, filling the rectangular grid.

[basic requirements]

(1) Randomly generate raw data;

(2) Input two positions, if the two patterns are the same, and can be connected by less than or equal to 3 straight lines, the two patterns can be eliminated.

Problem-solving ideas:

1. The first thing we need to do is to build a grid map. Here we use 10 capital letters from A to J (corresponding to numbers 1 to 10) to represent 10 different patterns. Because the number of each pattern is required to be an even number, we must first determine the number of each pattern (make sure they are all even numbers, and the sum is 200). Then traverse each grid in turn, and for each grid, we randomly select a pattern from the remaining patterns through random numbers to fill in.

2. After that is the stage of play game. We must first clarify the rules of the game: (1) The patterns that can be eliminated must be the same . (2) Two patterns can be connected by less than or equal to 3 straight lines. To explain here, a straight line connecting two patterns together can be considered a path. The path must be reachable (that is, connected by an empty position). When the initial pattern is full, only two adjacent patterns or two patterns on the same edge can be eliminated . In addition, less than or equal to 3 straight lines means that the path contains at most three straight lines (that is, it can only turn twice at most). Here, we can use DFS to start from one point to search another point, and count the number of turns at all times. If the number of turns is greater than 2, the search for this path will be terminated. If in the end, there is an arrival path with the number of turns less than or equal to 2, it means that it can be successfully eliminated.

Note: In order to improve the robustness of the program, input checking is required . The input must satisfy that the two positions cannot cross the boundary and there are patterns . As for whether it can be successfully eliminated, it depends on whether the two patterns are equal and whether a path between the two patterns can be found. For the pattern that has been eliminated, we use * (corresponding to the number 0) to fill in, mainly to facilitate the determination of the position when it is eliminated later. In addition, since two patterns located on the same edge can also be eliminated, when we open the array space, we need to appropriately expand the size of the original grid map .

code:

# include <iostream>
# include <random>
# include <time.h>
# define LONG 20   
# define WIDTH 10 
# define SIZE 200
# define NUM 10
using namespace std;

//随机生成图案
void Create();
//打印图案
void Print();
//输入判断
bool Judge(int a, int b, int c, int d);
//搜索路径
void DFS(int x, int y, int x2, int y2, int d, int k);
bool Find(int x1, int y1, int x2, int y2);
//玩游戏
void PlayGame();

int g[WIDTH + 2][LONG + 2] = { {0} };  //图像
int way[4][2] = { {0,1},{0,-1},{1,0},{-1,0} };  //前进方式
int visit[WIDTH + 2][LONG + 2] = { {0} };       //标记走过的地方
bool temp;          //是否存在路径

int main()
{
	Create();
	cout << "原图:" << endl;
	Print();
	PlayGame();
	return 0;
}

//随机生成图案
void Create()
{
	int n, sum = 0;
	int num[NUM + 1];   //每种图案的个数
	srand((unsigned int)time(0)); //修改种子
	for (int i = 1; i < NUM; i++) {
		//确定每种图案的个数
		n = rand() % SIZE + 1;
		if (n % 2 == 0 && sum + n < SIZE) {
			sum += n;
			num[i] = n;
		}
	}
	num[NUM] = SIZE - sum;  //直接求最后一种图案的个数
	for (int i = 1; i <= WIDTH; i++) {
		for (int j = 1; j <= LONG; j++) {
			n = rand() % NUM + 1;  //随机选取一种图案
			while (!num[n]) {
				//如果这种图案已放置完,跳到下一个
				n = (n + 1) % NUM;
				if (n == 0) {
					n = 10;
				}
			}
			g[i][j] = n;
			num[n]--;
		}
	}
}

//打印图案
void Print()
{
	char c;
	for (int i = 1; i <= WIDTH; i++) {
		for (int j = 1; j <= LONG; j++) {
			if (g[i][j]) {
				c = 64 + g[i][j];
				cout << c;
			}
			else {
				//已消去的地方用*补齐
				cout << "*";
			}
		}
		cout << endl;
	}
}

//输入判断
bool Judge(int a, int b, int c, int d)
{
	//越界检查
	if (a<1 || a>WIDTH || c<1 || c>WIDTH) {
		return false;
	}
	if (b<1 || b>LONG || d<1 || d>LONG) {
		return false;
	}
	//检查对应位置是否存在图案
	if (!g[a][b] || !g[c][d]) {
		return false;
	}
	return true;
}

//搜索路径
//(x,y)当前位置
//d是上一次的前进方向(0,1,2,3)
//k是已拐弯的次数
void DFS(int x, int y, int x2, int y2, int d, int k)
{
	if (x == x2 && y == y2 && k <= 2) {
		//到达终点,且拐弯次数小于等于2,可以成功消去
		temp = true;
		return;
	}
	if (k > 2) {
		return;
	}
	for (int i = 0; i < 4; i++) {
		int p1 = x + way[i][0];
		int p2 = y + way[i][1];
		if (visit[p1][p2] || p1<0 || p1>WIDTH + 1 || p2<0 || p2>LONG + 1) {
			//走过或越界的路淘汰
			continue;
		}
		if (g[p1][p2] && (p1 != x2 || p2 != y2)) {
			//不是终点,但有图案的路淘汰
			continue;
		}
		if (i == d || d == -1) {
			//没有拐弯
			visit[p1][p2] = 1;
			DFS(p1, p2, x2, y2, i, k);
		}
		else {
			//拐弯
			visit[p1][p2] = 1;
			DFS(p1, p2, x2, y2, i, k + 1);
		}
		//数据恢复
		visit[p1][p2] = 0;
	}
}

bool Find(int x1, int y1, int x2, int y2)
{
	temp = false;
	for (int i = 0; i <= WIDTH + 1; i++) {
		for (int j = 0; j <= LONG + 1; j++) {
			visit[i][j] = 0;
		}
	}
	DFS(x1, y1, x2, y2, -1, 0);
	return temp;
}

//玩游戏
void PlayGame()
{
	bool t;
	int x1, y1, x2, y2; //位置坐标(x1,y1),(x2,y2)
	cout << "\n游戏开始!(提示:输入0游戏结束)\n";
	cout << "请输入两个位置:";
	cin >> x1;
	while (x1) {
		cin >> y1 >> x2 >> y2;
		if (!Judge(x1, y1, x2, y2)) {
			cout << "坐标错误,请重新输入:";
		}
		else {
			if (g[x1][y1] != g[x2][y2]) {
				cout << "消去失败" << endl;
			}
			else {
				t = Find(x1, y1, x2, y2);
				if (t) {
					//符合消去要求
					g[x1][y1] = 0;
					g[x2][y2] = 0;
					cout << endl;
					Print();
				}
				else {
					cout << "消去失败" << endl;
				}
			}
			cout << "请输入两个位置:";
		}
		cin >> x1;
	}
}

operation result:

原图:
CEHDEFFIAAGJBDJHBFGH
DBHACEEHGHGDFEJIJHFD
CBEAGDFHDCEJEFGHIJJG
IDHFDFHGIDFJJBECEGGA
HHIBBJADHCCEDDAABIIH
CCDAFHFEDGHAEDGIDEFI
BHECGADHDDGABGCADGDC
DDBICDABDFBAACAABBHE
AGEDHEHIGCBBIGACCEEG
FGDBACCDGAADBAACIABA

游戏开始!(提示:输入0游戏结束)
请输入两个位置:1 2 1 5

C*HD*FFIAAGJBDJHBFGH
DBHACEEHGHGDFEJIJHFD
CBEAGDFHDCEJEFGHIJJG
IDHFDFHGIDFJJBECEGGA
HHIBBJADHCCEDDAABIIH
CCDAFHFEDGHAEDGIDEFI
BHECGADHDDGABGCADGDC
DDBICDABDFBAACAABBHE
AGEDHEHIGCBBIGACCEEG
FGDBACCDGAADBAACIABA
请输入两个位置:1 1 2 5

**HD*FFIAAGJBDJHBFGH
DBHA*EEHGHGDFEJIJHFD
CBEAGDFHDCEJEFGHIJJG
IDHFDFHGIDFJJBECEGGA
HHIBBJADHCCEDDAABIIH
CCDAFHFEDGHAEDGIDEFI
BHECGADHDDGABGCADGDC
DDBICDABDFBAACAABBHE
AGEDHEHIGCBBIGACCEEG
FGDBACCDGAADBAACIABA
请输入两个位置:0

The above is my view on this question, and I am very happy to share it with you.

Guess you like

Origin blog.csdn.net/CXR_XC/article/details/128277907
dfs