“#include <graphics.h>
#include <conio.h>
#include <vector>
#include <algorithm>
#include <ctime>
#include <string>
#include <cmath>
using namespace std;
// 游戏常量
const int WIDTH = 1200;
const int HEIGHT = 800;
const int PLAYER_MIN = 6;
const int PLAYER_MAX = 10;
const int MAX_N = 9;
const int MIN_N = 2;
const int THINKING_TIME = 9; // 9秒思考时间
// 牌的类型
enum CardType {
EMPTY, // 空牌
BAOWEI, // 保位牌
KILL, // 杀人牌
CHANGE_POS, // 换位牌
CHANGE_N, // 换数牌
IMMUNE // 不死牌
};
// 玩家类
class Player {
public:
int id; // 玩家ID
int position; // 位置 (1-n)
CardType card; // 持有的牌
bool usedCard; // 是否已使用牌
bool alive; // 是否存活
bool baowei; // 是否有保位状态
bool immune; // 是否使用不死牌
int target; // 目标玩家 (用于杀人牌和换位牌)
int newN; // 新的n值 (用于换数牌)
Player(int id, int pos) : id(id), position(pos), card(EMPTY),
usedCard(false), alive(true), baowei(false),
immune(false), target(-1), newN(-1) {}
// 重置状态 (每轮开始)
void reset() {
card = EMPTY;
usedCard = false;
baowei = false;
immune = false;
target = -1;
newN = -1;
}
};
// 游戏类
class Game {
private:
vector<Player> players; // 玩家列表
int currentN; // 当前报数n值
int currentPlayer; // 当前报数的玩家索引
int round; // 当前回合
bool gameOver; // 游戏是否结束
int winner; // 获胜者ID
// 牌堆
vector<CardType> deck;
public:
Game() : currentN(0), currentPlayer(0), round(1), gameOver(false), winner(-1) {}
// 初始化游戏
void initialize(int playerCount) {
players.clear();
deck.clear();
gameOver = false;
round = 1;
winner = -1;
// 创建玩家
for (int i = 0; i < playerCount; i++) {
players.push_back(Player(i + 1, i + 1));
}
// 随机n值
currentN = rand() % (MAX_N - MIN_N + 1) + MIN_N;
currentPlayer = 0; // 从第一个玩家开始
// 初始化牌堆
resetDeck();
}
// 重置牌堆
void resetDeck() {
deck.clear();
// 添加技能牌
deck.push_back(BAOWEI);
deck.push_back(KILL);
deck.push_back(CHANGE_POS);
deck.push_back(CHANGE_N);
deck.push_back(IMMUNE);
// 添加空牌
int emptyCount = players.size() - 5;
if (emptyCount > 0) {
for (int i = 0; i < emptyCount; i++) {
deck.push_back(EMPTY);
}
}
// 洗牌
random_shuffle(deck.begin(), deck.end());
}
// 发牌
void dealCards() {
resetDeck();
for (int i = 0; i < players.size(); i++) {
if (players[i].alive) {
players[i].reset();
players[i].card = deck.back();
deck.pop_back();
}
}
}
// 使用牌
void useCard(int playerIndex) {
Player& player = players[playerIndex];
if (!player.alive || player.usedCard || player.card == EMPTY)
return;
player.usedCard = true;
switch (player.card) {
case BAOWEI:
player.baowei = true;
break;
case KILL:
// 随机选择一个目标玩家 (不是自己)
do {
player.target = rand() % players.size();
} while (player.target == playerIndex || !players[player.target].alive);
break;
case CHANGE_POS:
// 随机选择一个目标玩家交换位置
do {
player.target = rand() % players.size();
} while (player.target == playerIndex || !players[player.target].alive);
// 交换位置
swap(players[playerIndex].position, players[player.target].position);
break;
case CHANGE_N:
// 随机一个新的n值
player.newN = rand() % (MAX_N - MIN_N + 1) + MIN_N;
break;
case IMMUNE:
player.immune = true;
break;
default:
break;
}
}
// 处理牌效果
void processCardEffects() {
// 按顺序处理牌: 保位牌->杀人牌->换位牌->换数牌->不死牌
// 1. 保位牌
for (Player& p : players) {
if (p.alive && p.usedCard && p.card == BAOWEI) {
p.baowei = true;
}
}
// 2. 杀人牌
for (Player& p : players) {
if (p.alive && p.usedCard && p.card == KILL) {
Player& target = players[p.target];
if (target.alive && !target.baowei) {
target.alive = false;
}
}
}
// 3. 换位牌 (已经在useCard阶段处理)
// 4. 换数牌
for (Player& p : players) {
if (p.alive && p.usedCard && p.card == CHANGE_N) {
currentN = p.newN;
}
}
// 5. 不死牌 (在报数阶段处理)
}
// 报数
bool count() {
if (gameOver) return true;
// 找到下一个存活的玩家
int count = 0;
int startPlayer = currentPlayer;
bool counted = false;
while (!counted) {
if (players[currentPlayer].alive) {
count++;
// 如果达到n
if (count == currentN) {
Player& p = players[currentPlayer];
// 如果使用了不死牌
if (p.immune) {
p.immune = false; // 消耗不死牌
// 停止报数,下一轮从当前玩家开始
currentPlayer = (currentPlayer + 1) % players.size();
return false;
}
// 否则淘汰玩家
else {
p.alive = false;
// 检查游戏是否结束
if (checkGameOver()) {
return true;
}
// 下一轮从淘汰玩家的下一位开始
currentPlayer = (currentPlayer + 1) % players.size();
return false;
}
}
}
// 移动到下一个玩家
currentPlayer = (currentPlayer + 1) % players.size();
// 防止无限循环
if (currentPlayer == startPlayer) {
break;
}
}
return false;
}
// 检查游戏是否结束
bool checkGameOver() {
int aliveCount = 0;
int lastAlive = -1;
for (int i = 0; i < players.size(); i++) {
if (players[i].alive) {
aliveCount++;
lastAlive = i;
}
}
if (aliveCount == 1) {
gameOver = true;
winner = players[lastAlive].id;
return true;
}
return false;
}
// 开始下一轮
void nextRound() {
round++;
dealCards();
processCardEffects();
}
// 获取玩家列表
vector<Player>& getPlayers() { return players; }
// 获取当前n值
int getCurrentN() const { return currentN; }
// 获取当前回合
int getRound() const { return round; }
// 获取当前玩家索引
int getCurrentPlayer() const { return currentPlayer; }
// 游戏是否结束
bool isGameOver() const { return gameOver; }
// 获取获胜者
int getWinner() const { return winner; }
// 获取存活玩家数量
int getAliveCount() const {
int count = 0;
for (const Player& p : players) {
if (p.alive) count++;
}
return count;
}
};
// 渲染玩家
void renderPlayers(const vector<Player>& players, int currentPlayer, int centerX, int centerY, int radius) {
const int playerRadius = 40;
const int count = players.size();
const double angleStep = 2 * 3.1415926535 / count;
// 渲染玩家
for (int i = 0; i < count; i++) {
const Player& p = players[i];
double angle = i * angleStep - 3.1415926535 / 2; // 从顶部开始
int x = centerX + static_cast<int>(radius * cos(angle));
int y = centerY + static_cast<int>(radius * sin(angle));
// 设置玩家颜色
COLORREF color;
if (!p.alive) {
color = RGB(100, 100, 100); // 灰色表示淘汰
} else if (i == currentPlayer) {
color = RGB(255, 215, 0); // 金色表示当前玩家
} else {
color = HSVtoRGB(static_cast<float>(i) / count * 360, 0.8f, 0.9f);
}
// 绘制玩家圆圈
setfillcolor(color);
setlinecolor(BLACK);
fillcircle(x, y, playerRadius);
// 绘制玩家ID
setbkmode(TRANSPARENT);
settextcolor(BLACK);
char idText[10];
sprintf(idText, "%d", p.id);
RECT r = {x - 20, y - 10, x + 20, y + 10};
drawtext(idText, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
// 绘制位置
sprintf(idText, "Pos:%d", p.position);
r.top += 20;
r.bottom += 20;
drawtext(idText, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
// 绘制状态图标
if (p.baowei) {
setfillcolor(RGB(0, 255, 0));
solidcircle(x - 15, y - 35, 8);
}
if (p.immune) {
setfillcolor(RGB(0, 0, 255));
solidcircle(x + 15, y - 35, 8);
}
}
}
// 渲染牌
void renderCard(CardType card, int x, int y, bool isFaceUp = true) {
const int cardWidth = 80;
const int cardHeight = 120;
if (!isFaceUp) {
// 牌背面
setfillcolor(RGB(200, 30, 30));
setlinecolor(RGB(150, 20, 20));
fillrectangle(x - cardWidth/2, y - cardHeight/2, x + cardWidth/2, y + cardHeight/2);
return;
}
// 牌正面
setfillcolor(WHITE);
setlinecolor(BLACK);
fillrectangle(x - cardWidth/2, y - cardHeight/2, x + cardWidth/2, y + cardHeight/2);
rectangle(x - cardWidth/2, y - cardHeight/2, x + cardWidth/2, y + cardHeight/2);
// 牌类型文本
const char* cardText = "";
COLORREF textColor = BLACK;
switch (card) {
case BAOWEI:
cardText = "保位";
textColor = RGB(0, 150, 0);
break;
case KILL:
cardText = "杀人";
textColor = RGB(200, 0, 0);
break;
case CHANGE_POS:
cardText = "换位";
textColor = RGB(150, 0, 150);
break;
case CHANGE_N:
cardText = "换数";
textColor = RGB(0, 0, 200);
break;
case IMMUNE:
cardText = "不死";
textColor = RGB(0, 100, 200);
break;
case EMPTY:
cardText = "空牌";
textColor = RGB(100, 100, 100);
break;
}
settextcolor(textColor);
setbkmode(TRANSPARENT);
RECT r = {x - cardWidth/2, y - cardHeight/2, x + cardWidth/2, y + cardHeight/2};
drawtext(cardText, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
// 渲染游戏状态
void renderGameInfo(const Game& game, int timeLeft) {
// 渲染回合信息
char roundText[50];
sprintf(roundText, "回合: %d", game.getRound());
settextcolor(BLACK);
settextstyle(24, 0, _T("宋体"));
outtextxy(50, 50, roundText);
// 渲染n值
char nText[50];
sprintf(nText, "当前 n: %d", game.getCurrentN());
outtextxy(50, 90, nText);
// 渲染存活玩家数量
char aliveText[50];
sprintf(aliveText, "存活玩家: %d", game.getAliveCount());
outtextxy(50, 130, aliveText);
// 渲染倒计时
if (timeLeft >= 0) {
char timeText[50];
sprintf(timeText, "思考时间: %d秒", timeLeft);
settextcolor(RGB(200, 0, 0));
outtextxy(WIDTH - 200, 50, timeText);
// 绘制进度条
float progress = timeLeft / static_cast<float>(THINKING_TIME);
setfillcolor(RGB(static_cast<int>(255 * (1 - progress)), static_cast<int>(255 * progress), 0));
fillrectangle(WIDTH - 220, 90, WIDTH - 220 + static_cast<int>(200 * progress), 120);
setlinecolor(BLACK);
rectangle(WIDTH - 220, 90, WIDTH - 20, 120);
}
// 渲染游戏结束
if (game.isGameOver()) {
settextcolor(RGB(200, 0, 0));
settextstyle(48, 0, _T("宋体"));
char winText[100];
sprintf(winText, "玩家 %d 获胜!", game.getWinner());
int textWidth = textwidth(winText);
int x = (WIDTH - textWidth) / 2;
int y = HEIGHT / 2 - 50;
outtextxy(x, y, winText);
}
}
// 渲染玩家手牌
void renderPlayerCards(const vector<Player>& players, int centerX, int centerY, int radius) {
const int count = players.size();
const double angleStep = 2 * 3.1415926535 / count;
for (int i = 0; i < count; i++) {
const Player& p = players[i];
if (!p.alive) continue;
double angle = i * angleStep - 3.1415926535 / 2; // 从顶部开始
angle += angleStep / 2; // 偏移到玩家之间的位置
int x = centerX + static_cast<int>((radius + 80) * cos(angle));
int y = centerY + static_cast<int>((radius + 80) * sin(angle));
// 渲染牌
renderCard(p.card, x, y, true);
// 显示使用状态
if (p.usedCard) {
settextcolor(RGB(0, 150, 0));
settextstyle(20, 0, _T("宋体"));
outtextxy(x - 30, y - 70, "已使用");
}
}
}
// 主函数
int main() {
// 初始化图形窗口
initgraph(WIDTH, HEIGHT);
setbkcolor(RGB(240, 240, 240));
cleardevice();
// 设置随机种子
srand(static_cast<unsigned int>(time(nullptr)));
// 创建游戏
Game game;
game.initialize(PLAYER_MIN + rand() % (PLAYER_MAX - PLAYER_MIN + 1));
// 游戏主循环
while (true) {
// 处理退出事件
if (_kbhit()) {
int key = _getch();
if (key == 27) { // ESC键退出
break;
} else if (key == 'r' || key == 'R') { // R键重新开始
game.initialize(PLAYER_MIN + rand() % (PLAYER_MAX - PLAYER_MIN + 1));
}
}
// 清屏
cleardevice();
// 游戏逻辑
if (!game.isGameOver()) {
// 思考阶段 (9秒)
for (int i = THINKING_TIME; i >= 0; i--) {
// 清屏
cleardevice();
// 渲染玩家
renderPlayers(game.getPlayers(), game.getCurrentPlayer(),
WIDTH/2, HEIGHT/2, 250);
// 渲染玩家手牌
renderPlayerCards(game.getPlayers(), WIDTH/2, HEIGHT/2, 250);
// 渲染游戏信息
renderGameInfo(game, i);
// 延迟1秒
Sleep(1000);
// 随机使用牌
for (int j = 0; j < game.getPlayers().size(); j++) {
if (game.getPlayers()[j].alive && !game.getPlayers()[j].usedCard) {
if (rand() % 3 == 0) { // 1/3概率使用牌
game.useCard(j);
}
}
}
}
// 处理牌效果
game.processCardEffects();
// 报数阶段
game.count();
// 如果游戏未结束,进入下一轮
if (!game.isGameOver()) {
game.nextRound();
}
}
// 渲染最终状态
cleardevice();
renderPlayers(game.getPlayers(), game.getCurrentPlayer(),
WIDTH/2, HEIGHT/2, 250);
renderPlayerCards(game.getPlayers(), WIDTH/2, HEIGHT/2, 250);
renderGameInfo(game, -1);
// 延迟一段时间
Sleep(2000);
}
closegraph();
return 0;
}”改善代码 游戏规则:6-10名玩家围成一圈为一组,每名玩家抽取顺序牌决定自己位置,随机抽报数牌决定n,2< =n< = 9,根据剩余玩家数量发牌,一人一张,五张技能牌,剩余牌为空,用牌前,可思考计算9秒并公开手牌(注:先用保位牌,再用杀人牌,再用换位牌,再用换数牌,最后用不死牌,可弃权)(保位牌:自身位置不可被交换,不被杀人牌杀死;杀人牌:指定淘汰一个玩家;换位牌:改变自身位置;换数牌:改变报数n;不死牌:本轮报数不被淘汰),报到n的玩家出局,再根据剩余玩家重新数量发牌,用牌,从淘汰的人的后一位开始报数,依次循环,止至只剩一个人(在使用技能牌阶段也可),此人便为胜利者,规则明确:如果报到n的玩家有不死牌,不会继续报下一个玩家