// // bridge.cc // Eerste programmeeropgave voor AI, 28 januari 2008, Bridge // Walter Kosters // #include #include #include #include using namespace std; /* Maak array verwijzingen expliciet en uniform */ #define NOORD 0 #define OOST 1 #define ZUID 2 #define WEST 3 /* Kaartdefinities */ #define KLAVEREN 0 #define RUITEN 1 #define HARTEN 2 #define SCHOPPEN 3 /* Contract mogelijkheden */ #define CONTRACT_RANDOM 0 /* Agent EEN */ #define CONTRACT_SLIM 1 /* Agent DRIE */ /* Niveau's */ #define NIVEAU_RANDOM 0 /* Agent TWEE */ #define NIVEAU_SLIM 1 /* Agent VIER */ /* Speeltype */ #define SPEEL_KOSTER_BRIDGE 0 #define VERBOSE 1 #define SILENT 0 /* Afsluit codes, teveel is positief, teweinig negetief */ #define GEHAALD = 0 //sorteer array A (met n elementen) via bubblesort void bubblesort (int A[ ], int n) { int i, j, temp; for ( j = 1; j < n; j++ ) for ( i = 0; i < n-j; i++ ) if ( A[i] > A[i+1] ) { temp = A[i]; A[i] = A[i+1]; A[i+1] = temp; }//if }//bubblesort //welke getalswaarde heeft kaart i? //1..13 zijn Klaver1..13, 14..26 zijn Ruiten1..13, //27..39 zijn Harten1..13 en 40..52 zijn Schoppen1..13 //eigenlijk is 13 de aas, dus 1 is een 2 ;-) int dewaarde (int i) { if ( i <= 13 ) return i; else if ( i <= 26 ) return i-13; else if ( i <= 39 ) return i-26; else return i-39; }//dewaarde //welke kleurwaarde heeft kaart i? char dekleurwaarde (int i) { if ( i <= 13 ) return KLAVEREN; else if ( i <= 26 ) return RUITEN; else if ( i <= 39 ) return HARTEN; else return SCHOPPEN; }//dekleur //welke kleur heeft kaart i? char dekleur (int i) { switch ( dekleurwaarde (i) ) { case KLAVEREN: return 'K'; case RUITEN: return 'R'; case HARTEN: return 'H'; case SCHOPPEN: return 'S'; } }//dekleur //print kaart i netjes void printkaart (int i) { cout << dekleur (i) << dewaarde (i); if ( dewaarde (i) < 10 ) cout << " "; }//printkaart //welke speler is i? char despeler (int i) { switch ( i ) { case NOORD: return 'N'; case OOST: return 'O'; case ZUID: return 'Z'; case WEST: return 'W'; }//switch return 'X'; }//despeler //=== class spel { public: int aantalkaarten; //hoeveel kaarten heeft iedere speler? char troef; //KRHS int hoogte; //1..13 bool NZ; //true betekent NZ, false betekent OW int dekaarten[4][13]; //N:0,O:1,Z:2,W:3 int slagenNZ; //aantal slagen voor NZ int slagenOW; //idem voor OW int spelerniveau[3]; /* Kwaliteit van speler */ void schud ( ); void print ( ); void maakcontract (int hoe, bool printdetails); void afspelen (int speeltype, bool printdetails); int trekkaart (int hoe, char kleur, int A[ ], int aantal); int uitslag (bool printdetails); };//spel //verdeel de kaarten, en schud ze over de 4 spelers void spel::schud ( ) { int kaarten[52]; int i, j, temp; aantalkaarten = 13; for ( i = 0; i < 52; i++ ) kaarten[i]= i+1; for ( i = 52-1; i > 0; i-- ) { j = rand ( ) % (i+1); temp = kaarten[i]; kaarten[i] = kaarten[j]; kaarten[j] = temp; }//for for ( i = 0; i < 13; i++ ) { dekaarten[NOORD][i] = kaarten[i]; dekaarten[OOST][i] = kaarten[i+13]; dekaarten[ZUID][i] = kaarten[i+26]; dekaarten[WEST][i] = kaarten[i+39]; }//for bubblesort (dekaarten[NOORD],13); bubblesort (dekaarten[OOST],13); bubblesort (dekaarten[ZUID],13); bubblesort (dekaarten[WEST],13); slagenNZ = slagenOW = 0; }//spel::schud //print huidige kaarten void spel::print ( ) { int i; cout << "=Kaart configuratie=" < kleurAantal[i - 1] ) troef = i; /* Elke troef levert een slag op */ hoogte = kleurAantal[troef]; /* Hoogste kaart(en) leveren ook slagen op */ slagen = 0; /* i is de zoekkaart */ for (int i = 52; i >= 0;) { while (zoekpuntA != -1 && dekaarten[spelerA][zoekpuntA] > i) zoekpuntA--; while (zoekpuntB != -1 && dekaarten[spelerB][zoekpuntB] > i) zoekpuntB--; /* Hebben we de kaart in bezit of moeten we naar een aas van * een andere kleur gaan zoeken */ if (zoekpuntA == -1 && zoekpuntB == -1) { break; } else if (zoekpuntA != -1 && dekaarten[spelerA][zoekpuntA] == i) { slagen++; i--; } else if (zoekpuntB != -1 && dekaarten[spelerB][zoekpuntB] == i) { slagen++; i--; } else { if ( i <= 13 ) { /* KLAVEREN aas is niet in bezit */ break; } else { /* Spring naar de volgende aas */ if ((i % 13) == 0) i = i - 13; else i = i - (i % 13); } } } hoogte = hoogte + slagen; /* Set troef naar ASCII waarde om */ troef = dekleur ( (troef + 1) * 13); break; } if (printdetails) { cout << endl << "=Contract=" << endl; cout << "Paar : " << ( NZ ? "NZ " : "OW " ) << endl; cout << "Slagen : " << hoogte < dewaarde (hoogstekaart) ) { hoogstekaart = j; } else if ( dewaarde (A[j]) == dewaarde (hoogstekaart) ) { /* Troef is beter */ if ( dekleur (A[j]) == troef ) { hoogstekaart = j; } } } i = hoogstekaart; break; } /* Troef spelen, levert aparte regels */ if ( kleur == troef ) { /* Hoogste troef als present, anders laagste kaart */ if ( heeftkleur ) i = totenmet; else i = 0; break; } /* Als kleur present dan meespelen met hoogste kaart */ if ( heeftkleur ) { i = totenmet; break; } /* Bij ontbreken van kleur, bepaal of troef present is */ for ( j = 0; j < aantal; j++ ) if ( dekleur (A[j]) == troef ) { if ( heeftkleur ) totenmet = j; else totenmet = vanaf = j; heeftkleur = true; }//if /* 'Steel' het slag door kleinste troefje te spelen */ if ( heeftkleur ) { i = vanaf; break; } /* Niets kunnen betekenen hier, laagste kaart dan maar ;-) */ i = 0; break; } /* Doe de boekhouding en werk het de eigen hand bij */ dekaart = A[i]; for ( j = i; j < aantal-1; j++ ) A[j] = A[j+1]; A[aantal-1] = 0; return dekaart; }//spel::trekkaart //speel af; printdetails geeft meer informatie void spel::afspelen (int speeltype, bool printdetails) { int speler, winnaar, hoogste, winkleur, vraagkleur; int kaart[ ] = {0, 0, 0, 0}; int buurt = 1; /* Laat random speler beginnen */ speler = rand ( ) % 4; // 0123 if (printdetails) { cout << "=Spel=" < Oost -> Zuid -> West -> Noord --> Oost -> Zuid" < 0 ) { if (printdetails) { if ( buurt < 10 ) cout << " "; cout << buurt << " | "; } /* Initiele kaart, geen voorkeur voor kleur */ kaart[0] = trekkaart (spelerniveau[speler],'X',dekaarten[speler], aantalkaarten); vraagkleur = dekleur (kaart[0]); if ( printdetails ) { cout << despeler (speler) << " | "; printkaart (kaart[0]); cout << " | "; }//if /* Laat de rest bijspelen */ for (int i = 1; i <= 3; i++) { kaart[i] = trekkaart (spelerniveau[i], vraagkleur, dekaarten[(speler+i)%4],aantalkaarten); if ( printdetails ) { printkaart (kaart[i]); cout << " | "; }//if } aantalkaarten--; /* controleer troef in het spel */ if ( dekleur(kaart[0]) == troef || dekleur(kaart[1]) == troef || dekleur(kaart[2]) == troef || dekleur(kaart[3]) == troef ) winkleur = troef; else winkleur = dekleur (kaart[0]); /* bepaal de winnende spelers */ hoogste = -1; if ( dekleur (kaart[0]) == winkleur && kaart[0] > hoogste ) { winnaar = speler; hoogste = kaart[0]; }//if if ( dekleur (kaart[1]) == winkleur && kaart[1] > hoogste ) { winnaar = (speler+1) % 4; hoogste = kaart[1]; }//if if ( dekleur (kaart[2]) == winkleur && kaart[2] > hoogste ) { winnaar = (speler+2) % 4; hoogste = kaart[2]; }//if if ( dekleur (kaart[3]) == winkleur && kaart[3] > hoogste ) { winnaar = (speler+3) % 4; hoogste = kaart[3]; }//if if ( printdetails ) { cout << despeler (winnaar) << " |" << endl; }//if if ( winnaar == 0 || winnaar == 2 ) slagenNZ++; else slagenOW++; speler = winnaar; buurt++; }//while break; }//switch }//spel::afspelen //uitslag op scherm int spel::uitslag (bool printdetails) { int slagen = ( NZ ? slagenNZ : slagenOW); if (printdetails) { cout << "=Uitslag=" << endl; cout << "Slagen NZ : " << slagenNZ << endl; cout << "Slagen OW : " << slagenOW << endl; cout << "Contract bod : " << hoogte << endl; cout << "Contract paar : " << ( NZ ? "NZ " : "OW " ) << endl; cout << "Contact gehaald : "; } if ( slagen < hoogte ) { if (printdetails) cout << "TEKORT"; } else if ( slagen == hoogte ) { if (printdetails) cout << "CORRECT"; } else { if (printdetails) cout << "TEVEEL"; } if (printdetails) cout << " (" << slagen - hoogte << ")" << endl; return (slagen - hoogte); }//spel::uitslag //=== void printTotaalWaarde (string type, double waarde, double totaal) { cout << setiosflags(ios::left); cout << setw(10) << type << " : "; cout << resetiosflags(ios::left); double percent = (waarde / totaal) * 100; cout.precision(8); cout << setw(8) << waarde; cout << " = "; cout.precision(2); cout << setw(7) << setiosflags(ios::fixed) << percent < 0) { teveel++; /* elk punt teveel score: -10 */ eindscore = eindscore + retcode * -10; } else if (retcode == 0) { correct++; /* elk goede score +20 */ eindscore = eindscore + 20; } else { tekort++; /* elk punt tekort score: -20 * retcode is al negatief */ eindscore = eindscore + (retcode * 20); } } /* Bereken eindresultaat */ fout = tekort + teveel; goed = correct; printTotaalWaarde("Tekort", tekort, aantalKeer); printTotaalWaarde("Correct", correct, aantalKeer); printTotaalWaarde("Teveel", teveel, aantalKeer); cout << endl; printTotaalWaarde("Goed", goed, aantalKeer); printTotaalWaarde ("Fout", fout, aantalKeer); printTotaalWaarde ("EindScore", eindscore, aantalKeer * 20); }//main