Dovrebbe usare il contatore, o flag all'interno degli oggetti, per indicare il progresso?

1

Ad esempio, ho un gioco, ha 5 nemici che attaccano una volta in sequenza ad ogni round:

class Enemy{
};

class Game{
public:
    Enemy enemys[5];
};

Voglio qualcosa per indicare quale nemico ha attaccato e quale no, ora ho 2 soluzioni:

1.add un contatore "enemyIndex" per indicare quale nemico sta attaccando, dopo che ogni nemico ha attaccato, il contatore "enemyIndex" automaticamente +1:

class Enemy{
};

class Game{
public:
    int enemyIndex;
    Enemy enemys[5];
};

2.each L'oggetto nemico aggiunge una bandiera "isAttacked", dopo che il nemico ha attaccato, il suo flag "isAttacked" contrassegnato da false a true:

class Enemy{
public:
    bool isAttacked;
};

class Game{
public:
    Enemy enemys[5];
};

quale è più ragionevole in termini di design pattern?

    
posta ggrr 02.10.2015 - 10:00
fonte

4 risposte

1

Un buon approccio potrebbe essere l'utilizzo di elenco collegato . È facile mantenere l'ordine, puoi aggiungere o rimuovere qualsiasi oggetto (creatura) in qualsiasi posto nell'elenco collegato.

Una demo:

              Last attacked
                |
c1 --> c2  --> c3 --> c4 --> c5 -
 ^                              |
 |------------------------------

Il giocatore colpisce c3 e lo ha ucciso

c1 --> c2  --x c3 --x c4 --> c5
^                      ^     |
|       | -------------|     |
|----------------------------

Verifica come next() dopo c3

           Current turn
               |
c1 --> c2 --> c4 --> c5
 ^                    |
 |--------------------|

Puoi anche conservare dati extra nei nodi oltre i dati del link. Puoi semplicemente seguire il link next() per ottenere il prossimo nodo. Rimuovi o aggiungi nodo ogni volta che vuoi.

    
risposta data 02.10.2015 - 10:34
fonte
1

Stai confondendo la classe del nemico, concentrandoti nell'eseguire qualsiasi cosa e tutto ciò che è relativo a quel particolare nemico con la sua rappresentazione nella classe di gioco.

La classe nemica dovrebbe sapere cosa significa attaccare, ma non dovrebbe interessarsi agli effetti in altre classi se non è un effetto diretto dell'attacco. In altre parole, un nemico potrebbe aver bisogno di eseguire alcune operazioni sul suo obiettivo, ma non avrebbe bisogno di conservare le informazioni di stato relative al fatto che non abbia già attaccato o meno.

Il chiamante dovrebbe saperlo e dovrebbe tenere traccia di ciò, e presumo che il chiamante sia la stessa classe di gioco. Se questo è il caso, allora la soluzione è semplice. La tua classe di gioco dovrebbe contenere due liste: una con un elenco di nemici che non hanno attaccato e un altro con un elenco di nemici che hanno. Crea un metodo privato nella tua classe di gioco che esegue la chiamata "attacco" per un nemico particolare. Dopo la chiamata, la rimuovi dall'elenco di nemici che non hanno attaccato e la aggiungi all'elenco dei nemici che hanno attaccato.

Le operazioni eseguite su tutti i nemici richiederebbero semplicemente due passaggi, uno per ciascuna lista.

Se la classe di gioco non chiama l'attacco di Enemy, allora Enemy richiederà un semplice sistema di gestione degli eventi che permetta ad altri oggetti di ascoltare. Il gioco sarà quindi iscritto all'evento di attacco di tutte le sue istanze nemiche. Quando si verifica un attacco, tiene traccia di quali nemici hanno attaccato e che non hanno utilizzato il sistema di elenchi di cui sopra.

Considera l'utilizzo del pattern del bus degli eventi per centralizzare tutti gli eventi nel tuo programma se senti la necessità di utilizzare molti eventi come questo. Avere un'istanza che consente a un chiamante di ascoltare o attivare un evento per nome. Quindi crei un nome "nemico.attaccante" per indicare un evento specifico per un nemico che attacca. Allo stesso modo puoi fare lo stesso per altri eventi.

Spero che questo aiuti!

    
risposta data 02.10.2015 - 10:45
fonte
1

È possibile incapsulare la logica di iterazione in un Iterator. Quindi chiamerai l'iteratore nella classe di gioco o creerai un elenco di nemici che restituiscono questo iteratore.

Game :: getAttackIterator () o EnemiesList :: getAttackIterator ()

Questo ti permette di incapsulare la logica di iterazione per l'attacco, per esempio se vuoi che i nemici vengano attaccati due volte in sequenza invece di una sola volta, cambieresti semplicemente l'implementazione dell'iteratore.

    
risposta data 06.10.2015 - 14:26
fonte
0

Solo enemyIndex soddisfa i criteri "che attacca una volta in sequenza"

Tuttavia, presumibilmente, vorrai variare il modello di attacco ad un certo punto. Per rendere tutto questo facile, aggiungerei ID univoci a ciascun nemico e passare un elenco di essi a una classe AI che conterrebbe la logica dell'ordine di attacco, creando un ordine dagli Id, tenendo traccia di chi ha attaccato e causandone ciascuno attacco a turno.

Cerca di evitare di cuocere la logica nelle tue strutture dati.

    
risposta data 02.10.2015 - 10:21
fonte

Leggi altre domande sui tag