C++炸金花
_j_o_k_e_r_ · · 科技·工程
#include<windows.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<random>
#include<vector>
#include<queue>
#include<cmath>
#include<ctime>
#include<map>
#define intt long long
#define intu unsigned long long
#define dle double
#define dlel long double
using namespace std;
const int Imax=0x7fffffff;
const long long LLmax=0x7fffffffffffffff;
mt19937 Rand(time(0));
const string number[15] = {
"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"
};
const string color[5] = {
"黑桃", "红桃", "梅花", "方片"
};
struct Card {
string color,number;
};
struct Cards {
Card card[5];
};
struct Player {
Cards _card_;
int money;
bool have_saw;//是否看过牌
bool have_run;//是否逃跑
};
Player players[15];
vector<Card> cards;
int now_player,player_number;
int now_money;
int last_money;
int _choice;
int __;
void print() {//打印输出
printf("%d 轮后开牌\n上家押的钱数:%d 本局总钱数:%d\n", player_number - __, last_money, now_money);
for (int i = 1; i <= player_number; i++) {
printf("玩家 %2d: 剩余钱数: %d ", i, players[i].money);
if (players[i].money <= 0) {
puts("破产");
} else if (players[i].have_run) {
puts("逃跑");
} else if (players[i].have_saw) {
puts("看过牌");
} else {
puts("未看牌");
}
}
}
int operator < (Card _x, Card _y) {//两张牌比大小
if (_x.number == _y.number) {//数字相同就比花色
int _x_id = 0, _y_id = 0;
while (color[_x_id] != _x.color) {
_x_id++;
}
while (color[_y_id] != _y.color) {
_y_id++;
}
return _x_id > _y_id;
}
//数字不相同就比数字
int _x_id = 0, _y_id = 0;
while (number[_x_id] != _x.number) {
_x_id++;
}
while (number[_y_id] != _y.number) {
_y_id++;
}
return _x_id < _y_id;
}
void init() {
for (int i = 0; i < 4; i ++) {//初始化牌堆
for (int j = 0; j < 13; j++) {
cards.push_back((Card){color[i], number[j]});
}
}
for (int i = 1; i <= player_number; i++) {
for (int j = 1; j <= 3; j++) {
int _size = cards.size();
int choice = Rand() % _size;
players[i]._card_.card[j] = cards[choice];
cards.erase(cards.begin() + choice);
}
sort(players[i]._card_.card + 1, players[i]._card_.card + 4);//提前排好序
}
}
string next_card(Card _card) {
if(_card.number == "A") return "Nothing";
int position = 0;
while (number[position] != _card.number) {
position ++;
}
return number[position + 1];
}
int check_baozi(Cards _card) {//检查是否为豹子
return _card.card[1].number == _card.card[2].number && _card.card[2].number == _card.card[3].number;
}
int check_shunzi(Cards _card) {//检查是否为顺子
return _card.card[2].number == next_card(_card.card[1]) && _card.card[3].number == next_card(_card.card[2]);
}
int check_tonghua(Cards _card) {//检查是否为同花
return _card.card[1].color == _card.card[2].color && _card.card[2].color == _card.card[3].color;
}
int check_duizi(Cards _card) {//检查是否有对子
return _card.card[1].number == _card.card[2].number || _card.card[2].number == _card.card[3].number;
}
int type(Cards _card) {//牌的类型
if (check_baozi(_card)) {//豹子
return 6;
} else if (check_shunzi(_card) && check_tonghua(_card)) {//同花顺
return 5;
} else if (check_shunzi(_card)) {//顺子
return 4;
} else if (check_tonghua(_card)) {//同花
return 3;
} else if(check_duizi(_card)) { //对子
return 2;
} else {
return 1;
}
return 0;
}
int operator < (Cards _x, Cards _y) {
//235 比 AAA 大
if (_x.card[1].number == "2" && _x.card[2].number == "3" && _x.card[3].number == "5") {
if (_y.card[1].number == "A" && _y.card[2].number == "A" && _y.card[3].number == "A") {
return 0;
}
}
if (type(_x) != type(_y)) {//牌型不一样就直接判断大小
return type(_x) < type(_y);
} else if (type(_x) == 6) {//豹子比大小
return _x.card[1] < _y.card[1];
} else if (type(_x) == 5 || type(_x) == 4) {//同花顺(顺子)比大小
return _x.card[3] < _y.card[3];
} else if (type(_x) == 3) {//同花比大小
for (int i = 3; i >= 1; i--) {//从大到小逐一比较
if (_x.card[i].number != _y.card[i].number) {
return _x.card[i] < _y.card[i];
}
}
return _x.card[3] < _y.card[3];//数字一样就比花色
} else if (type(_x) == 2) {//对子比大小
Card _x_card, _y_card, _x_other, _y_other;//_x_card 和 _y_card 都取对子的较大者
if (_x.card[1].number == _x.card[2].number) {
_x_card.number = _x.card[2].number;
_x_card.color = _x.card[2].color;
_x_other.number = _x.card[3].number;
_x_other.color = _x.card[3].color;
} else {
_x_card.number = _x.card[3].number;
_x_card.color = _x.card[3].color;
_x_other.number = _x.card[1].number;
_x_other.color = _x.card[1].color;
}
if (_y.card[1].number == _y.card[2].number) {
_y_card.number = _y.card[2].number;
_y_card.color = _y.card[2].color;
_y_other.number = _y.card[3].number;
_y_other.color = _y.card[3].color;
} else {
_y_card.number = _y.card[3].number;
_y_card.color = _y.card[3].color;
_y_other.number = _y.card[1].number;
_y_other.color = _y.card[1].color;
}
if (_x_card.number == _y_card.number) {//对子数字相同就比剩下的数字
if (_x_other.number == _y_other.number) {//剩下的数字还一样就比对子的花色
//由于两人各 2 张,共 4 张,必有黑桃,黑桃在哪家,哪家就大
return _y_card.color == "黑桃";
}
//剩下的数字不一样就比剩下牌的数字
return _x_other < _y_other;
}
//对子数字不同就必对子数字
return _x_card < _y_card;
} else {//散牌比大小
//与同花相同
for (int i = 3; i >= 1; i--) {//从大到小逐一比较
if (_x.card[i].number != _y.card[i].number) {
return _x.card[i] < _y.card[i];
}
}
return _x.card[3] < _y.card[3];//数字一样就比花色
}
return 0;//防 Warning,不会执行到这里
}
int hashh(Cards _card) {//算牌力
if (type(_card) == 1) {//散牌
if (_card.card[3].number == "A" || _card.card[3].number == "K") {//有 K 或 A 可以高一点
return 500;
} else {//否则最好尽快跑路
return 100;
}
} else if (type(_card) == 2) {//对子,常规牌
if (_card.card[1].number == _card.card[2].number) {
if((Card){"黑桃","8"} < _card.card[2]) {//比较大的对子
return 3000;
} else {//小对子
return 1000;
}
}
} else if (type(_card) == 3) {//同花,稀有牌
return 8000;
} else if (type(_card) == 4) {//顺子,超稀有
return 20000;
} else if (type(_card) == 5) {//同花顺,超级稀有
return 60000;
}
return 100000;//豹子,终极稀有
}
bool check(int number) {//number% 的概率是否中了
return Rand() % 100 <= number;
}
int random(int L, int R) {//在 [L,R] 中生成随机数
return Rand() % (R - L + 1) + L;
}
void play(int id) {//编号为 id 的玩家进行游戏
system("cls");
print();
if (id == 1) {//编号为 1 的玩家为真人玩家
if (!players[id].have_saw) {//没看过牌可以选择看牌
puts("您是否选择看牌?(请输入 0 或 1)");
scanf("%d", &_choice);
if (_choice == 1) {
players[id].have_saw = 1;
}
}
if (players[id].have_saw) {
puts("\n您的牌是:");
for (int i = 1; i <= 3; i++) {
cout << players[id]._card_.card[i].color << players[id]._card_.card[i].number << " ";
}
putchar('\n');
}
puts("您是否选择逃跑?(请输入 0 或 1)");
scanf("%d", &_choice);
if (_choice == 1) {
players[id].have_run = 1;
now_player--;
return;
}
int money_number;
printf("\n请输入您要押的钱数(不得少于上家),上家押的钱数为:%d\n", last_money);
scanf("%d", &money_number);
while (money_number < last_money || players[id].money < money_number) {
puts("输入有误,请重新输入");
Sleep(2000);
system("cls");
print();
if (!players[id].have_saw) {
puts("您是否选择看牌?(请输入 0 或 1)");
scanf("%d", &_choice);
if (_choice == 1) {
players[id].have_saw = 1;
}
}
if (players[id].have_saw) {
puts("\n您的牌是:");
for (int i = 1; i <= 3; i++) {
cout << players[id]._card_.card[i].color << players[id]._card_.card[i].number << " ";
}
putchar('\n');
}
puts("您是否选择逃跑?(请输入 0 或 1)");
scanf("%d", &_choice);
if (_choice == 1) {
players[id].have_run = 1;
now_player--;
return;
}
printf("\n请输入您要押的钱数(不得少于上家),上家押的钱数为:%d\n", last_money);
scanf("%d", &money_number);
}
players[id].money -= money_number;
last_money = money_number;
now_money += money_number;
} else {//否则是人机
Sleep(2000);
if (players[id].money < last_money) {//钱不够直接跑
printf("玩家 %d 逃跑\n", id);
players[id].have_run = 1;
now_player--;
return;
}
if (!players[id].have_saw) {
if (check(25)) {//有 25% 的概率看牌
printf("玩家 %d 看牌\n", id);
players[id].have_saw = 1;
Sleep(2000);
}
}
if (players[id].have_saw) {//看过牌可以根据牌力选择是否逃跑
if (hashh(players[id]._card_) < now_money) {//牌力不够
if (check(40)) {//40% 的概率逃跑
printf("玩家 %d 逃跑\n", id);
players[id].have_run = 1;
now_player--;
return;
}
}
}
if (check(3)) {//3% 的概率逃跑
printf("玩家 %d 逃跑\n", id);
players[id].have_run = 1;
now_player--;
return;
}
int money_number = last_money + random(0, 100);
if (players[id].have_saw) {//看过牌可以根据牌力押钱
if (hashh(players[id]._card_) > now_money * 5) {//超了 5 倍
money_number = random(last_money, last_money + 2000);
} else if (hashh(players[id]._card_) > now_money * 3) {//超了 3 倍
money_number = random(last_money, last_money + 800);
} else if (hashh(players[id]._card_) > now_money * 2) {//超了 2 倍
money_number = random(last_money, last_money + 500);
} else {
money_number = random(last_money, last_money + 100);
}
}
while (check(30)) {//30% 的概率加随机数
money_number += random(0, 50);
}
while (money_number > players[id].money) {//钱不够
money_number--;
}
printf("玩家 %d 押 %d 元\n", id, money_number);
players[id].money -= money_number;
last_money = money_number;
now_money += money_number;
}
}
void open_card() {//开牌
system("cls");
puts("清算时刻");
Sleep(2000);
int max_id = -1;
for (int i = 1; i <= player_number; i++) {
if (players[i].money <= 0) {
printf("玩家 %d 破产\n", i);
} else if (players[i].have_run) {
printf("玩家 %d 逃跑\n", i);
} else {
Sleep(1000);
printf("玩家 %d 的牌:", i);
Sleep(2000);
for (int j = 1; j <= 3; j++) {
cout << players[i]._card_.card[j].color << players[i]._card_.card[j].number << " ";
}
if (max_id == -1) {
max_id = i;
} else {
if (players[max_id]._card_ < players[i]._card_) {
max_id = i;
}
}
putchar('\n');
}
}
Sleep(1000);
printf("玩家 %d 获胜\n", max_id);
players[max_id].money += now_money;
Sleep(4000);
}
void Main() {//程序核心实现
puts("请输入人数(最少为 2 且最多为 10):");
scanf("%d", &player_number);
while (player_number < 2 || player_number > 10) {//输入有误
system("cls");
puts("输入有误,请重新输入游戏人数:");
scanf("%d", &player_number);
}
for (int i = 1; i <= player_number; i++) {
players[i].money = 10000;
}
while (1) {
init();
__ = last_money = now_money = 0;
for (int i = 1; i <= player_number; i++) {
players[i].have_saw = players[i].have_run = 0;
}
now_player = player_number;
bool have_open_card = 0;
while (__ < player_number) {
for (int i = 1; i <= player_number; i++) {
if (now_player == 1) {
open_card();
have_open_card = 1;
break;
}
if (players[i].have_run || !players[i].money) {
continue;
} else {
play(i);
}
Sleep(3000);
}
if (have_open_card) {
break;
}
__++;
}
if (!have_open_card) {
open_card();
}
}
}
int main() {
Main();
return 0;
}