Khối rơi và hình dạng phức tạp


10

Tôi hiện đang có một trò chơi giống như Tetris đơn giản và đã gặp phải một vấn đề mà tôi không thể giải quyết.

Không giống như Tetris, nơi có một hình dạng rơi duy nhất , tôi có nhiều hình dạng, có khả năng lồng vào nhau cần phải rơi; Tôi cần tính toán vị trí cuối cùng của họ. Hãy xem xét những điều sau đây:

ví dụ về vấn đề khối rơi

  1. Để tính toán vị trí cuối cùng của hình dạng màu xanh lá cây, tôi chỉ cần quét xuống cho mỗi hình vuông cho đến khi tôi chạm vào một hình vuông khác hoặc cạnh của bảng. Làm xong

  2. Đối với nhiều hình dạng đơn giản, tôi làm việc theo cách của mình lên bảng. Do đó, màu đỏ được tìm thấy là không cần di chuyển, màu cam đi xuống một, màu xanh xuống ba. Làm xong

  3. Tôi không biết làm thế nào để xử lý các hình dạng màu xanh lá cây và màu đỏ lồng vào nhau. Sử dụng logic của số 2, chúng tôi sẽ kết thúc "không khí" lơ lửng giữa không trung. Nếu tôi quét xuống hình dạng màu xanh lá cây, tôi bắt gặp màu đỏ và do đó không di chuyển và ngược lại với màu đỏ. Giải pháp có thể là coi hai hình dạng là một.

  4. Tương tự như # 3, trong kịch bản này, tôi cũng có thể thành công bằng cách coi các đối tượng là một.

  5. Không giống như số 3 và số 4, tôi không thể coi hình dạng là một vì hình dạng màu cam sẽ nổi lên một hình vuông quá cao ...

  6. Một biến thể khác của vấn đề # 6.

Có thể có các kịch bản khác theo đó tôi có nhiều hình dạng đan xen trong các kịch bản ngày càng phức tạp hơn, nhưng tôi nghĩ ở trên bao gồm các phần cơ bản nhất của vấn đề.

Tôi cảm thấy như có một giải pháp tao nhã mà tôi chưa gặp phải / nghĩ ra và sẽ rất biết ơn về bất kỳ hiểu biết, ý tưởng hoặc tài nguyên nào.

GIẢI PHÁP

Giải pháp tôi đưa ra thực sự rất thanh lịch, dựa trên câu trả lời của @ user35958 bên dưới, tôi đã tạo ra hàm đệ quy sau (mã giả)

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 hoạt hình hiển thị từng lượt giải pháp

Để tóm tắt:

  • Khi "dừng" một hình vuông, chúng tôi cũng dừng lại:
    • MỌI hình vuông phía trên nó. LUÔN LUÔN.
    • Hình vuông lân cận mà chúng ta được kết nối (nghĩa là cùng hình dạng).
  • Chúng tôi dừng toàn bộ hàng dưới cùng và chức năng đệ quy qua các ô vuông.
  • Chúng tôi lặp lại cho đến khi tất cả các hình vuông được dừng lại.
  • Sau đó, chúng tôi hoạt hình.

GIF hoạt hình hiển thị từng lượt của chuỗi logic


Tôi tưởng tượng nếu bạn giải được 5 thì 6 cũng sẽ được giải. Trên thực tế, tôi tin rằng giải quyết 5 có thể sẽ giải quyết tất cả các tình huống này.
UnderscoreZero

+1 cảm ơn vì đã chia sẻ. Giải pháp tuyệt vời. Yêu hoạt hình :)
tro999

Chúc mừng tro cốt999, tôi nghĩ rằng tôi cần một hình ảnh động mới với các mũi tên chỉ ra cách logic dừng "chảy" từ hàng dưới cùng và sinh sôi nảy nở trong toàn bộ sân khấu ...
oodavid

Câu trả lời:


4

Chà, chính xác là bạn không cần phải coi hình dạng là một nếu có sự phân biệt giữa các hình dạng đang chuyển động và hình dạng đang nghỉ ngơi. Một hình dạng (A) có thể phát hiện một hình dạng (B) ngay bên dưới nó và nếu nó di chuyển, thì hình dạng B có thể thấy nếu có bất cứ thứ gì ngay bên dưới nó, và nếu có một hình dạng nghỉ ngơi, thì A và B hiện đang nghỉ ngơi, và nếu không có gì, cả hai đều di chuyển xuống, nhưng nếu có hình dạng chuyển động, thì hình dạng mới này sẽ được A và B xử lý như A được xử lý B, vì vậy đó là loại đệ quy. Hãy nhớ rằng đối với mỗi bước, các hình dạng thấp nhất cần kiểm tra các hình bên dưới chúng trước.

Vì vậy, đối với vấn đề # 6, hình dạng màu xanh lá cây là hình dạng chuyển động thấp nhất và nó sẽ thấy rằng hình dạng duy nhất ngay bên dưới nó là hình dạng màu đỏ, do đó, hình dạng màu đỏ sẽ không phát hiện thấy gì ngay bên dưới nó và chúng sẽ di chuyển xuống . Khi hình dạng màu xanh lá cây liền kề với hình dạng màu cam, nó sẽ nghỉ ngơi và hình dạng màu đỏ sẽ di chuyển xuống và sau đó phát hiện hình dạng màu xanh lá cây còn lại, và nó cũng sẽ nghỉ ngơi.


Tôi có đúng không khi nghĩ rằng chúng ta phải giả sử tất cả các hình dạng không nghỉ ngơi cho đến khi chúng ta chứng minh điều khác?
oodavid

Tôi đã dành một chút thời gian để suy nghĩ về điều này và tôi phải nói rằng nó có vẻ như là một kỹ thuật rất tốt. Tôi sẽ thử nó vào ngày mai / cuối tuần và xem nó như thế nào.
oodavid

3

Có vẻ như vấn đề với các trường hợp # 5 và # 6 xuất phát từ một gốc duy nhất: bạn chỉ thực hiện một lần kiểm tra chuyển động. Bạn nên tiếp tục di chuyển mọi thứ xuống (hãy gọi nó là "vượt qua trọng lực") cho đến khi bạn biết không có gì di chuyển.

Ví dụ: trong trường hợp 6, đây là điều sẽ xảy ra nếu bạn sử dụng nhiều đường chuyền:

  • Cam di chuyển xuống
  • Màu xanh di chuyển xuống
  • Cam di chuyển xuống
  • Màu xanh di chuyển xuống
  • Cam di chuyển xuống
  • Không có gì di chuyển xuống (thực hiện!)

Chiến lược vượt qua nhiều trọng lực này cũng có thể giải quyết # 5, mặc dù nó sẽ không giúp ích cho các trường hợp # 3 và # 4 trong đó có vẻ như bạn cần đối xử với chúng như một mảnh.

Để phân biệt khi hai hoặc nhiều mảnh nên được coi là một mảnh duy nhất, tôi nghĩ thuật toán đơn giản nhất là kiểm tra xem có bất kỳ "lỗ hổng" nào trong không gian kết hợp của tất cả các mảnh hay không. Nếu có, nó có thể được coi là nhiều mảnh.


1
Với số 3 và số 4 cũng có thể có các biến thể trong đó nói rằng 2 hoặc 3 hình được bao bọc hoàn toàn bởi hình chữ "C" lớn hơn, tìm ra nếu các mảnh bị đông lại có thể gây ra nhiều vấn đề hơn nữa. Tôi sẽ cho nó đi và xem những gì đến của nó! Chúc mừng @ tro999
oodavid

@oodavid yêu cầu / thiết kế của bạn có vẻ phức tạp không cần thiết với tôi. Bắt đầu với một cái gì đó đơn giản hơn và làm theo cách của bạn khi bạn giải quyết những vấn đề này.
tro999

Nahhhh, vấn đề ở trên là một cách đơn giản hóa / trừu tượng hóa hoàn toàn để mô tả một vấn đề phức tạp hơn nhiều. Tôi đang làm điều này cho sự hồi hộp của cuộc rượt đuổi!
oodavid
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.