Created
October 29, 2013 11:02
-
-
Save veeenu/7212602 to your computer and use it in GitHub Desktop.
Quant'ero giovane.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Briscola.cpp - by X-3mE`89 - http://exxtreme.altervista.org | |
Released under GNU GPL terms | |
Codice per la console Windows preso da http://msdn.microsoft.com | |
Buon divertimento | |
Versione: 0.1 | |
Bugs: | |
- Ogni tanto il computer lascia dei carichi quando gioco liscio -- rivedere | |
l'intelligenza artificiale (che parolone). Comunque e' gia' abbastanza | |
buona, nonostante i bug sono riuscito a farmi battere diverse volte. | |
- All'ultima mano il computer spesso e volentieri mi gioca il ??? di ???, | |
che sarebbe la carta nulla, quando ho esplicitamente richiesto di non | |
giocarla -- devo rivedere l'intelligenza artificiale (che parolone, e | |
due) | |
- Prestazioni sufficientemente orribili; provvedere ad una raffinazione | |
ed ottimizzazione del codice. | |
*/ | |
#include <iostream> | |
#include <iomanip> | |
#include <vector> | |
#include <algorithm> | |
#include <stdlib.h> | |
#if defined(WINDOWS) || defined(__WINDOWS__) || defined(__WIN32__) | |
#include <windows.h> | |
WORD wOldColorAttrs; | |
#endif | |
#define VERSION "v0.1" | |
using namespace std; | |
int myrand(unsigned int); | |
int mysrand(unsigned int); | |
const int valoriCarte[] = | |
{ | |
11, 0, 10, 0, 0, 0, 0, 2, 3, 4 | |
}; | |
// | |
// Funzioni varie | |
// | |
int mysrand(unsigned int seed) | |
{ | |
srand(seed); | |
} | |
int myrand(unsigned int no) | |
{ | |
return rand() % no; | |
} | |
// | |
// Definizioni delle classi e degli enum | |
// | |
enum Seme | |
{ | |
S_NESSUNO, | |
S_DENARI, | |
S_BASTONI, | |
S_SPADE, | |
S_COPPE | |
}; | |
class Carta | |
{ | |
private: | |
enum Seme _seme; | |
unsigned int _val; | |
public: | |
Carta(); | |
Carta(enum Seme, unsigned int); | |
Carta(const Carta&); | |
Carta& operator=(const Carta&); | |
const bool operator>(const Carta&) const; | |
const bool operator<(const Carta& rhs) const | |
{ return !(*this > rhs); } | |
bool operator!(); | |
bool operator==(const Carta&); | |
bool operator!=(const Carta& rhs) { return !(*this == rhs); } | |
~Carta(); | |
void gioca(); | |
const enum Seme seme() const { return _seme; } | |
const unsigned int valore() const { return _val; } | |
const unsigned int punti() const; | |
}; | |
class Mazzo | |
{ | |
private: | |
vector< Carta > _mazzo; | |
public: | |
Mazzo(); | |
Mazzo(const Mazzo&); | |
Mazzo& operator=(const Mazzo&); | |
~Mazzo(); | |
void mescola(); | |
Carta pesca(); | |
bool vuoto() { return _mazzo.empty(); } | |
}; | |
// | |
// Funzioni wrapper varie per la compatibilita' Windows/Linux | |
// | |
// Inizializza la console. Per il momento solo Windows ne ha | |
// bisogno. La parte di Windows copia gli attributi di default | |
// della console in wOldColorAttrs | |
void InitConsole() | |
{ | |
#if defined(WINDOWS) || defined(__WINDOWS__) || defined(__WIN32__) | |
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); | |
if(hCon == INVALID_HANDLE_VALUE) | |
return; | |
CONSOLE_SCREEN_BUFFER_INFO csbi; | |
if(!GetConsoleScreenBufferInfo(hCon, &csbi)) | |
return; | |
wOldColorAttrs = csbi.wAttributes; | |
#else | |
#endif | |
} | |
void GotoXY(int x, int y) | |
{ | |
#if defined(WINDOWS) || defined(__WINDOWS__) || defined(__WIN32__) | |
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); | |
if(hCon == INVALID_HANDLE_VALUE) | |
return; | |
CONSOLE_SCREEN_BUFFER_INFO csbi; | |
if(!GetConsoleScreenBufferInfo(hCon, &csbi)) | |
return; | |
csbi.dwCursorPosition.X = x; | |
csbi.dwCursorPosition.Y = y; | |
SetConsoleCursorPosition(hCon, csbi.dwCursorPosition); | |
#else | |
// aaah che belli i terminali UNIX | |
cout << "\e[" << y << ';' << x << 'H' << flush; | |
#endif | |
} | |
// Nota: il colore vero e proprio viene visualizzato | |
// solo sotto Linux, in Windows l'unico colore previsto | |
// e' il rosso | |
void TextColor(int color, bool bold) | |
{ | |
#if defined(WINDOWS) || defined(__WINDOWS__) || defined(__WIN32__) | |
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); | |
if(hCon == INVALID_HANDLE_VALUE) | |
return; | |
if(bold) | |
SetConsoleTextAttribute(hCon, FOREGROUND_INTENSITY|FOREGROUND_RED); | |
else | |
SetConsoleTextAttribute(hCon, wOldColorAttrs); | |
#else | |
cout << "\e[" << color ? color+30 : 0; | |
if(bold) cout << ";1"; | |
cout << 'm' << flush; | |
#endif | |
} | |
void ClearScreen() | |
{ | |
#if defined(WINDOWS) || defined(__WINDOWS__) || defined(__WIN32__) | |
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); | |
if(hCon == INVALID_HANDLE_VALUE) | |
return; | |
TextColor(0,false); | |
COORD coordScreen = { 0, 0 }; | |
DWORD cCharsWritten; | |
CONSOLE_SCREEN_BUFFER_INFO csbi; | |
DWORD dwConSize; | |
if(!GetConsoleScreenBufferInfo(hCon, &csbi)) | |
return; | |
dwConSize = csbi.dwSize.X * csbi.dwSize.Y; | |
if(!FillConsoleOutputCharacter(hCon, (TCHAR) ' ', | |
dwConSize, coordScreen, &cCharsWritten)) | |
return; | |
if(!GetConsoleScreenBufferInfo(hCon, &csbi)) | |
return; | |
if(!FillConsoleOutputAttribute(hCon, csbi.wAttributes, | |
dwConSize, coordScreen, &cCharsWritten)) | |
return; | |
SetConsoleCursorPosition(hCon, coordScreen); | |
#else | |
cout << "\ec" << flush; | |
#endif | |
} | |
// | |
// Variabili globali | |
// | |
enum Seme briscola = S_NESSUNO; | |
Carta aTerra; | |
// | |
// Implementazione della classe Carta | |
// | |
Carta::Carta() | |
: _seme(S_NESSUNO), _val(0) | |
{ | |
} | |
Carta::Carta(enum Seme sm, unsigned int v) | |
: _seme(sm), _val(v) | |
{ | |
} | |
Carta::Carta(const Carta& rhs) | |
: _seme(rhs._seme), _val(rhs._val) | |
{ | |
} | |
Carta::~Carta() | |
{ | |
_seme = S_NESSUNO; | |
_val = 0; | |
} | |
Carta& Carta::operator=(const Carta& rhs) | |
{ | |
if(this == &rhs) | |
return *this; | |
_seme = rhs._seme; | |
_val = rhs._val; | |
return *this; | |
} | |
const bool Carta::operator>(const Carta& comanda) const | |
{ | |
if(_seme != briscola) | |
{ | |
if(_seme != comanda._seme) | |
return false; | |
if(punti() > comanda.punti() || | |
((punti() == comanda.punti()) && | |
_val > comanda._val)) | |
return true; | |
} | |
if(_seme != comanda._seme) | |
return true; | |
if(punti() > comanda.punti() || | |
((punti() == comanda.punti()) && | |
_val > comanda._val)) | |
return true; | |
return false; | |
} | |
bool Carta::operator==(const Carta& rhs) | |
{ | |
return (rhs._seme == _seme && rhs._val == _val); | |
} | |
bool Carta::operator!() | |
{ | |
return (_seme == S_NESSUNO && _val == 0); | |
} | |
void Carta::gioca() | |
{ | |
_seme = S_NESSUNO; | |
_val = 0; | |
} | |
const unsigned int Carta::punti() const | |
{ | |
if(_val < 11 && _val > 0) | |
return valoriCarte[_val-1]; | |
return 0; | |
} | |
ostream& operator<<(ostream& o, const Carta& carta) | |
{ | |
int val = carta.valore(); | |
enum Seme s = carta.seme(); | |
o << '[' << setw(8) << left; | |
switch(val) | |
{ | |
case 1: | |
o << 'A'; | |
break; | |
case 2: | |
case 3: | |
case 4: | |
case 5: | |
case 6: | |
case 7: | |
o << val; | |
break; | |
case 8: | |
o << "Donna"; | |
break; | |
case 9: | |
o << "Cavallo"; | |
break; | |
case 10: | |
o << "Re"; | |
break; | |
default: | |
o << "???"; | |
break; | |
} | |
o << " di " << setw(8) << left; | |
switch(s) | |
{ | |
case S_DENARI: | |
o << "Denari"; | |
break; | |
case S_BASTONI: | |
o << "Bastoni"; | |
break; | |
case S_SPADE: | |
o << "Spade"; | |
break; | |
case S_COPPE: | |
o << "Coppe"; | |
break; | |
default: | |
o << "???"; | |
break; | |
} | |
if(s == briscola) o << '*'; | |
else o << ' '; | |
o << ']'; | |
return o; | |
} | |
// | |
// Implementazione della classe Mazzo | |
// | |
Mazzo::Mazzo() | |
{ | |
enum Seme s = S_DENARI; | |
for(int x = 0; x < 4; x++) | |
{ | |
for(unsigned int i = 0; i < 10; i++) | |
_mazzo.push_back(Carta(s, i+1)); | |
switch(s) | |
{ | |
case S_DENARI: | |
s = S_BASTONI; | |
break; | |
case S_BASTONI: | |
s = S_SPADE; | |
break; | |
case S_SPADE: | |
s = S_COPPE; | |
break; | |
case S_COPPE: | |
s = S_NESSUNO; | |
break; | |
} | |
} | |
mysrand((unsigned)time(NULL)); | |
random_shuffle(_mazzo.begin(), _mazzo.end(), myrand); | |
//briscola = _mazzo[6].seme(); | |
aTerra = *(_mazzo.end()-1); | |
briscola = aTerra.seme(); | |
//swap(_mazzo[6], *(_mazzo.end()-1)); | |
} | |
Mazzo::Mazzo(const Mazzo& rhs) | |
{ | |
for(vector< Carta >::const_iterator i = rhs._mazzo.begin(); | |
i != rhs._mazzo.end(); ++i) | |
_mazzo.push_back(*i); | |
} | |
Mazzo& Mazzo::operator=(const Mazzo& rhs) | |
{ | |
if(this == &rhs) | |
return *this; | |
for(vector< Carta >::const_iterator i = rhs._mazzo.begin(); | |
i != rhs._mazzo.end(); ++i) | |
_mazzo.push_back(*i); | |
return *this; | |
} | |
Mazzo::~Mazzo() | |
{ | |
} | |
void Mazzo::mescola() | |
{ | |
if(vuoto()) return; | |
random_shuffle(_mazzo.begin(), _mazzo.end()); | |
} | |
Carta Mazzo::pesca() | |
{ | |
if(vuoto()) return Carta(S_NESSUNO, 0); | |
Carta c(_mazzo.front()); | |
_mazzo.erase(_mazzo.begin()); | |
return c; | |
} | |
// | |
// Intelligenza Artificiale del computer (un po' stupida) | |
// | |
int cpu_gioca_carta(Carta c0, Carta c1, Carta c2, Carta gioc) | |
{ | |
if(gioc == Carta(S_NESSUNO, 0)) | |
return myrand(3); // una a caso | |
int punti = gioc.punti(); | |
// Cerca di risparmiarsi le briscole e prende con la carta piu' alta | |
// (vedi carico, o il liscio piu' alto) | |
if(c0.seme() != briscola && c0 > gioc) | |
{ | |
if(c1.seme() != briscola && c1 > c0) | |
return 1; | |
if(c2.seme() != briscola && c2 > c0) | |
return 2; | |
return 0; | |
} | |
if(c1.seme() != briscola && c1 > gioc) | |
{ | |
if(c0.seme() != briscola && c0 > c1) | |
return 0; | |
if(c2.seme() != briscola && c2 > c1) | |
return 2; | |
return 1; | |
} | |
if(c2.seme() != briscola && c2 > gioc) | |
{ | |
if(c0.seme() != briscola && c0 > c2) | |
return 0; | |
if(c1.seme() != briscola && c1 > c2) | |
return 1; | |
return 2; | |
} | |
// usa (cerca di usare) una briscola | |
// usa di solito la prima che trova (da correggere) | |
if(punti >= 10) | |
{ | |
if(c0 > gioc) | |
return 0; | |
if(c1 > gioc) | |
return 1; | |
if(c2 > gioc) | |
return 2; | |
} | |
// ritorna la piu' piccola; da' priorita' ai carichi | |
Carta c(min(min(c0,c1), c2)); | |
Carta nullc; | |
if(c0 != nullc && c == c0) return 0; | |
if(c1 != nullc && c == c1) return 1; | |
if(c2 != nullc && c == c2) return 2; | |
if(c0 != nullc) return 0; | |
if(c1 != nullc) return 1; | |
if(c2 != nullc) return 2; | |
if(c0.seme() != S_NESSUNO) return 0; | |
if(c1.seme() != S_NESSUNO) return 1; | |
if(c2.seme() != S_NESSUNO) return 2; | |
if(c0.valore() != 0) return 0; | |
if(c1.valore() != 0) return 1; | |
if(c2.valore() != 0) return 2; | |
return 0; | |
} | |
// | |
// Mostra alcuni dati | |
// | |
void stats() | |
{ | |
cout << "Briscola: "; | |
switch(briscola) | |
{ | |
case S_DENARI: | |
cout << "Denari"; | |
break; | |
case S_BASTONI: | |
cout << "Bastoni"; | |
break; | |
case S_SPADE: | |
cout << "Spade"; | |
break; | |
case S_COPPE: | |
cout << "Coppe"; | |
break; | |
default: | |
cout << "???"; | |
break; | |
} | |
cout << endl << "Carta a terra: " << aTerra << endl; | |
} | |
// | |
// Implementazione del main() | |
// | |
int main(int argc, char** argv) | |
{ | |
InitConsole(); | |
Mazzo mazzo; | |
cout << "Briscola " << VERSION << " by X-3mE'89 - http://exxtreme.altervista.org" | |
<< endl << endl; | |
vector< Carta > manoComputer(3), manoGiocatore(3); | |
int puntiComputer = 0, puntiGiocatore = 0; | |
bool turnoGiocatore = true; | |
manoGiocatore[0] = mazzo.pesca(); | |
manoComputer [0] = mazzo.pesca(); | |
manoGiocatore[1] = mazzo.pesca(); | |
manoComputer [1] = mazzo.pesca(); | |
manoGiocatore[2] = mazzo.pesca(); | |
manoComputer [2] = mazzo.pesca(); | |
int ultimaMano = 0; | |
while(!mazzo.vuoto() || ultimaMano <= 3) | |
{ | |
Carta nullc; | |
int cndx = 0, gndx = 0; | |
ClearScreen(); | |
cout << "Tocca al " << (turnoGiocatore ? | |
"Giocatore" : "Computer") << endl; | |
stats(); | |
GotoXY(0, 15); | |
cout << "Punti totalizzati: " << endl << | |
"\tComputer:\t" << puntiComputer << endl << | |
"\tGiocatore:\t" << puntiGiocatore << endl; | |
GotoXY(0, 4); | |
for(int i = 0; i < 44; i++) cout << '-'; | |
GotoXY(0, 8); | |
for(int i = 0; i < 44; i++) cout << '-'; | |
if(!turnoGiocatore) | |
{ | |
cndx = cpu_gioca_carta(manoComputer[0], | |
manoComputer[1], | |
manoComputer[2], | |
nullc); | |
GotoXY(0, 5); | |
TextColor(2, true); | |
cout << "*** Computer gioca: " << | |
manoComputer[cndx] << endl; | |
TextColor(0, false); | |
} | |
int carta = 0; | |
while(carta != 1 && carta != 2 && carta != 3) | |
{ | |
GotoXY(0, 9); | |
cout << | |
"1." << manoGiocatore[0] << endl << | |
"2." << manoGiocatore[1] << endl << | |
"3." << manoGiocatore[2] << endl << | |
endl << "Quale carta giochi? (123): "; | |
cin >> carta; | |
} | |
gndx = carta-1; | |
GotoXY(0, 6); | |
TextColor(1, true); | |
cout << "*** Giocatore gioca: " << | |
manoGiocatore[gndx] << endl; | |
TextColor(0, false); | |
if(turnoGiocatore) | |
{ | |
cndx = cpu_gioca_carta(manoComputer[0], | |
manoComputer[1], | |
manoComputer[2], | |
manoGiocatore[gndx]); | |
GotoXY(0, 5); | |
TextColor(2, true); | |
cout << "*** Computer gioca: " << | |
manoComputer[cndx] << endl; | |
TextColor(0, false); | |
} | |
cout << endl; | |
if((!turnoGiocatore && | |
manoGiocatore[gndx] < manoComputer[cndx]) || | |
(turnoGiocatore && manoComputer[cndx] > | |
manoGiocatore[gndx])) | |
{ | |
GotoXY(0, 7); | |
cout << "Prende il Computer" << endl; | |
puntiComputer += | |
manoComputer[cndx].punti() + | |
manoGiocatore[gndx].punti(); | |
if(!mazzo.vuoto()) manoComputer[cndx] = mazzo.pesca(); | |
else manoGiocatore[gndx] = nullc; | |
if(!mazzo.vuoto()) manoGiocatore[gndx] = mazzo.pesca(); | |
else manoComputer[cndx] = nullc; | |
turnoGiocatore = false; | |
} | |
else | |
{ | |
GotoXY(0, 7); | |
cout << "Prende il Giocatore" << endl; | |
puntiGiocatore += | |
manoComputer[cndx].punti() + | |
manoGiocatore[gndx].punti(); | |
if(!mazzo.vuoto()) manoGiocatore[gndx] = mazzo.pesca(); | |
else manoGiocatore[gndx] = nullc; | |
if(!mazzo.vuoto()) manoComputer[cndx] = mazzo.pesca(); | |
else manoComputer[cndx] = nullc; | |
turnoGiocatore = true; | |
} | |
if(mazzo.vuoto()) ultimaMano++; | |
GotoXY(0,19); | |
cout << endl << "Premi invio per continuare..."; | |
char* ptr = new char[8]; | |
cin.getline(ptr,1); | |
cin.getline(ptr,1); | |
delete[] ptr; | |
} | |
ClearScreen(); | |
stats(); | |
cout << "Punti totalizzati: " << endl << | |
"\tComputer:\t" << puntiComputer << endl << | |
"\tGiocatore:\t" << puntiGiocatore << endl; | |
if(puntiGiocatore == puntiComputer) cout << "Pareggio." << endl; | |
else cout << "Vince " << (puntiGiocatore > puntiComputer ? | |
"Giocatore" : "Computer") << "!" << endl; | |
char* ptr = new char[8]; | |
cin.getline(ptr,1); | |
cin.getline(ptr,1); | |
delete[] ptr; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment