Skip to content

Instantly share code, notes, and snippets.

@veeenu
Created October 29, 2013 11:02
Show Gist options
  • Save veeenu/7212602 to your computer and use it in GitHub Desktop.
Save veeenu/7212602 to your computer and use it in GitHub Desktop.
Quant'ero giovane.
/*
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