Ho un problema strutturale per un'applicazione su cui sto lavorando. Nell'interesse della piena divulgazione, è per un incarico universitario, quindi non sto cercando te per darmi una risposta, ma aiutami a pensare attraverso l'approccio migliore.
Sto costruendo un gioco usando un approccio OO. Ho una classe astratta chiamata Player da cui derivano diversi tipi. Questi rappresentano il computer e i giocatori umani. Quindi ho una classe HumanPlayer derivata che deve fornire un'implementazione per un metodo chiamato ChooseCard. Il modo in cui l'utente seleziona una carta è cliccando su una carta in una GUI. Quindi la carta verrà identificata dall'utente attraverso un gestore di eventi.
La parte rilevante del mio codice è elencata di seguito. Al momento la classe di gioco scorre attraverso ciascun giocatore e chiama il metodo PlayCard su ciascun giocatore. Non sono sicuro di come programmare il metodo ChooseCard nella classe HumanPlayer in modo che possa attendere che l'utente selezioni una scheda da riprodurre, ma l'interfaccia utente rimane reattiva. Idealmente, voglio essere in grado di trattare ciascuno dei tipi di giocatori derivati lo stesso (cioè come il giocatore della classe base).
Questa domanda chiede fondamentalmente la stessa cosa che io sono ma Non mi piacciono molto le risposte.
La risposta a questa domanda è interessante, utilizzando la classe TaskCompletionSource.
Non sono fisso su questa struttura se esiste una soluzione superiore, anche se devo mantenere la struttura della classe.
modifiche Aggiunto un diagramma di classe per i modelli della mia applicazione e uno screenshot di come appare il tabellone (al momento).
Ecco il mio pensiero attuale: L'utente farà clic sulla carta che desidera giocare. L'evento click si propagherà al CardViewModel associato (a questo punto l'azione potrebbe essere gestita al livello Model o ViewModel). Ora CardViewModel (o Card ) non sa chi è interessato a sapere che l'utente l'ha selezionato. La parte interessata sarà PlayerViewModel / HumanPlayer a cui appartiene la Card , ma saranno interessati solo quando si aspettano una risposta da parte dell'utente. Cioè quando viene chiamato HumanPlayer.PlayCard () .
Quindi penso che CardViewModel / Card dovrebbe generare un evento a cui l'oggetto HumanPlayer può iscriversi quando è interessato all'utente che effettua una selezione di carte .
Posso rendere HumanPlayer.ChooseCard () iscriversi agli eventi CardSelected di ognuna delle carte. Non sono sicuro di come far aspettare il metodo senza bloccare fino a quando uno di quegli eventi non viene attivato.
abstract public class Player
{
public IReadOnlyList<Card> Cards { get { return cards.AsReadOnly(); } }
public Card PlayCard()
{
var cardToPlay = ChooseCard();
// ...
}
protected abstract Card ChooseCard();
}
public class HumanPlayer : Player
{
protected override Card ChooseCard()
{
// TODO: request a card from the user.
throw new NotImplementedException();
}
}
public class Game
{
private List<Player> livingPlayers = new List<Player>();
public void PlayRound()
{
var cardsPlayedByPlayers = GetCardsPlayed();
// ...
}
private Dictionary<Player, Card> GetCardsPlayed()
{
var cardsPlayedByPlayers = new Dictionary<Player, Card>();
foreach (var player in livingPlayers.Where(p => !p.IsDead))
{
// Player.PlayCard() called here getting chosen card from the player.
cardsPlayedByPlayers.Add(player, player.PlayCard());
}
return cardsPlayedByPlayers;
}
}
Aggiornamento:
Ho messo il codice finale su GitHub qui da quando il compito è terminato. Ora puoi vedere chiaramente il codice completo e se vuoi criticarlo, sarei curioso di sentire i tuoi pensieri.