Λοιπόν, το έκανα... μόνο που δεν άφησα σχεδόν τίποτα ίδιο με το αυθεντικό, πέρα από το output και τον αλγόριθμο που υπολογίζει τα exact & approximate matches

Το ανέβασα στο migf1 branch, στο fork μου:
https://github.com/migf1/mastermind/tree/migf1 αλλά δεν σου έκανα pull-request γιατί υποπτεύομαι πως μάλλον δεν θα θέλεις να το κάνεις merge (επειδή αλλάζει σχεδόν ολόκληρο τον αρχικό σου κώδικα). Αν κάνω λάθος, πες μου να σου κάνω pull-request.
Δεν έχω τώρα άλλα κουράγια για να κάνω εξαντλητικές δοκιμές, οπότε αν έχεις όρεξη και κέφι κατέβασέ το και ζόρισέ το να δούμε τι θα βγάλει (έχω ήδη true το DEBUG directive μέσα στο mastermind.c και gcc debugging flags στο Makefile).
Η μεγάλη αλλαγή στον κώδικα προήλθε από την προσθήκη της"κλάσης" colors.h/colors.c η οποία παράγει βασικά ένα δυναμικό πίνακα χρωμάτων.
Το κάθε
χρώμα είναι μια κάπως πιο ευρεία έννοια, γιατί περιλαμβάνει
3 fields:
1.
labelΗ ετικέτα του χρώματος, η οποία πρέπει να περιέχει και τον χαρακτήρα '&' μπροστά από το γράμμα που θέλουμε να αντιπροσωπεύει το συγκεκριμένο χρώμα ως εντολή. Η public μέθοδος: colors_print_label_at_idx() που τυπώνει την ετικέτα, εσωκλείνει αυτόματα το εν λόγω γράμμα μέσα σε παρενθέσεις.
2.
codeΑυτό είναι το ascii-code του γράμματος που μέσα στο label έχει μπροστά του τον χαρακτήρα '&'... αυτό που περιγράφω παραπάνω, στο 1. Την μετατροπή από label σε ascii-code ουσιαστικά την κάνει η private μέθοδος: _label_to_code() την οποία χρησιμοποιεί ο constructor της κλάσης: new_colors()
3.
fgΤο χρώμα προσκηνίου με το οποίο γίνεται output στην κονσόλα οτιδήποτε συσχετισθεί με το συγκεκριμένο χρώμα της κλάσης (κανονικά πρέπει να μπει και background χρώμα εδώ, αλλά επειδή δεν είχες το παρέλειψα κι εγώ, και όταν τυπώνω δίνω BG_DEFAULT ως χρώμα φόντου).
Όταν γίνεται instantiate η κλάση (μέσω του constructor της, του new_colors() ) ΔΕΝ παράγει ένα μεμονωμένο χρώμα, αλλά έναν δυναμικό πίνακα με όλα τα διαθέσιμα χρώματα. Αυτό που κάνει λοιπόν expose publicly το colors.h είναι ένα enumeration (ονόματι:
enum ColorIdx) με τα indices των χρωμάτων στον δυναμικό πίνακα. Ο τύπος Color αυτός κάθε αυτός είναι opaque (private δηλαδή).
Για να δώσω ένα παράδειγμα, ας πούμε πως θέλουμε να φτιάξουμε έναν πίνακα από 4 χρώματα για να αποθηκεύουμε τα guesses το παίκτη...
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
...
#include "colors.h"
...
int main( void )
{
Color *colors = new_colors();
if ( NULL == colors ) {
exit(EXIT_FAILURE);
}
enum ColorIdx guess[4];
/* init to no-colors */
for (int i=0; i < 4; i++) {
guess[i] = IDX_NOCOLOR;
}
...
/* fill guess with 4 random color-indices */
for (int i=0; i < 4; i++) {
guess[i] = colors_get_random_index(colors);
}
/* print guess's color-indices as labels */
for (int i=0; i < 4; i++) {
colors_print_label_at_idx( colors, guess[i] );
putchar ( '\n' );
}
...
/* print the codes of the color-indices hosted in guess, printing them in their corresponding fg color */
for (int i=0; i < 4; i++) {
CONOUT_PUTCHAR(
colors_get_fg_at_idx( colors, guess[i] ),
BG_DEFAULT,
colors_get_code_at_idx( colors, guess[i] )
);
putchar ( '\n' );
}
...
colors_free( colors );
exit( EXIT_SUCCESS );
}
Εξωτερικά δηλαδή δουλεύουμε με color-indices του δυναμικού πίνακα από Color που έχει δημιουργήσει η new_colors() και με τις public μεθόδους που μας παρέχει.
Μια άλλη προσθήκη λοιπόν στον κώδικα, βασισμένη στα παραπάνω, είναι ο τύπος
MMCode που δεν είναι τίποτε άλλο από έναν πίνακα από NCOLS color-indices. Και για να μην τον γράφω συνέχεια έτσι, τον έχω κάνει typedef στο mastermind.c...
-
Μορφοποιημένος Κώδικας: Επιλογή όλων
-
typedef enum ColorIdx MMCode[NCOLS];
και του έχω φτιάξει ένα μίνι-interface επίσης μέσα στο mastermind.c... είναι οι συναρτήσεις που ξεκινάνε με:
mmcode_. Απλώς τέτοιου είδους typedefs θέλουν προσοχή, γιατί όταν περνιούνται ως ορίσματα σε συναρτήσεις, π.χ. foo( MMCode mmcode); περνάνε by reference επειδή πρόκειται για πίνακες. Αυτό με τη σειρά του σημαίνει πως αν μέσα στη συνάρτηση κάνουμε: sizeof( mmcode ) θα πάρουμε το μέγεθος του δείκτη και όχι όλου του πίνακα... για όλον τον πίνακα πρέπει να κάνουμε: sizeof( MMCode );
Αυτά είναι πάνω-κάτω τα βασικά για να μπορέσεις να περιηγηθείς πιο εύκολα στον κώδικα αν το θελήσεις. Συν ότι έχω χρησιμοποιήσει την τελευταία έκδοση του con_color.h που παρέχει δυνατότητα ορισμού μεταβλητών τύπου ConSingleColor και τύπου ConColors (αυτό το τελευταίο είναι pair από fg & bg χρώματα).
Το βλέπεις αν και όταν έχει όρεξη και χρόνο και μου λες αν θέλεις να σου κάνω pull-request ή όχι.