Saya akan menawarkan beberapa saran. Beberapa dari mereka saling bertentangan. Tapi mungkin ada yang bermanfaat.
Pertimbangkan daftar versus bendera
Anda dapat mengulangi dunia dan memeriksa bendera pada setiap item untuk memutuskan apakah akan melakukan hal bendera. Atau Anda dapat menyimpan daftar hanya barang-barang yang harus melakukan hal bendera.
Pertimbangkan daftar & enumerasi
Anda dapat terus menambahkan bidang boolean ke kelas item Anda, isAThis dan isAThat. Atau Anda dapat memiliki daftar elemen string atau enum, seperti {"isAThis", "isAThat"} atau {IS_A_THIS, IS_A_THAT}. Dengan begitu Anda bisa menambahkan yang baru di enumerasi (atau string const) tanpa menambahkan bidang. Bukannya ada yang salah dengan menambahkan bidang ...
Pertimbangkan fungsi pointer
Alih-alih daftar bendera atau enum, bisa memiliki daftar tindakan untuk mengeksekusi untuk item itu dalam konteks yang berbeda. (Entitas-ish ...)
Pertimbangkan benda
Beberapa orang lebih suka pendekatan berbasis entitas data, atau skrip, atau komponen. Tapi hierarki benda kuno juga patut dipertimbangkan. Kelas dasar perlu menerima tindakan, seperti "mainkan kartu ini untuk fase-B" atau apa pun. Kemudian setiap jenis kartu dapat menimpa dan merespons sebagaimana mestinya. Mungkin ada objek pemain dan objek game juga, sehingga game dapat melakukan hal-hal seperti, if (player-> isowedToPlay ()) {do the play…}.
Pertimbangkan kemampuan debug
Satu hal yang menyenangkan tentang setumpuk bidang bendera adalah Anda dapat memeriksa & mencetak kondisi setiap item dengan cara yang sama. Jika keadaan diwakili oleh berbagai jenis, atau kantong komponen, atau pointer fungsi, atau berada di daftar yang berbeda, mungkin tidak cukup hanya dengan melihat bidang item. Ini semua kompromi.
Akhirnya, refactoring: Pertimbangkan tes unit
Tidak peduli seberapa besar Anda menggeneralisasikan arsitektur Anda, Anda akan dapat membayangkan hal-hal yang tidak tercakup. Maka Anda harus refactor. Mungkin sedikit, mungkin banyak.
Cara untuk membuat ini lebih aman adalah dengan tes unit. Dengan begitu Anda dapat yakin bahwa meskipun Anda menata ulang hal-hal di bawahnya (mungkin banyak!), Fungsionalitas yang ada masih berfungsi. Setiap unit tes terlihat, secara umum, seperti ini:
void test1()
{
Game game;
game.addThis();
game.setupThat(); // use primary or backdoor API to get game to known state
game.playCard(something something).
int x = game.getSomeInternalState;
assertEquals(“did it do what we wanted?”, x, 23); // fail if x isn’t 23
}
Seperti yang Anda lihat, menjaga agar panggilan API tingkat atas agar game (atau pemain, kartu, & c) tetap stabil adalah kunci strategi pengujian unit.