Ωραίος!
Προφανώς, χρειάζεται πλέον να τριφτείς γράφοντας κώδικα. Μιλάμε πάντα για κονσόλα, γιατί για GUI θα πρέπει να ξαναδιαβάσεις πάλι (την τεκμηρίωση του εκάστοτε API). Το βιβλίο καλύπτει μονάχα τα βασικά της γλώσσας και των στάνταρ βιβλιοθηκών της.
Μια ιδέα είναι να ξαναφτιάξεις το address-book και το παιχνίδι με τα χαρτιά, σε C. Καλύτερα το παιχνίδι με τα χαρτιά (ή κάποιο άλλο, αν βαριέσαι το ίδιο), γιατί console-based address-book δεν νομίζω να το χρησιμοποιήσει κανείς

(εκτός αν θες να το κάνεις απλώς για να δυναμώσεις το προγραμματιστικό σου υπόβαθρο σε C).
Το βασικό τώρα κατά την άποψή μου είναι να τριφτείς στη χρήση των struct/enum/πινάκων (προφανώς σε συνδυασμό με τη χρήση δεικτών & δυναμικής διαχείρισης μνήμης, αλλά όχι απαραίτητα από το 1ο κιόλας project).
Θα μπορούσες για παράδειγμα να αναβαθμίσεις το Hunt ώστε να είναι αλληλοεπιδραστικό. Δηλαδή ας πούμε να εμπλουτίσεις/ζωντανέψεις την σκηνή στην οποία εξελίσσεται η δράση, βάζοντας για παράδειγμα "διάθεση" (mood) στο κάθε ζώο... π.χ. επιθετικό, φοβισμένο, ουδέτερο. Αν είναι επιθετικό θα μπορεί να επιτίθεται στον παίκτη μέσα σε 1-2 κινήσεις αν δεν το έχει πυροβολήσει. Αν είναι φοβισμένο να φεύγει από την σκηνή μετά από 1-2 κινήσεις (οπότε ο παίκτης θα χάνει την ευκαιρία να το συλλάβει).
Μπορείς να σκεφτείς 1002 ακόμα πράγματα για να εμπλουτίσεις το Hunt. Προσθήκη αντικειμένων που θα μπορεί να μαζέψει για να χρησιμοποιήσει ο παίκτης, όπως το χρυσάφι που σκέφτηκες, ή ας πούμε διάφορα είδη όπλων διαφορετικής δυναμικής/εμβέλειας κλπ... ας πούμε: σφεντόνα, ακόντιο, δίκανο, καραμπίνα.
Θα μπορούσες επίσης να προσθέσεις health στον παίκτη, που θα του την "τρώνε" ζώα που θα του επιτίθενται (πάνω σε αυτό θα μπορούσες να προσθέσεις και "attacking power" στο κάθε ζώο, ώστε το καθένα να προκαλεί διαφορετικού μεγέθους ζημιά).
Και... και... και... η λίστα είναι ατέλειωτη!
Αν αποφασίσεις να ασχοληθείς με κάτι σαν το παραπάνω, θα "αναγκαστείς" να μάθεις πως μπορείς να κάνεις Object Oriented προγραμματισμό με C. Εννοώ περισσότερο ως οργάνωση του κώδικα, σε αρχεία, δομές, κλπ, και όχι στο να προσπαθήσεις να μιμηθείς επακριβώς τις υλοποιήσεις κλάσεων, πολυμορφισμού, κληρονομικότητας, κλπ των OOP γλωσσών (κάτι τέτοιο προϋποθέτει εμπειρία που αυτή τη στιγμή σου λείπει).
Θα σου δώσω ένα απλό παράδειγμα, για να καταλάβεις περίπου τι εννοώ. Ας πούμε ότι για κάθε ζώο θέλεις να υπάρχουν γενικά χαρακτηριστικά που θα ισχύουν πάντα (typeid, name, description, attacking power) καθώς και χαρακτηριστικά που θα μεταβάλλονται ανά σκηνή (health, mood, distance from player).
Μπορείς λοιπόν να έχεις το βασικό struct όλων σου των ζώων (την base-class σύμφωνα με την OOP ορολογία)
AnimalType ...
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
/* */
enum AniTypeId {
ATID_INVALID = -1,
ATID_BEAR,
ATID_DEER,
ATID_DUCK,
ATID_FERRET,
ATID_FOX,
ATID_RABBIT,
ATID_RACOON,
ATID_WLDBOAR,
ATID_WOLF,
MAX_ANIMALTYPES
};
/** Base class for all animals **/
typedef struct AnimalType {
enum AniTypeId id;
char *name;
int attpower; /* 50 to 100 */
char *desc;
}AnimalType;
Κατόπιν μπορείς να φτιάξεις μια άλλη δομή,
SceneAnimal που θα "κληρονομεί" τα γενικά χαρακτηριστικά της
AnimalType και θα προσθέτει τα πιο εξειδικευμένα για την (εκάστοτε) σκηνή...
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
typedef enum ScenAniMood { SAM_SCARED = -1, SAM_NEUTRAL, SAM_AGGRESSIVE } ScenAniMood ;
/** extends AnimalType class **/
typedef struct SceneAnimal {
AnimalType type; /* general characteristics of a SceneAnimal (inhereted from AnimalType) */
int id; /* for identification in the scene */
ScenAniMood mood;
int health; /* 0 to 100 */
int dist; /* distance from player */
} SceneAnimal;
Κατόπιν η δομή της (εκάστοτε) σκηνής...
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
typedef struct Scene {
int nanimals; /* number of animals in scene */
SceneAnimal *animals; /* will be allocated dynamically to nanimals * sizeof(SceneAnimal) */
} Scene;
Στην main() θα αρχικοποιείς έναν πίνακα με όλους του τύπους ζώων, και θα ορίζεις και μια μεταβλητή για την σκηνή,
π.χ...
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
#define MAX_SCENE_ANIMALS 4
int main( void )
{
AnimalType attable[ MAX_ANIMALTYPES ] = {
/* .id .name .attpower .desc */
{ ATID_BEAR, "bear", 100, "a general bear description goes here" },
{ ATID_DEER, "deer", 75, "a general deer description goes here"},
{ ATID_DUCK, "duck", 50, "a general duck description goes here" },
{ ATID_FERRET, "ferret", 55, "a general ferret description goes here" },
{ ATID_FOX, "fox", 60, "a general fox description goes here" },
...
{ ATID_WOLF, "wolf", 90, "a general wolf description goes here" }
};
Scene scene = {0, NULL};
...
Στη ρουτίνα που θα χτίζει την σκηνή όταν ξεκινάει το game, θα περνάς by-reference την μεταβλητή
scene. Μέσα στη ρουτίνα θα παράγεις τυχαία έναν αριθμό από 0 έως MAX_SCENE_ANIMALS για το:
scene->nanimals και θα δεσμεύεις χώρο για τόσα ζώα στη σκηνή.
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
scene->nanimals = rand() % MAX_SCENE_ANIMALS;
scene->animals = calloc( scene->nanimals, sizeof(SceneAnimal) );
/* chack for calloc) failure here */
Κατόπιν, στην ρουτίνα που θα βάζει αρχικές τιμές στο κάθε ζώο της σκηνής, θα ξεκινάς παράγοντας έναν τυχαίο αριθμό από 0 έως MAX_ANIMAL_TYPES για το πεδίο:
type του κάθε SceneAnimal, και θα αντιγράφεις μέσα του τα γενικά χαρακτηριστικά του τύπου, κάνοντας indexing με τον τυχαίο που παρήγαγες τον πίνακα των τύπων... θα αντιγράφεις δηλαδή τα γενικά χαρακτηριστικά του ζώου από τον πίνακα των τύπων. Μετά θα βάζεις τιμές και στα υπόλοιπα, εξειδικευμένα για την σκηνή, χαρακτηριστικά (πεδία).
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
AniTypeId temp = ATID_INVALID;
for (int i=0; i < scene->nanimals; i++) {
temp = rand() % MAX_ANIMAL_TYPES;
memcpy( &scene->animals[i].type, &attable[temp], sizeof(AnimalType) );
/* init remaining fields of scene->animals[i] here */
}
Αν είσαι αρκετά ορεξάτος, μπορείς προφανώς να έχεις map από σκηνές ( έναν μικρό κόσμο δηλαδή, π.χ. έναν πίνακα από scenes) τις οποίες είτε θα τις αρχικοποιέις εξαρχής, ή μια-μια όταν την επισκέπτεται για 1η φορά ο παίκτης.
Αν αποφασίσεις να ασχοληθείς, μη κάνεις κόσμο γιατί θα χάσεις την μπάλα τελείως (επειδή αυτό προϋποθέτει και κίνηση σε κατευθύνσεις του ορίζοντα). Φτιάξε μια μόνο σκηνή, εμπλούτισέ την αν θες και με άλλα στοιχεία (π.χ. όπλα, λεφτά, κλπ) δίνε στον παίκτη έναν fixed αριθμό κινήσεων και μετά αντί για νέα σκηνή, κάνε randomize τα περιεχόμενα της ίδιας σκηνής (στο παραπάνω παράδειγμα, νέο πλήθος και είδος ζώων).
ΥΓ. Όλα τα παραπάνω τα προτείνω για να εντρυφήσεις στο C programming (και στο programming γενικότερα). Για τη δημιουργία adventures (text ή μη) υπάρχουν εξειδικευμένα Rapid Development Tools ή/και Γλώσσες (Π.χ. TADS3, Inform7, κλπ)