Xác định xem một tập hợp các ô trên lưới có tạo thành hình dạng kèm theo không


10

Đưa ra một tập hợp các ô trên lưới, tôi muốn xác định:

  • Nếu gạch tạo thành một hình kèm theo
  • Nếu các ô tạo thành một hình kèm theo khi bạn đếm các cạnh của bảng là một cạnh của hình
  • Nếu một trong hai câu lệnh trước là đúng, thì các ô bổ sung nằm trong hình được đính kèm, mẫu gạch ban đầu.

Người chơi sẽ bắt đầu bằng cách nhấn xuống một ô, sau đó kéo ngón tay của họ sang các ô khác để tạo ra một chuỗi các ô cùng màu. Tôi sẽ kiểm tra khi tôi đi xem gạch tiếp theo có hợp lệ không. Ví dụ. Nếu người chơi bắt đầu trên một ô màu đỏ, bước di chuyển hợp lệ tiếp theo của họ là một ô màu đỏ liền kề (các đường chéo sẽ được tính). Khi người dùng nhấc ngón tay lên, tôi cần có thể kiểm tra 3 mục trên.

Vì vậy, suy nghĩ ban đầu của tôi là, vì tôi đã kiểm tra tính hợp lệ của chuỗi mỗi lần tôi đi, khi người chơi nhấc ngón tay lên, tôi có thể kiểm tra xem các ô đầu tiên và cuối cùng có liền kề hay không. (Tôi đã biết chúng có cùng màu.) Nếu chúng liền kề tôi có linh cảm tôi đã tạo ra một hình người kèm theo, và tôi sẽ đến đây để thử xem tôi có thiếu thứ gì lớn không, và để có được một số loại bằng chứng logic / toán học cho thấy linh cảm của tôi là đúng (hoặc một ví dụ chứng minh nó không chính xác.)

Nhưng đó là khi tôi nghĩ đến mục số 2: Tôi cũng phải tính đến các chuỗi sử dụng một cạnh của bảng như một mặt của hình kèm theo. Trong trường hợp đó, các mục đầu tiên và cuối cùng trong chuỗi sẽ không liền kề, nhưng tôi vẫn sẽ có một hình kèm theo. Vì vậy, bây giờ tôi trở lại một hình vuông, một chút.

Tôi có thể làm gì với chuỗi tọa độ lưới này để tìm hiểu xem chúng có tạo hình kín hay không? Và khi tôi làm biết tôi có một nhân vật kín, cách tốt nhất để có được một danh sách bổ sung của tất cả các gạch rơi bên trong giới hạn của nó là gì?

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

Ở trên tôi đã vẽ những bức tranh về những gì tôi mong đợi 4 kết quả có thể có của bài kiểm tra này.

  1. Chuỗi không tạo ra một con số kèm theo.

  2. Chuỗi này làm cho một con số kèm theo.

  3. Nếu bạn tính các cạnh của bảng là một cạnh (hoặc nhiều hơn một cạnh) của hình, chuỗi sẽ tạo ra một hình kèm theo.

  4. Chuỗi thực hiện một hình kèm theo, nhưng có các điểm dữ liệu bổ sung (được người dùng chọn hợp lệ là một phần của chuỗi) không phải là một phần của hình được tạo.

Trường hợp 4 là khó nhất, bởi vì bạn phải trích xuất các liên kết chuỗi "phụ" để tìm hình được đính kèm và các mảnh nằm bên trong nó (nhưng không phải xung quanh khu vực "không bị che khuất").

Vậy ... có ai có ý tưởng về một cách tốt để giải quyết vấn đề này không, hay chỉ là điểm khởi đầu cho tôi? Lúc này tôi đang đi theo vòng tròn và có thể sử dụng một đôi mắt khác.


1
Điều gì về các đường giao nhau như hình 8, hoặc năm sao ? Bạn sẽ giả sử quy tắc điền khác không hoặc chẵn lẻ ?
Anko

Trường hợp 4 cũng có thể sáp nhập với Trường hợp 3: Kèm lợi dụng thân của hội đồng quản trị, với thông tin thêm
ChargingPun

Nếu bạn có một đường thẳng đứng chạy xuống giữa bảng của bạn từ cạnh trên xuống dưới, thì phía nào của bảng được 'bao quanh'?
Steven Stadnicki

Tôi nghĩ rằng chúng ta nên cho rằng không gian nhỏ nhất được bao quanh bây giờ. Trừ khi OP chỉ định khác.
Piddock Tom 'Blue'

Câu trả lời:


3

1. Phát hiện một vòng gạch

Vấn đề có vẻ giống với việc phát hiện một chu kỳ (vòng lặp) trong biểu đồ, xem tại đây hoặc tại đây .

  • Tập hợp các nút Vcủa biểu đồ đó G=(V, E)là các ô,
  • một cạnh e = (v1, v2)tồn tại giữa hai nút khác nhau, nếu các ô là hàng xóm trực tiếp hoặc chéo

2. Xử lý trường hợp viền màn hình

Đường viền màn hình bao gồm các ô tưởng tượng sẽ tạo thành một viền rộng một ô xung quanh màn hình của các ô có thể nhìn thấy.

Theo đặc điểm kỹ thuật của bạn, viền màn hình sẽ tạo thành một phần ngầm định của một vòng khép kín. Chỉ cần phát hiện một vòng khép kín, sẽ đủ để mở rộng biểu đồ Gthành biểu đồ G'bằng cách tôn trọng kết nối thông qua quy tắc này:

  • một cạnh khác tồn tại giữa bất kỳ hai nút khác nhau, nếu hai ô được đặt trực tiếp gần viền của màn hình

Do đó, các ô tại (0,0) và (1,0) sẽ là một phần của vòng khép kín, cùng với "các ô viền" (-1,0), (-1, -1), (0, -1) , (1, -1).

3. Phần bên trong của một khu vực vòng

Tôi sẽ đi theo một hướng tương tự với những gì người dùng Arthur Wulf White gợi ý:

Giới hạn bộ gạch chúng ta phải kiểm tra bằng hộp giới hạn của gạch vòng.

Sau đó, sử dụng công cụ lấp lũ để chọn tất cả các ô trong khung giới hạn bên ngoài hoặc bên trong vào vòng kín. Nó chỉ có thể là một trong hai trường hợp đó. Cái nào chúng ta phải tìm hiểu sau đó.

Mở rộng hộp giới hạn bởi một ô theo mỗi hướng cũng sẽ là một ý tưởng tốt, extbbvì vậy chúng tôi chỉ kết thúc với một tập hợp các điểm bên ngoài được kết nối, trong trường hợp chúng tôi bắt đầu lấp đầy bằng một lớp gạch bên ngoài.

Khi chúng ta có vùng lấp lũ, chúng ta cũng sẽ tính hộp giới hạn của nó ffbb. Trong trường hợp chúng tôi bắt đầu với một lớp gạch bên ngoài, nó phải giống hệt với hộp giới hạn vòng mở rộng.

ffbb == extbb

Trong trường hợp chúng tôi bắt đầu với một gạch nội thất, nó sẽ mang lại một hộp giới hạn nhỏ hơn rõ rệt, bởi vì các vòng lặp phải được kẹp ở giữa cả hai hộp giới hạn.

ffbb < extbb

Ngói ban đầu cho vùng lấp lũ có thể là bất kỳ ô nào trong extbbđó là ô miễn phí. Có lẽ chọn một cách ngẫu nhiên là cách tiếp cận tốt nhất.

Nếu trước đây tôi biết rằng bên trong nhỏ hơn bên ngoài, tôi sẽ bắt đầu xung quanh tâm khối lượng của các điểm vòng trong phần bên trong đối với nhiều khu vực (ví dụ: khu vực hình chữ C), nếu không thì trên đường viền của extbb. Nhưng tôi không biết làm thế nào để ước tính điều này.

Chú thích cuối

Normaly Tôi sẽ nói rằng một bước đi đơn giản bắt đầu từ một số ô và giữ một danh sách các ô được truy cập là đủ để phát hiện một chu kỳ, nhưng điều kiện biên màn hình đó có thể mang lại một biểu đồ phức tạp hơn, vì vậy bạn nên ở bên an toàn với thuật toán biểu đồ .

Dưới đây là một ví dụ trong đó phần bên trong không được kết nối, mặt khác, việc phát hiện chu kỳ sẽ tìm thấy hai vòng lặp trong trường hợp đó, một vòng sẽ bị loại bỏ.

một số trường hợp


1

Bạn có thể giải quyết điều này bằng cách:

  1. Tìm hộp giới hạn của hình dạng đó.
  2. Tăng kích thước của nó lên 1 theo mỗi hướng.
  3. Lặp lại qua khung của hộp giới hạn hơi mở rộng mới và áp dụng cách lấp đầy.
  4. Nếu có bất kỳ ô nào mà bạn không đánh dấu bằng vùng lấp đầy không nằm trong chuỗi đó thì chúng sẽ được đính kèm. Tôi cho rằng theo định nghĩa của bạn nếu có các ô kín hơn hình dạng là một hình kín.

Để làm một, lặp qua tất cả các gạch trên chuỗi và tìm họ minX, minY, maxXmaxYvà đó là khung giới hạn của bạn hoặc AABB.

Hai là tầm thường.

Lặp lại trên khung là đơn giản, chỉ cần đảm bảo không lấp đầy bên ngoài lưới. Bạn có thể tìm hiểu làm thế nào để lấp đầy trong Wikipedia .

Đối với số bốn, bạn có thể bắt đầu bằng cách chỉ kiểm tra các ô liền kề với chuỗi. Bạn có thể lấp đầy từ bất kỳ ô nào bạn thấy không được đánh dấu để xác định vị trí nhiều ô hơn.


0

Trực giác của bạn là đúng, giả sử rằng chuỗi kết thúc ngay khi người dùng cố gắng chọn một lát họ đã chọn. Trong trường hợp đó, hình dạng nói chung trông giống như một bức tranh, trong bức tranh của bạn (4). Nếu họ có thể tiếp tục vuốt, thì họ có thể vẽ nhiều vòng, và mọi thứ trở nên phức tạp hơn. Những gì bạn muốn làm là trả lời câu hỏi đa điểm .

Đầu tiên, chúng ta cần xác định vấn đề. Tôi sẽ giả định rằng tình huống trông giống như (2), tức là bất kỳ cái đuôi nào đã bị tước bỏ, và phần cuối kết nối trở lại điểm bắt đầu, để mỗi ô có chính xác một "tiền thân" và chính xác là một "người kế thừa" trong chuỗi (trong đó tiền thân của người kế vị của gạch X luôn là gạch X). Hơn nữa, nếu bạn theo dõi "người kế vị" đủ lâu, cuối cùng bạn sẽ quay lại nơi bạn bắt đầu. Bạn có thể sử dụng đề xuất của Gurgadurgen để phát hiện xem vòng lặp có thực sự quay trở lại chính nó tại bất kỳ điểm nào không. Giả sử bạn kết thúc đầu vào của người dùng khi thực hiện, nó sẽ trông giống như một số nút trong một dòng, theo sau là một vòng lặp. Bạn có thể tước dòng khỏi vòng lặp get.

Bây giờ chúng tôi, cho mỗi hàng làm như sau:

  1. Bắt đầu ở cạnh trái và theo dõi boolean cho mỗi ô cho biết chúng ta đang VÀO. Bắt đầu ra.
  2. Nếu gạch hiện tại là một phần của chuỗi, hãy nhìn vào cả người kế nhiệm và người tiền nhiệm (phải liền kề). Nếu một trong hai phía trên (ví dụ: bắc, đông bắc hoặc tây bắc của gạch hiện tại), hãy đặt trạng thái của gạch hiện tại ở phía đối diện của gạch ở bên trái. Nếu không, đặt nó giống như gạch ở bên trái. Đi 4.
  3. Nếu ô hiện tại không phải là một phần của chuỗi, đặt ô ở trạng thái của tiêu đề ở bên trái. Đi 4.
  4. Gạch một bên phải bây giờ là gạch hiện tại. Đi 2.

Bây giờ, lấy tất cả các ô đang IN, thêm vào các ô trên đường viền (bao gồm cả đuôi nếu bạn tước nó trước đó hay không, lựa chọn của bạn) và gọi đó là vùng.

Nếu bạn muốn cho phép người dùng sử dụng viền, hãy nhớ rằng điều này không xác định và IN / OUT trên bảng, mà chỉ chia nó thành hai phần. Ví dụ, bạn có thể chọn vùng nhỏ hơn hoặc yêu cầu người dùng sử dụng hai cạnh liền kề (nghĩa là bên trái và dưới cùng, nhưng không phải trên cùng / dưới cùng hoặc trái / phải).

Một tối ưu hóa là bạn chỉ cần thực hiện các hàng có bất kỳ đường viền nào trong đó (nếu bạn không thể sử dụng các cạnh). Tôi giả định rằng bảng của bạn đủ nhỏ để lặp đi lặp lại trên mỗi ô và thực hiện một phép tính rất đơn giản không phải là vấn đề, ngay cả trên hệ thống di động yếu nhất. (Rốt cuộc, bạn phải kết xuất chúng, một nhiệm vụ phức tạp hơn nhiều).

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.