떨어지는 블록과 복잡한 모양


10

나는 현재 간단한 테트리스와 같은 게임을 가지고 있으며 해결할 수없는 문제를 겪었습니다.

단일 떨어지는 모양 이있는 Tetris와는 달리 , 여러 가지 잠재적으로 맞 물리는 모양이 있습니다. 최종 위치를 계산해야합니다. 다음을 고려하세요:

낙하 블록 문제의 예

  1. 녹색 모양의 최종 위치를 계산하기 위해 다른 사각형이나 보드 가장자리에 닿을 때까지 모든 사각형을 간단히 스캔합니다. 끝난

  2. 여러 개의 간단한 모양을 위해 보드 위로 올라갑니다. 따라서 빨간색은 움직일 필요가 없으며 주황색은 1 씩, 녹색은 3으로 내려갑니다. 끝난

  3. 연동 된 녹색 및 빨간색 모양을 처리하는 방법을 모르겠습니다. # 2의 논리를 사용하여 공중에 떠 다니는 "고착"됩니다. 녹색 모양을 스캔하면 빨간색이 표시되어 움직이지 않으며 빨간색도 마찬가지입니다. 해결책은 두 모양을 하나로 취급하는 것입니다.

  4. # 3과 유사하게이 시나리오에서 객체를 하나로 취급하여 성공할 수도 있습니다.

  5. # 3 및 # 4와 달리 주황색 모양이 1 제곱을 너무 높게 떠서 모양을 하나로 취급 할 수 없었습니다 ...

  6. 문제 # 6의 또 다른 변형.

점점 더 복잡한 시나리오에 얽히는 많은 모양이있는 다른 시나리오가있을 수 있지만 위의 문제가 가장 근본적인 부분이라고 생각합니다.

나는 아직 만나거나 생각하지 않았고 통찰력, 아이디어 또는 리소스에 매우 감사 할 우아한 솔루션이 있다고 생각합니다.

해결책

내가 생각해 낸 해결책은 아래 @ user35958의 답변을 바탕으로 실제로 우아하고 다음과 같은 재귀 함수 (의사 코드)를 만들었습니다.

function stop(square1, square2){
    // Skip if we're already stopped
    if(square1.stopped){
        return;
    }
    // Are we comparing squares?
    if(!square2){
        // We are NOT comparing squares, simply stop.
        square1.stopped = true;
    } else {
        // Stop IF
        // square1 is directly above square2
        // square1 is connected to square2 (part of the same complex shape)
        if(square1.x == square2.x && square1.y == (square2.y+1) || isConnected(square1, square2)){
            square1.stopped = true;
        }
    }
    // If we're now stopped, we must recurse to our neighbours
    stop(square1, squareAbove);
    stop(square1, squareBelow);
    stop(square1, squareRight);
    stop(square1, squareDown);
}

솔루션의 각 단계를 보여주는 애니메이션 GIF

요약하면 다음과 같습니다.

  • 정사각형을 "정지"하면 다음도 중지됩니다.
    • 위의 모든 사각형. 항상.
    • 우리가 연결된 이웃 광장 (즉, 같은 모양).
  • 우리는 전체 행을 멈추고 함수는 사각형을 통해 반복됩니다.
  • 모든 사각형이 멈출 때까지 반복합니다.
  • 그런 다음 애니메이션을 만듭니다.

논리 시퀀스의 각 패스를 보여주는 애니메이션 GIF


당신이 5를 풀면 6도 풀 것이라고 상상합니다. 사실, 나는 5를 해결하면 이러한 모든 상황을 해결할 수 있다고 생각합니다.
UnderscoreZero

공유해 주셔서 감사합니다. 놀라운 해결책. 애니메이션을 사랑 :)
ashes999

건배 ashes999, 나는 정지 논리가 맨 아래 줄에서 "흐르고"전체 단계를 통해 확산되는 방법을 보여주는 화살표가있는 새로운 애니메이션이 필요하다고 생각합니다.
oodavid

답변:


4

음, 움직이는 모양과 휴지 모양 사이에 차이가있는 경우 모양을 하나로 취급 할 필요가 없습니다. 셰이프 (A)는 바로 아래에있는 셰이프 (B)를 감지 할 수 있으며, 움직이면 B 바로 아래에 무언가가 있는지 확인하고 휴식중인 셰이프가 있으면 A와 B가 쉬고 있습니다. 아무것도 없으면 둘 다 아래로 이동하지만 움직이는 모양이 있으면이 새로운 모양은 A와 B에 의해 A 처리 B로 처리되므로 일종의 재귀 적입니다. 각 단계마다 가장 낮은 모양이 먼저 아래에있는 모양을 확인해야합니다.

따라서 문제 # 6의 경우 녹색 모양이 가장 낮은 이동 모양이며 바로 아래에있는 유일한 모양은 빨간색 모양이므로 빨간색 모양은 바로 아래에 아무것도 감지하지 못하고 아래쪽으로 이동합니다. . 녹색 모양이 주황색 모양에 인접 해 있으면 휴식을 취하고 빨간색 모양이 아래로 이동 한 다음 휴식하는 녹색 모양을 감지하면 휴식도됩니다.


우리가 달리 증명할 때까지 모든 모양이 쉬지 않는다고 가정해야한다고 생각하는 것이 맞습니까?
oodavid

방금 이것을 숙고하는 데 시간을 보냈으며 아주 좋은 기술인 것 같습니다. 나는 내일 / 주말에 시도하고 어떻게 진행되는지 볼 것입니다.
oodavid

3

사례 # 5 및 # 6의 문제는 단일 루트에서 비롯된 것 같습니다. 한 번의 이동 검사 만 수행하는 것입니다. 아무것도 움직이지 않을 때까지 물건을 계속 내려 가야합니다 ( "중력 패스"라고 함).

예를 들어, 6의 경우 여러 패스를 사용하면 다음과 같이됩니다.

  • 오렌지색 아래로 이동
  • 녹색이 아래로 이동
  • 오렌지색 아래로 이동
  • 녹색이 아래로 이동
  • 오렌지색 아래로 이동
  • 아무것도 아래로 이동하지 않습니다 (완료!)

이 다중 중력 통과 전략은 # 5도 해결할 수 있지만 사례 # 3 및 # 4에서는 도움이되지 않지만 사례를 한 조각처럼 취급해야합니다.

두 개 이상의 조각을 단일 조각으로 취급해야 할 때를 구별하기 위해 가장 쉬운 알고리즘은 모든 조각의 결합 공간에 "구멍"이 있는지 확인하는 것입니다. 있다면 여러 조각으로 취급 할 수 있습니다.


1
# 3과 # 4를 사용하면 2 개 또는 3 개의 모양이 더 큰 "C"모양으로 완전히 둘러싸여있어 조각이 응고되는지 여부를 파악하면 다른 문제가 발생할 수 있습니다. 나는 그 일을하고 그것의 오는 것을 볼 것입니다! 건배 @ ashes999
oodavid

@oodavid 귀하의 요구 사항 / 디자인은 불필요하게 나에게 복잡해 보입니다. 더 간단한 것으로 시작하여 이러한 문제를 해결하는 데 도움이됩니다.
ashes999

아니, 위의 문제는 훨씬 더 복잡한 문제를 설명하기 위해 철저히 단순화 / 추상화 된 방법입니다. 나는 추격의 스릴을 위해 이것을하고 있습니다!
oodavid
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.