Προς το περιεχόμενο

Position wrap mapping


Προτεινόμενες αναρτήσεις

Δημοσ.

Αν το έχει κάποιος πιο πρόχειρο από μένα, ας βοηθήσει (μπας και γλιτώσω λίγο χρόνο) γιατί κόλλησα πάλι...

 

Σε ένα τραπέζι πόκερ Texas Hold'em μπορούν να παίξουν από 2 έως και 10 παίκτες, ενώ γενικώς υπάρχουν 6 ονοματισμένες (labeled) θέσεις στο τραπέζι, ως εξής:

 

Cutoff

Dealer (ή Button)

Small Blind

Big Blind

Under the gun

Other

 

ας πούμε για συντομία...

 

>
char g_seatLabels[] = {'C', 'D', 'S', 'B', 'U', 'O'};

 

O Cutoff είναι πάντα ο προηγούμενος του dealer (ο αμέσως δεξιά του δηλαδή στο τραπέζι, in real life) ενώ οι SB, BB και U είναι οι αμέσως επόμενοι (δλδ οι αμέσως αριστερά του dealer). "Other" είναι οποιαδήποτε άλλη θέση.

 

Τα δεδομένα που δίνονται είναι:

 

α) πλήθος παικτών

β) θέση του dealer

γ) θέση του παίκτη

 

και καλούμαι να υπολογίσω το label του παίκτη.

 

Δηλαδή, αν μας δοθούν ας πούμε...

>
α) πλήθος παικτών = 9
β) θέση του dealer = 2
γ) θέση του παίκτη = 6

τότε πρέπει να επιστρέψουμε ως label του παίκτη το 'O' (δλδ label-index = 5).

 

Αν μας δοθεί π.χ...

>
α) πλήθος παικτών = 9
β) θέση του dealer = 9
γ) θέση του παίκτη = 2

τότε πρέπει να επιστρέψουμε ως label του παίκτη το 'Β' (δλδ label-index = 3).

 

και πάει λέγοντας.

 

Σημειώστε πως το nplayers μεταβάλλεται από 2 έως και 10.

 

Το spoiler που ακολουθεί είναι για όποιον ενδιαφέρεται να βοηθήσει λίγο παραπάνω, μιας και βάζει κι άλλο παράγοντα στο πρόβλημα (τους out-of-hand players).

 

 

 

Τα εκτός του spoiler, παραπάνω, είναι λίγο απλοποιημένα.

 

Όχι μόνο δεν παίρνω τα δεδομένα έτοιμα (πρέπει να τα κάνω extract από file συγκεκριμένης δομής) αλλά μπορεί να μου έχει και out-of-hand players, οι οποίοι πρέπει να αφαιρεθούν από το nplayers πριν ξεκινήσω να υπολογίζω το label του παίκτη.

 

Παραθέτω ένα παράδειγμα από σχετικό απόσπασμα ενός τέτοιου file, από το οποίο καλούμαι να υπολογίσω αυτό που περιέγραψα παραπάνω...

 

>
Table '607754190 3' 9-max Seat #9 is the button
Seat 1: ecomaniac87 (2095 in chips) out of hand (moved from another table into small blind)
Seat 2: eagle_slb114 (3400 in chips)
Seat 3: fackyd (3000 in chips)
Seat 4: mr.24/h (3800 in chips)
Seat 5: Mr. AT_159 (5800 in chips)
Seat 6: betgenius78 (6000 in chips)
Seat 7: JACCATWIN (10760 in chips)
Seat 8: npapale (22295 in chips)
Seat 9: localboy0935 (4485 in chips)
eagle_slb114: posts small blind 75
fackyd: posts big blind 150

 

Όπως βλέπουμε, επειδή ο ecomaniac87 είναι out-of-hand, δεν λαμβάνεται υπόψη στον υπολογισμό. Δηλαδή το SmallBlind (που πάντα έπεται του dealer... τον λέει Button τον Dealer, το ίδιο πράγμα είναι) δεν είναι ο ecomaniac87 αλλά ο eagle_slb114 (το αναγράφει αμέσως μετά από την λίστα των παικτών).

 

Παρεμπιπτόντως, ούτε τον παίκτη τον έχουμε έτοιμο... τον περνάμε ως παράμετρο στον parser μας για να τον υπολογίσει από την λίστα.

 

Π.χ. Μια parse_round( plrname, blabla) ... με κλήση: parse_round( "betgenius78", blabla) τραβάει από την λίστα το δεδομένο γ) που παρέθεσα πριν από το spoiler (δηλαδή τη θέση του παίκτη, που ισούται με 6 σε αυτό το παράδειγμα)

 

Τέσπα, αυτό το τελευταίο (και πολλά άλλα) τα έχω κάνει, αλλά έχω κολλήσει σε αυτό με τα labels (συμπεριλαμβανομένου και το θέματος με όσους εμφανίζονται ως out-of-hand στη λιστα).

 

 

  • Απαντ. 30
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Δημοφιλείς Ημέρες

Συχνή συμμετοχή στο θέμα

Δημοσ.

Γιατί δεν κάνεις έναν unsigned char array με size 9 (από 0 έως 8) που να είναι οι θέσεις του τραπεζιού και έναν unsigned char* array με size 5 (από 0 έως 4) και κάθε φορά που θα θες να κάνεις allocate τους ρόλους απλά θα αλλάζεις την τιμή που θα έχουν τα στοιχεία του, όπου η τιμή θα είναι το index για τον array με τις θέσεις του τραπεζιού.

 

Βέβαια, εάν έχεις λιγότερους από 5 παίχτες, θα πρέπει να φροντίσεις τι γίνεται με τους ρόλους. Επίσης, εάν θες να κρατάς και τον ρόλο σε κάθε θέση και να μην έχεις αλληλοεξαρτήσεις, μπορείς να τα κλείσεις σε ένα struct (π.χ.).

 

Ακόμα καλύτερα, ο πίνακες με τις θέσεις του τραπεζιού θα μπορούσε να είναι void* (με το απαραίτητο NULL setting όταν δεν κάθεται κανείς σε κάποια θέση), να δείχνει εκεί που έχεις την ονομασία του παίχτη και να τον κάνεις index σύμφωνα με τα indices από τον πίνακα με τα roles.

 

Ακόμα καλύτερα, το όλο table θα μπορούσε να είναι ένας 2D array void*, κάτω να έχεις unsinged chars (όπου θα μετατρέπεις το void* σε unsiged char*) και πάνω τις διευθύνσεις για τα ονόματα. Έτσι, με ένα απλό lookup στην κάτω σειρά, θα μπορείς να έχεις και το πού δείχνει η πάνω και όλα αυτά σε μία μεταβλητή. Έτσι, κάποιος other απλά θα έχει != NULL στην πάνω σειρά και NULL στην κάτω. Επίσης, εάν αύριο θες να επεκτείνεις τους ρόλους, απλά αντί να κάνεις μετατροπή τον void*, τον βάζεις να δείχνει εκεί που θα είναι οι νέοι ρόλοι σου.

Δημοσ.

Άμα πω πως κατάλαβα, ψέμματα θα είναι :lol:

 

Βασικά αυτό που με ενδιαφέρει να κρατήσω από αυτό το απόσπασμα του αρχείου που παρέθεσα στο spoiler, είναι 2 πράγματα:

 

α) σε πόσους παίκτες μοιράστηκαν χαρτιά, δηλαδή τους Χ-max στην 1η γραμμή μείον τους out-of-hand της λίστας που ακολουθεί (που είναι trivial και προφανώς το έχω κάνει ήδη)

 

β) το label της θέσης του (εκάστοτε περασμένου ως όρισμα στον parser) παίκτη.

 

Έχω κολλήσει (άσχημα κιόλας) στο β) ... αυτό που μου προτείνεις, μπορείς να δώσεις ένα πρόχειρο παράδειγμα σε κώδικα; Γιατί οκ τα 2 tables (που ιδανικά θα ήθελα να τα αποφύγω, αλλά δεν με χαλάνε κιόλας) αλλά από εκεί και πέρα πως το εννοείς.

 

Έχουμε σκανάρει πες τις γραμμές του αρχείου κι έχουμε κρατήσει σε μεταβλητές, ας πούμε...

 

>
int nplayers;   // = max - n_out_of_hand
int buttonSeat; // μας το δίνει έτοιμο
int playerSeat; // το τραβάμε από την γραμμή της λίστας που έχει το όνομα του παίκτη

 

Πες ότι έχουμε και τα 2 arrays που λες...

 

>
uint8_t g_tableSeats[10];
uint8_t g_seatLabels[6];  // C, D, S, B, U, O

 

Τον g_tableSeats[] υποθέτω εννοείς να τον γεμίζω διαβάζοντας τις θέσεις των παικτών από τη λίστα του αρχείου; Αν ναι, με τι. Και μετα τι :lol:

 

Δημοσ.

Εφόσον έχουμε να κάνουμε με κάτι που πάει "κυκλικά" προφανώς αυτό που χρειάζεται είναι modulo operator. Απο κει και πέρα το μόνο που θέλει σκέψη είναι το ποιό θα είναι το πρώτο όρισμα.

 

>int numPlayers = 10, playerPos, dealerPos, playerIndex;
char seatLabels[] = {'C', 'D', 'S', 'B', 'U', 'O', 'O', 'O', 'O', 'O' }; // numPlayers items

for (playerPos = 0; playerPos < numPlayers; ++playerPos) {
for (dealerPos = 0; dealerPos < numPlayers; ++dealerPos) {
 playerIndex = (playerPos - dealerPos + numPlayers + 1) % numPlayers;
printf("When the dealer is at #%d and the player at #%d his seat is labeled %c\n",
		 dealerPos + 1, playerPos + 1, seatLabels[playerIndex]);
}
}

 

http://ideone.com/G8a77

 

Ο πίνακας πρέπει να έχει τουλάχιστον numPlayers στοιχεία και αν θέλεις να δουλεύει για οποιοδήποτε αριθμό παικτών (μέχρι και 1) τότε πρέπει τα labels να εμφανίζονται με τη σειρά που μπαίνουν οι παίκτες στο παιχνίδι (άρα προφανώς ο D πρέπει να είναι πρώτος γιατί χωρίς dealer λίγο δύσκολο), στην οποία περίπτωση θα πρέπει το C να πάει στο τέλος και το +1 στο playerIndex να φύγει (γιατί είναι το offset του dealer μέσα στα labels). Άρα για οποιοδήποτε αριθμό παικτών:

 

>int numPlayers = 10, playerPos, dealerPos, playerIndex;
char seatLabels[] = {'D', 'S', 'B', 'U', 'O', 'O', 'O', 'O', 'O', 'Ο' }; // numPlayers items
if (numPlayers > 1) seatLabels[numPlayers - 1] = 'C';

for (playerPos = 0; playerPos < numPlayers; ++playerPos) {
   for (dealerPos = 0; dealerPos < numPlayers; ++dealerPos) {
    playerIndex = (playerPos - dealerPos + numPlayers) % numPlayers;
    printf("When the dealer is at #%d and the player at #%d his seat is labeled %c\n",
		 dealerPos + 1, playerPos + 1, seatLabels[playerIndex]);
   }
}

 

Not tested.

Δημοσ.

Καταρχήν ευχαριστώ για την άμεση απάντηση. Believe it or not, εκεί που είχα κολλήσει ήταν στο...

 

>
playerIndex = (playerPos - dealerPos + numPlayers + 1) % numPlayers;

 

αυτό δλδ δεν μπορούσα να υπολογίσω !!! (που είναι το :ashamed: smiley? )

 

Με ένα πολύ πρόχειρο τεστ που του έκανα (με βομβαρδίζουν από 10 μεριές διάφορες δουλειές) η 1η σου απάντηση φαίνεται να με εξυπηρετεί... (βασικά την 2η δεν έχω προλάβει ακόμα να την δω).

 

>
#include <stdio.h>
#include <stdlib.h>

#define MAX_PLAYERS    10
#define MIN_PLAYERS    2

/* -------------------------------------------------------
*
* -------------------------------------------------------
*/
int calc_seatLabelIndex( int nplayers, int dealerPos, int playerPos )
{
   if ( playerPos < 1 || playerPos > MAX_PLAYERS
   || nplayers < MIN_PLAYERS || nplayers > MAX_PLAYERS
   || playerPos > nplayers )
       return MAX_PLAYERS;

   return (playerPos - dealerPos + nplayers + 1) % nplayers;

}

/* -------------------------------------------------------
*
* -------------------------------------------------------
*/
int main( void )
{
   char seatLabels[ MAX_PLAYERS+1] = {'C', 'D', 'S', 'B', 'U', 'O', 'O', 'O', 'O', 'O', '?' };
   int nplayers = 5;
   int dealerPos = 1;
   int playerPos = 6;
   int seatLabelIndex = MAX_PLAYERS;

   for (int i=0; i < MAX_PLAYERS; i++ )
       putchar( seatLabels[i] );
   putchar('\n');

   printf( "nplayers : %d\n", nplayers );
   printf( "dealerPos: %d\n", dealerPos );
   printf( "playerPos: %d\n", playerPos );

   seatLabelIndex = calc_seatLabelIndex( nplayers, dealerPos, playerPos );
   printf( "player seatLabel: %c (%d)\n\n", seatLabels[seatLabelIndex], seatLabelIndex );

   system("pause");
   exit( EXIT_SUCCESS );
}

χμ... μήπως το modulo θέλει με MAX_PLAYERS instead? (που είναι το :hm: smiley? )

 

Θα τα κοιτάξω ξανά με ησυχία (και το edit που έκανες) κι αν χρειαστώ κάτι, θα επανέλθω.

 

Thanks και πάλι.

 

 

 

Τσάμπα έχει πάει σχεδόν ο μισός parser :(

Μόλις πήρα νέα files που εμφανίζουν δομικές διαφορές :( :( :( :( :( :(

 

 

Δημοσ.

Άμα πω πως κατάλαβα, ψέμματα θα είναι :lol:

 

Βασικά αυτό που με ενδιαφέρει να κρατήσω από αυτό το απόσπασμα του αρχείου που παρέθεσα στο spoiler, είναι 2 πράγματα:

 

α) σε πόσους παίκτες μοιράστηκαν χαρτιά, δηλαδή τους Χ-max στην 1η γραμμή μείον τους out-of-hand της λίστας που ακολουθεί (που είναι trivial και προφανώς το έχω κάνει ήδη)

 

β) το label της θέσης του (εκάστοτε περασμένου ως όρισμα στον parser) παίκτη.

 

Έχω κολλήσει (άσχημα κιόλας) στο β) ... αυτό που μου προτείνεις, μπορείς να δώσεις ένα πρόχειρο παράδειγμα σε κώδικα; Γιατί οκ τα 2 tables (που ιδανικά θα ήθελα να τα αποφύγω, αλλά δεν με χαλάνε κιόλας) αλλά από εκεί και πέρα πως το εννοείς.

 

Έχουμε σκανάρει πες τις γραμμές του αρχείου κι έχουμε κρατήσει σε μεταβλητές, ας πούμε...

 

>
int nplayers; // = max - n_out_of_hand
int buttonSeat; // μας το δίνει έτοιμο
int playerSeat; // το τραβάμε από την γραμμή της λίστας που έχει το όνομα του παίκτη

 

Πες ότι έχουμε και τα 2 arrays που λες...

 

>
uint8_t g_tableSeats[10];
uint8_t g_seatLabels[6]; // C, D, S, B, U, O

 

Τον g_tableSeats[] υποθέτω εννοείς να τον γεμίζω διαβάζοντας τις θέσεις των παικτών από τη λίστα του αρχείου; Αν ναι, με τι. Και μετα τι :lol:

 

 

Ο g_tableSeats θα είναι ένας 2D pointer array.

 

Κάθε στοιχείο της πρώτη γραμμής θα δείχνει στα ονόματα των παιχτών ή θα είναι NULL εάν δεν υπάρχει παίκτης.

 

Τα στοιχεία της 2ης γραμμής είτε θα έχουν έναν από τους άλλους ρόλους είτε θα είναι NULL (όπου NULL είναι other, δηλαδή θα είναι ο g_seatsLabel).

 

Θα μπορείς να πλοηγείσαι από το όνομα στον ρόλο και από τον ρόλο στο όνομα. Το εάν κάθετε κάποιος σε μία θέση, το έχεις από το NULL της 1ης γραμμής του g_tableSeats.

 

Ακόμα καλύτερα, θα μπορούσες να τα βάλεις σε structs για να έχεις και έλεγχο μέσα στα structs για την εισαγωγή και την προσπέλαση (σαν κλάσεις). Όπου εκεί έχεις σε διάκριτα πεδία τις θέσεις και σε κάθε μία μπορείς να έχεις ένα struct που να έχει εάν κάθεται κανείς, το όνομά του και τον ρόλο του.

 

Π.χ.

 

>
typedef struct theSeatStructr{
 char*         theName;
 unsigned char  isOccupied;
 unsinged char  theRole;
}Seat, *pSeat;

 

Και έτσι, το τελικό σου struct θα είναι:

 

>
typedef int (*pfcn_populateSeat) (int seatIndex, char* theName);
typedef void (*pfcn_getName) (int seatIndex, char** theName, int* namesLength);
typedef unsigned char (*pfcn_getRole) (int seatIndex);
typedef unsigned char (*pfcn_getSeat) (void* theIndex, ...);
typedef void (*pfcn_newHand) (void);

typedef struct theTableStruct{
 pfcn_populateSeat populateSeat;
 pfcn_getRole       getRole;
 pfcn_getSeat       getSeat;
 pfcn_newHand       newHand;
 unsigned int       currentPlayers;
 pSeat           theSeats;
}Table, *pTable;

 

edit:

Sorry για το brainstorming :P

 

Ελπίζω να μην σε μπέρδεψα παραπάνω.

 

edit:

Ξέχασα να βάλω και τις functions για την αλλαγή ρόλων..

 

edit:

Και ένας "int" για γρήγορη εύρεση του πόσοι παίζουν τώρα.

Δημοσ.

Thanks ρε συ timon, δεν ήταν brain-storming. Πολύ ενδιαφέρον (και generic :) ) αλλά επίσης ολίγον overkill για τη δουλειά που το θέλω.

 

Τραβάω κι άλλες πληροφορίες μέσα από το αρχείο (έχει προφανώς κι άλλα περιεχόμενα) ... τα οποία τελικά τα μετατρέπω σε πεδία δικού μου record, και το περνάω στην βάση μου.

 

 

 

Το κάθε αρχείο περιέχει μέσα πολλές παιγμένες παρτίδες (π.χ 2000 παρτίδες) με την κάθε μια τους να περιγράφεται σε τμήματα των περίπου 50 γραμμών ανά παρτίδα.

 

Άσε έφαγα φρίκη τώρα! Μόλις πήρα στο email αρχείο που έχει διαφορές στη δόμησή του... φτου ξανά μανά πάλι σχεδόν από την αρχή να κάνω τον parser... arghhhhhhhhhhhhhhhhhhhh

 

 

 

Δημοσ.

Χε... κουράγιο!

 

Πάντως, εάν πρόκειται να έχεις αλλαγές.. οι function pointers προσφέρονται. Απλά θα αλλάζεις την υλοποίηση για την function και όλο το άλλο θα είναι κομπλέ.

 

Οπότε, και εάν έχεις όρεξη... θα μπορούσες να κάνεις μία generic υλοποίηση και στον parser σου και σε κάθε τυχόν αλλαγή να αλλάζεις απλά την υλοποίηση των functions (υλοποίηση με την έννοια από ΟΟΡ). :P

 

Αλλά μάλλον δεν έπιασα από την αρχή τι ακριβώς ήθελες... :)

 

Νομίζω όμως ότι η λύση του defacer θα πρέπει να σε καλύπτει σε αυτό που θέλεις.

 

Ωραία φάση πάντως τέτοια προβληματάκια (ιδίως εάν δεν είναι δικά σου και τα διαβάζεις στο forum! :D :D )

 

 

Y.Γ. Γιατί δεν λειτουργεί το active sync με windows CE board ενώ όλα τα components είναι ΟΚ στο BSP στον Platform builder, ξέρει κανείς;

Δημοσ.

 

 

Άσε έφαγα φρίκη τώρα! Μόλις πήρα στο email αρχείο που έχει διαφορές στη δόμησή του... φτου ξανά μανά πάλι σχεδόν από την αρχή να κάνω τον parser... arghhhhhhhhhhhhhhhhhhhh

 

 

 

Απο δω η φίλη μου η regular expression...

Δημοσ.

Ενδιαφερον

Να και η δικη μου εκδοχη

>
char *TypeOfSeat[] =
{
"-/-",
"Player",
"Dealer",
"Big",
"Small"
};
int desk[9] = { 0 };
void Roll()
{
//find dealer
int fd;
int tos = 1; // typeofseat idx
for( fd = 0; fd < _countof(desk) && desk[fd] != 2; fd++);
//itr 9 times
for(int i = 0; i < _countof(desk) && tos < _countof(TypeOfSeat) ; i++)
{
int fixedIdx = fd >= _countof(desk) ? fd - _countof(desk) : fd;
if(desk[fixedIdx] != 0) // skip empty seat
desk[fixedIdx] = tos++;
fd++;
}

}
void print()
{
printf("Roll\n\n");
for(int i = 0; i < _countof(desk); i++)
{
printf("Seat:\t%d\t%s\n",i, TypeOfSeat[ desk[i] ]);
}
}
int main(int argc, char **argv)
{
desk[8] = 2;//dealer
desk[1] = desk[5] = desk[0] = desk[3] = 1; // players
print();
Roll();
print();
Roll();
print();
Roll();
print();
Roll();
print();
Roll();
return 0;
}

 

εδιτ: GTP το code tag

Δημοσ.

 

 

Απο δω η φίλη μου η regular exp<b></b>ression...

 

 

 

Δεν έχει να κάνει με regex'es, έχει να κάνει για παράδειγμα ότι σε έναν γύρο μπορεί να είναι έτσι...

 

>
...
*** FLOP *** [3d Td 8h]
*** TURN *** [3d Td 8h] [5h]
*** RIVER *** [3d Td 8h 5h] [Th]
*** SHOW DOWN ***
Mr. AT_159: shows [7s 7h] (two pair, Tens and Sevens)
betgenius78: shows [6c 2c] (a pair of Tens)
Mr. AT_159 collected 12225 from pot
betgenius78 finished the tournament in 135th place
*** SUMMARY ***
Total pot 12225 | Rake 0
Board [3d Td 8h 5h Th]
...

 

Σε άλλον να είναι έτσι...

 

>
...
*** FLOP *** [Tc Qs Td]
npapale: checks
Cypriotu: bets 500
Mr. AT_159: folds
betgenius78: folds
npapale: folds
Uncalled bet (500) returned to Cypriotu
Cypriotu collected 900 from pot
*** SUMMARY ***
Total pot 900 | Rake 0
Board [Tc Qs Td]
...

(no turn, no river)

 

και σε κάποιον άλλον έτσι...

 

>
...
*** FLOP *** [Js 9h 8s]
JACCATWIN: checks
Cypriotu: checks
eagle_slb114: checks
ibonator1983: bets 300
JACCATWIN: folds
Cypriotu: calls 300
eagle_slb114: calls 300
*** TURN *** [Js 9h 8s] [7c]
Cypriotu: checks
eagle_slb114: checks
ibonator1983: bets 2400 and is all-in
Cypriotu: folds
eagle_slb114: folds
Uncalled bet (2400) returned to ibonator1983
ibonator1983 collected 2150 from pot
*** SUMMARY ***
Total pot 2150 | Rake 0
Board [Js 9h 8s 7c]
...

(no river)

 

Μέχρι τώρα θεωρούσα πως σε όλους τους γύρους αναγράφονται πάντα flop, turn & river, έστω με invalid cards αν δεν παίχτηκαν. Τώρα ΔΕΝ αναγράφονται καν!

 

 

 

@timon

 

 

 

Το πρόβλημά μου δεν είναι στο parsing της γραμμής, αλλά στον εντοπισμό ποιας ή/και ποιων γραμμων χρειάζεται να γίνουν parsed για κάθε στοιχείο/στοιχεία που χρειάζομαι να τραβήξω από μέσα της (κάποια στοιχεία βγαίνουν με parsing πολλών συνεχόμενων γραμμών, όπως π.χ. αυτό που είπαμε πριν με τον αριθμό θέσης του παίκτη).

 

Εννοείται πως μόλις εντοπίσω στο main-loop τη γραμμή ή την ακολουθία γραμμών που χρειάζομαι, την/τις περνάω σε ξεχωριστές συναρτήσεις... ξεχωριστά για κάθε αυτόνομο πεδίο που θέλω για το δικό μου record.

 

Π.χ.

 

>
   ...
   id = 0;
   buttonSeat = 0;
   while ( !feof(fp) )
   {
       // get next line
       if ( !fgets(line, MAX_FILELINE, fp) )
           break;

       // is it beginning of a round ?  ( line contains STR_TSROUND_BEGIN ? )
       if ( strstr(line, STR_TSROUND_BEGIN) )
       {
           round_init( &roundTry );        // reset

           // get gameType (from the line below STR_TSROUND_BEGIN)
           if ( !fgets(line, MAX_FILELINE, fp) )
               break;
           parseLine_getGameType( line, &roundTry );
           printf( "GameType: %s\n", round_get_gameType_as_string(&roundTry) );
...

 

 

 

@papi:

 

Κλείσε τον διακόπτη πάνω αριστερά, για να μην έχεις formatted features... εκεί κρατάει το code tag σωστά.

Δημοσ.

migf1 σ' αυτή την περίπτωση να σου γνωρίσω τον άλλο φίλο μου τον finite state machine?

 

Δε θα τολμήσω βέβαια να πω ότι έτσι που γράφεις τον parser δεν είναι καλά γιατί μαύρο φίδι που σας έφαγε όλους εδω μέσα, αλλά μήπως να σκεφτόσουν και αυτό:

 

>enum states {
Expect_Begin_Round,
Expect_Game_Type,
// ...
};

enum states state = Expect_Begin_Round;

while ( !feof(fp) ) {
// get next line
if ( !fgets(line, MAX_FILELINE, fp) )
	 break;

switch (state) {
 case Expect_Begin_Round:
	 if ( !strstr(line, STR_TSROUND_BEGIN) ) stop_parse_ton_poulo();
	 round_init( &roundTry );
	 state = Expect_Game_Type;
	 break;
 case Expect_Game_Type:
	 parseLine_getGameType( line, &roundTry );
	 state = Expect_Something_Else;
	 break;
	 /// ...
}
}

 

Και ακόμα καλύτερα θα ήταν να μπει η fgets μετά το switch ούτως ώστε να έχεις τη δυνατότητα να αλλάξεις state και κατευθείαν continue. Αν το είχες έτσι τότε η διαπίστωση "omg δεν τα γράφει πάντα όλα" θα συνοδευόταν από περίπου 2 λεπτά δουλειάς.

Δημοσ.

Γιατί να μας φάει μαύρο φίδι;

 

 

 

Μια χαρά τεχνική είναι τα states, αλλά στο συγκεκριμένο δεν βλέπω να μου δίνει κάποιο πλεονέκτημα. Ίδια ακριβώς λογική είναι, απλώς εσύ αντί για if έχεις case κι ένα παραπανίσιο enum...

 

>
       while ( !feof(fp) )
       {
           round_init( &roundTry );        // reset

           // get gameType (from the line below STR_TSROUND_BEGIN)
           if ( !fgets(line, MAX_FILELINE, fp) )
               break;
           parseLine_getGameType( line, &roundTry );
           printf( "GameType: %s\n", round_get_gameType_as_string(&roundTry) );

           /*
            * Get player's SEAT & count OutOfHand players
            * (from the players-list shown at the top of each round)
            *     Scan the lines until the one containing STR_HOLE is found,
            *     while looking for a line containing the player's name.
            */
           for (;
           {
               // read next line...
               if ( !fgets(line, MAX_FILELINE, fp) )
                   goto end_of_main_loop;  // forcefully break nested loop

               // until line containing STR_HOLE
               if ( strstr(line, STR_HOLE) ) {
                   break;
               }

               // subtract any out-of-hand players from gamePlayers
               if ( strstr(line, STR_OUTOFHAND) )
                   round_add_gamePlayers(&roundTry, -1);
               // if found line containing plrname, get the seat (tokens[1])
               if ( strstr(line, plrname) ) {
                   /* MUST BE REPLACED WITH parseLine_get_plrSeat(line, &roundTry)*/
                   ntokens = s_tokenize(line, tokens, 2, " :\t\n");
                   printf( "%s' seat = %s\n", plrname, tokens[1] );
               }
           }

           // get Hole cards (from the line that follows the STR_HOLE line)
           if ( !fgets(line, MAX_FILELINE, fp) )
               break;
           parseLine_getHole( line, &roundTry );
           print_roundHandHole( &roundTry );
...

 

Αντί δηλαδή για enumerator εγώ τα έχω απευθείας με commented if's και αντίστοιχα #define, τα οποία btw ειναι απευθείας ορισμένα ως string-literals (κάτι που δεν γίνεται με enumerators).

 

Δεν έχει κάποια ουσιώδη διαφορά λογικής δηλαδή... ούτε προσφέρει κάποιο πλεονέκτημα σε πιθανή προσθήκη/αφαίρεση κάποιου state.

 

Εκτός αν μου διαφεύγει κάτι (διόλου απίθανο με το πακέτο που τρώω :P)

 

 

 

 

btw, το stop_parse_ton_poulo() πως θα το υλοποιούσες να σπάει nested loops?

Δημοσ.
Γιατί να μας φάει μαύρο φίδι;

 

defacer, μπορείς λίγο να αναπτύξεις το σκεπτικό σου για τον parser και τους "όλους εδώ μέσα";

 

Μου κίνησε την περιέργεια :)

 

Αν κρίνω από τις αντιδράσεις σας θα πρέπει μάλλον να το αναπτύξω ως "απόπειρα χιούμορ"...

 

Μια χαρά τεχνική είναι τα states, αλλά στο συγκεκριμένο δεν βλέπω να μου δίνει κάποιο πλεονέκτημα. Ίδια ακριβώς λογική είναι, απλώς εσύ αντί για if έχεις case κι ένα παραπανίσιο enum...

 

Ίδια λογική αλλά οι λεπτομέρειες κάνουν τη διαφορά. Έτσι που τα έγραψα μπορείς υπερπανεύκολα να αλλάζεις το state του parser, πράγμα που είναι ακριβώς και ο λόγος για τον οποίο δε σου άρεσε όταν είδες τα νέα logs. Επίσης έτσι μπορείς να διαχειριστείς στο μυαλό σου τα διάφορα states πολύ ευκολότερα γιατί όλες οι αλλαγές state είναι φανερές, ενώ στον κώδικα που δίνεις αλλαγή state μπορεί να προκληθεί από οποιοδήποτε control structure πράγμα που σημαίνει ότι για να δεις πως πάει η ροή πρέπει βασικά να τρέξεις όλο τον κώδικα στο μυαλό σου.

 

Αυτό που λες για string literals είναι άσχετο με το παραπάνω γιατί εκεί έχεις μπει στο μέρος της αναγνώρισης tokens. Για να πω την αλήθεια και αυτό θα το έκανα τελείως διαφορετικά γιατί κατά τη γνώμη μου το γεγονός ότι μπλέκονται στον ίδιο κώδικα επίπεδα abstraction που απέχουν πολύ μαζί τους είναι επίσης αρκετά προβληματικό (αν και όχι τόσο όσο τα παραπάνω). Στη μία γραμμή είναι ο κώδικας που αναγνωρίζει tokens (γραμμές του log δηλαδή), στην ακριβώς από κάτω είναι ο κώδικας που επεξεργάζεται τα tokens (τα ψειρίζει παραπάνω), και ανάμεσα υπάρχει και state change.

 

To stop_parse μπορεί να μην είναι καν stop (ας πούμε ένας παλιός parser μου προσπαθεί απλώς να κάνει recover γυρνώντας στο αρχικό state και αγνοώντας όλο το input που βρίσκει μέχρι να αρχίσει το αντίστοιχο του καινούριου παιχνιδιού, στην ουσία σαν ένα τηλεπικοινωνιακό κανάλι όπου χάνοντας το συγχρονισμό αγνοείς τα πάντα μέχρι να ξανακαταφέρεις να συγχρονίσεις). Αν είναι όντως stop μπορείς να το υλοποιήσεις με χίλιους δύο τρόπους, π.χ. με απλό return οπότε δεν κατάλαβα ακριβώς γιατί ρώτησες.

 

Δεν έχει κάποια ουσιώδη διαφορά λογικής δηλαδή... ούτε προσφέρει κάποιο πλεονέκτημα σε πιθανή προσθήκη/αφαίρεση κάποιου state.

 

Διαφορά λογικής δεν έχει, διαφορά στην πράξη έχει τεράστια. Για να πω την αλήθεια δεν περίμενα κάποια διαφορετική απάντηση και ούτε θα κάνω την προσπάθεια να σου αλλάξω γνώμη. Απλώς θα πω ότι για κάποιο λόγο αυτό που εσύ ανέφερες ως "πακετώθηκα" στο μυαλό μου είναι "no biggie", πράγμα που νομίζω ότι συμβαίνει διότι επίσης έχουμε με διαφορετικό τρόπο στο μυαλό μας τη δομή του parser.

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

  • Δημιουργία νέου...