Vedere se una determinata configurazione di griglia corrisponde a una determinata ricetta è semplice se si codifica la griglia 3x3 come stringa e si utilizza una corrispondenza di espressioni regolari . Accelerare lo sguardo è una questione diversa, di cui parlerò alla fine. Continua a leggere per ulteriori informazioni.
Passaggio 1) Codifica la griglia come stringa
Basta dare un carattere char ad ogni tipo di cella e concatenare tutto fianco a fianco in questo ordine:
123
456 => 123456789
789
E come esempio più concreto, considera la ricetta del bastone, dove W sta per legno ed E è una cella vuota (potresti semplicemente usare un carattere vuoto ''):
EEE
WEE => EEEWEEWEE
WEE
Passaggio 2) Abbina la ricetta usando l'espressione regolare (o String.Contains con un po 'di elaborazione sui dati)
Continuando dall'esempio sopra, anche se spostiamo la formazione in giro, c'è ancora un motivo nella stringa (WEEW imbottito da E su entrambi i lati):
EEW
EEW => EEWEEWEEE
EEE
Quindi, indipendentemente da dove sposti il bastoncino, corrisponderà comunque alla seguente espressione regolare: /^E*WEEWE*$/
Le espressioni regolari ti consentono anche di eseguire il comportamento condizionale che hai citato. Ad esempio (ricetta preparata), se si desidera che un piccone fatto di ferro o pietra dia lo stesso risultato, ovvero:
III SSS
EWE or EWE
EWE EWE
È possibile combinare entrambi nell'espressione regolare: /^(III)|(SSS)EWEEWE$/
I flip orizzontali possono anche essere aggiunti altrettanto facilmente (usando anche l'operatore |).
Modifica: in ogni caso, la parte regex non è strettamente necessaria. È solo un modo per incapsulare il problema in una singola espressione Ma per il problema della posizione variabile potresti anche tagliare la stringa della griglia di qualsiasi spazio di riempimento (o E in questo esempio) e fare un String.Contains (). E per il problema degli ingredienti multipli o le ricette speculari, potresti semplicemente gestirle tutte come ricette multiple (cioè separate) con lo stesso risultato.
Passaggio 3) Accelerare la ricerca
Per quanto riguarda la riduzione della ricerca, dovrai creare una struttura di dati per raggruppare le ricette e aiutare con la ricerca. Trattare la griglia come stringa presenta anche alcuni vantaggi :
È possibile definire la "lunghezza" di una ricetta come la distanza tra il primo carattere non vuoto e l'ultimo carattere non vuoto. Un semplice Trim().Length()
ti darebbe queste informazioni. Le ricette possono essere raggruppate per lunghezza e memorizzate in un dizionario.
o
Una definizione alternativa di "lunghezza" potrebbe essere il numero di caratteri non vuoti. Nient'altro cambia. Puoi anche raggruppare le ricette secondo questi criteri.
Se il punto numero 1 non è sufficiente, le ricette possono anche essere ulteriormente raggruppate in base al tipo del primo ingrediente che appare nella ricetta. Questo sarebbe semplice come fare Trim().CharAt(0)
(e proteggersi da Trim risultante in una stringa vuota).
Quindi, ad esempio, dovresti conservare le ricette in un:
Dictionary<int, Dictionary<char, List<string>>> _recipes;
Ed esegui la ricerca come qualcosa di simile:
// 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
}
}