Sto costruendo un gioco di slot machine per un cliente (soldi virtuali, non giochi a soldi veri). Hanno iniziato con un gioco di template e mi hanno assunto per reskin e apportare modifiche "minori" per una versione "rapida". Sfortunatamente, non ci sono freni sul trenino.
Il modello originale era molto semplice. Contare il numero di icone consecutive a partire da sinistra e controllare il valore nella tabella dei pagamenti. Ad esempio, se il giocatore fa girare "7 7 Chery Cherry 7", questo conta come due 7, quindi verifichiamo la tabella dei pagamenti per il valore (se ce ne sono) di ottenere due 7. C'erano anche alcuni casi speciali nel codice di valutazione per gestire icone speciali come Wild, Bonus e Scatter.
Icon
aveva inizialmente tre proprietà:
string name
Image image
IconType type (Normal, Wild, Bonus, or Scatter)
La tabella dei pagamenti è una tabella semplice con tre colonne
string name, int matches, int value
Una singola classe ProcessResult
gestisce i risultati per tutte le macchine; determina quale combinazione è emersa e (in base al tipo di icona) cerca il valore nella tabella dei pagamenti o applica un effetto speciale se la combinazione consiste di icone bonus o di dispersione.
Tuttavia, ogni volta che mi inviano le specifiche per una nuova macchina, il client aggiunge nuove funzionalità che non sono compatibili con il codice esistente. Ora abbiamo icone che non hanno bisogno di essere consecutive, icone che non devono iniziare a sinistra, icone che possono combinarsi con altri tipi di icone, icone che modificano il comportamento di altre icone, icone che modificano il comportamento generale della macchina, ecc. ecc.
Per un po 'stavo aggiungendo nuove proprietà alla classe Icon (ad esempio compatibleWithWilds
, startsFromLeft
, consecutiveOnly
), ma ora ha un sacco di proprietà che non si applicano alla maggior parte delle icone e al ProcessResult la classe è piena di casi problematici per gestire tutte queste proprietà. Sta diventando non mantenibile, e penso che sia ora di un refactoring, ma non sono sicuro di come affrontarlo.
Ho identificato diversi casi speciali che sono particolarmente problematici:
- Le icone che non hanno bisogno di essere consecutive o iniziano da sinistra aumentano notevolmente la complessità di determinare quale icona è considerata il "risultato" per lo spin
- Le icone che possono essere abbinate ad altre icone oltre a se stesse sono difficili da rappresentare nella tabella dei pagamenti corrente. Ad esempio, immagina uno slot a 3 rulli dove tre ciliegie pagano 5 volte, tre banane ne pagano 3 volte, ma una combinazione di ciliegie e banane paga 4 volte. La mia soluzione attuale è di assegnare loro un nome secondario con una voce separata nella tabella dei pagamenti (quindi ad esempio l'icona "ciliegia" conta come "ciliegia" o "frutto" e l'icona della banana conta come "banana" o "frutto", con "ciliegia" "banana" e "frutto" tutti elencati separatamente nella tabella dei pagamenti).
- Alcune icone speciali di solito non hanno alcun valore di retribuzione intrinseco (ad es. "Bonus", che attiva qualche tipo di minigioco o di stato macchina alternativo) e quindi non possiamo cercare quante corrispondenze sono richieste nella tabella dei pagamenti. In questo momento la macchina ha proprietà generiche come "minBonusMatches", ma ciò significa che alcune macchine hanno proprietà per i tipi di icone che in realtà non usano e non funzionerebbero se il client avesse introdotto un secondo tipo di un'icona speciale su qualche macchina (es. "Match 3 delle icone Bonus per un bonus normale o 5 delle icone Super Bonus per un super bonus")
Non sono sicuro di come progettare l'architettura in un modo che possa facilmente adattarsi a qualsiasi nuova regola pazza che il cliente pensa. Sicuramente non voglio continuare a costruire sul groviglio attuale di% nidificato% che gestisce tutti i casi limite. Sono abbastanza sicuro non voglio scrivere una classe separata "ProcessResult" per ogni macchina, perché penso che sia confusa e incoraggi probabilmente la duplicazione del codice. Ho preso in considerazione l'estensione della classe Icon con classi figlio che definiscono la propria logica, ma penso che diventerà disordinato, e sembrerebbe come caricare la responsabilità nel posto sbagliato (le icone avrebbero quindi bisogno di sapere tutto sullo stato del gioco, che sembra indietro).
Esiste un modello o un'architettura particolare che si adatta bene qui? Il meglio che ho adesso è una vaga idea di usare qualcosa come il pattern di componenti per assegnare proprietà alle icone e alimentarle attraverso una catena di responsabilità, ma ho problemi a pensare a un'implementazione concreta, come il vecchio detto va, non può vedere la foresta per i casi limite.
Il client ignora tutti i consigli, quindi qualsiasi risposta che implichi dare consigli al client in merito allo scope creep o alla gestione del progetto è inutile