Việc xem liệu một cấu hình lưới nhất định phù hợp với một công thức nhất định có đơn giản không nếu bạn mã hóa lưới 3x3 dưới dạng chuỗi và sử dụng kết hợp biểu thức chính quy . Tăng tốc tìm kiếm là một vấn đề khác, cuối cùng tôi sẽ nói về nó. Đọc tiếp để biết thêm thông tin.
Bước 1) Mã hóa lưới dưới dạng Chuỗi
Chỉ cần cung cấp một id char cho từng loại ô và ghép mọi thứ cạnh nhau theo thứ tự này:
123
456 => 123456789
789
Và như một ví dụ cụ thể hơn, hãy xem xét công thức thanh, trong đó W là viết tắt của gỗ và E là một ô trống (bạn có thể chỉ cần sử dụng một char trống rỗng ''):
EEE
WEE => EEEWEEWEE
WEE
Bước 2) Kết hợp công thức bằng cách sử dụng biểu thức chính quy (hoặc String.Contains với một chút xử lý trên dữ liệu)
Tiếp tục từ ví dụ trên, ngay cả khi chúng ta di chuyển đội hình xung quanh, vẫn có một mẫu trong chuỗi (WEEW được đệm bởi E ở cả hai bên):
EEW
EEW => EEWEEWEEE
EEE
Vì vậy, bất kể bạn di chuyển cây gậy xung quanh ở đâu, nó vẫn sẽ khớp với biểu thức thông thường sau: /^E*WEEWE*$/
Biểu thức thông thường cũng cho phép bạn thực hiện hành vi có điều kiện mà bạn đề cập. Ví dụ: (đã tạo thành công thức), nếu bạn muốn một cái cuốc được làm bằng sắt hoặc đá để cho kết quả tương tự, tức là:
III SSS
EWE or EWE
EWE EWE
Bạn có thể kết hợp cả hai thành biểu thức chính quy: /^(III)|(SSS)EWEEWE$/
Flips ngang cũng có thể được thêm dễ dàng (sử dụng toán tử | quá).
Chỉnh sửa: Dù sao, phần regex không thực sự cần thiết. Đây chỉ là một cách để gói gọn vấn đề trong một biểu thức duy nhất Nhưng đối với vấn đề vị trí biến, bạn cũng có thể cắt chuỗi lưới của bất kỳ không gian đệm nào (hoặc E trong ví dụ này) và thực hiện String.Contains (). Và đối với vấn đề nhiều thành phần hoặc các công thức được nhân đôi, bạn có thể xử lý tất cả chúng dưới dạng nhiều công thức (nghĩa là riêng biệt) với cùng một đầu ra.
Bước 3) Tăng tốc Tra cứu
Đối với việc giảm tìm kiếm, bạn sẽ cần tạo một số cấu trúc dữ liệu để nhóm các công thức nấu ăn cùng nhau và giúp tìm kiếm. Xử lý lưới như chuỗi cũng có một số lợi thế ở đây :
Bạn có thể định nghĩa "độ dài" của công thức là khoảng cách giữa ký tự không trống đầu tiên và ký tự không trống cuối cùng. Một đơn giản Trim().Length()
sẽ cung cấp cho bạn thông tin này. Bí quyết có thể được nhóm theo chiều dài và được lưu trữ trong một từ điển.
hoặc là
Một định nghĩa khác về "độ dài" có thể là số lượng ký tự không trống. Không có gì khác thay đổi. Bạn có thể nhóm công thức nấu ăn theo tiêu chí này quá.
Nếu điểm số 1 là không đủ, công thức nấu ăn cũng có thể được nhóm lại theo loại thành phần đầu tiên xuất hiện trong công thức. Điều này sẽ đơn giản như làm Trim().CharAt(0)
(và bảo vệ chống lại Trim dẫn đến một chuỗi rỗng).
Vì vậy, ví dụ bạn sẽ lưu trữ các công thức nấu ăn trong:
Dictionary<int, Dictionary<char, List<string>>> _recipes;
Và thực hiện tra cứu như một cái gì đó như:
// A string encode of your current grid configuration
string grid;
// Get length and first char in our grid
string trim = grid.Trim();
int length = trim.Length();
char firstChar = length==0 ? ' ' : trim[0];
foreach(string recipe in _recipes[length][firstChar])
{
// Check for a match with the recipe
if(Regex.Match(grid, recipe))
{
// We found a matching recipe, do something with it
}
}