블록 회전처리 구현

void RotateBlock(BlockType type, int rotation, int& startX, int& startY) {

	bool moveFlag = true;
	vector<pair<int, int>> nextBlocks;
	vector<pair<int, int>> curBlocks;
	map<pair<int, int>, bool> treeMap;

	// 포인터 = 배열
	int* dx = nullptr;
	int* dy = nullptr;
	int blockSize = 4;

	// BlockType 에 맞는 dx, dy 배열을 설정
	SetBlockOffsets(type, rotation, dx, dy);

	// 유효성 검사
	for (int i = 0; i < 4; i++) {
		int x = startX + dx[i];
		int y = startY + dy[i];
		if (!CheckBoundary(y, x)) {
			cerr << "Block이 유효범위를 벗어났음.\\n";
			exit(EXIT_FAILURE);
		}
	}

	// 먼저 현재블록들 위치를 treeMap에 true로 두고
	// 현재 블록들 위치를 vector 형태로 저장한다.
	for (int i = 0; i < blockSize; i++) {
		int curX = startX + dx[i];
		int curY = startY + dy[i];

		pair<int, int> curPosPair = make_pair(curY, curX);
		curBlocks.push_back({ curY, curX });
		treeMap[curPosPair] = true;
	}

그 다음이 다르다. 회전이후 위치들을 살펴보고 놓을 수 있는지 판단해야한다.

void RotateClockWiseBlock(BlockType type, int& rotation, int& startX, int& startY) {

	bool moveFlag = true;
	vector<pair<int, int>> nextBlocks;
	vector<pair<int, int>> curBlocks;
	map<pair<int, int>, bool> treeMap;

	// 포인터 = 배열
	int* dx = nullptr;
	int* dy = nullptr;
	int blockSize = 4;

	// 현재 회전 상태의 오프셋 설정
	SetBlockOffsets(type, rotation, dx, dy);

	// 현재 블록 좌표 저장
	for (int i = 0; i < blockSize; i++) {
		int curX = startX + dx[i];
		int curY = startY + dy[i];

		if (!CheckBoundary(curY, curX)) {
			cerr << "Block이 유효범위를 벗어났음.\\n";
			exit(EXIT_FAILURE);
		}

		pair<int, int> curPosPair = make_pair(curY, curX);
		curBlocks.push_back(curPosPair);
		treeMap[curPosPair] = true;
	}

	// 다음 회전 상태 계산
	int nextRotation = (rotation + 1) % 4;

	int* next_dx = nullptr;
	int* next_dy = nullptr;
	SetBlockOffsets(type, nextRotation, next_dx, next_dy);

	// 다음 회전 좌표 계산 및 검사
	for (int i = 0; i < blockSize; i++) {
		int nextX = startX + next_dx[i];
		int nextY = startY + next_dy[i];
		nextBlocks.push_back({ nextY, nextX });

		// 경계 검사
		if (!CheckBoundary(nextY, nextX)) {
			return; // 회전 불가
		}

		// 겹침 검사 (자기 자신 제외)
		pair<int, int> nextPos = { nextY, nextX };
		if (treeMap.find(nextPos) == treeMap.end() && grid[nextY][nextX] == 1) {
			return; // 회전 불가
		}
	}

	// ---- 여기까지 오면 회전 가능 ---- //

	// 기존 위치 비우기
	for (auto& curBlock : curBlocks) {
		grid[curBlock.first][curBlock.second] = 0;
	}

	// 새로운 위치 채우기
	for (auto& nextBlock : nextBlocks) {
		grid[nextBlock.first][nextBlock.second] = 1;
	}

	// 회전 상태 갱신
	rotation = nextRotation;
}

void RotateCounterClockWiseBlock(BlockType type, int& rotation, int& startX, int& startY) {

	bool moveFlag = true;
	vector<pair<int, int>> nextBlocks;
	vector<pair<int, int>> curBlocks;
	map<pair<int, int>, bool> treeMap;

	// 포인터 = 배열
	int* dx = nullptr;
	int* dy = nullptr;
	int blockSize = 4;

	// 현재 회전 상태의 오프셋 설정
	SetBlockOffsets(type, rotation, dx, dy);

	// 현재 블록 좌표 저장
	for (int i = 0; i < blockSize; i++) {
		int curX = startX + dx[i];
		int curY = startY + dy[i];

		if (!CheckBoundary(curY, curX)) {
			cerr << "Block이 유효범위를 벗어났음.\\n";
			exit(EXIT_FAILURE);
		}

		pair<int, int> curPosPair = make_pair(curY, curX);
		curBlocks.push_back(curPosPair);
		treeMap[curPosPair] = true;
	}

	// 다음 회전 상태 계산
	int nextRotation = ((rotation - 1) + 4)) % 4;

	int* next_dx = nullptr;
	int* next_dy = nullptr;
	SetBlockOffsets(type, nextRotation, next_dx, next_dy);

	// 다음 회전 좌표 계산 및 검사
	for (int i = 0; i < blockSize; i++) {
		int nextX = startX + next_dx[i];
		int nextY = startY + next_dy[i];
		nextBlocks.push_back({ nextY, nextX });

		// 경계 검사
		if (!CheckBoundary(nextY, nextX)) {
			return; // 회전 불가
		}

		// 겹침 검사 (자기 자신 제외)
		pair<int, int> nextPos = { nextY, nextX };
		if (treeMap.find(nextPos) == treeMap.end() && grid[nextY][nextX] == 1) {
			return; // 회전 불가
		}
	}

	// ---- 여기까지 오면 회전 가능 ---- //

	// 기존 위치 비우기
	for (auto& curBlock : curBlocks) {
		grid[curBlock.first][curBlock.second] = 0;
	}

	// 새로운 위치 채우기
	for (auto& nextBlock : nextBlocks) {
		grid[nextBlock.first][nextBlock.second] = 1;
	}

	// 회전 상태 갱신
	rotation = nextRotation;
}

블록 회전 관련 키입력처리