这道题是一道经典的模拟题,考察的是对复杂规则的理解和代码实现能力。 题目地址
题目解析
这道题要求我们模拟一个在环形棋盘上进行的多玩家大富翁游戏。我们需要根据给定的规则,一步步执行每个玩家的回合,直到游戏结束。 非常非常大的令人恶心的模拟
核心规则梳理
游戏环境:
一个有 m 个格子的环形棋盘,编号 1 到 m。第 m 格的下一格是第 1 格。
n 名玩家,初始都在第 1 格,拥有各自的初始金币。
回合流程:
玩家按编号 1 到 n 的顺序循环行动。
停牌状态: 如果玩家处于停牌状态(由监狱格导致),则解除停牌,本回合不移动、不使用骰子。
正常移动: 否则,使用下一个骰子点数 d,顺时针移动 d 格。
触发效果: 移动后,根据落点格子的类型触发相应效果。
格子类型与效果:
起点格 (第 1 格): 落在该格获得 200 金币。注意:游戏开始时在第 1 格不触发此效果。
地产格:
无主: 如果玩家金币足够,必须购买(扣除价格,玩家成为地主)。
有主 (且地主不是自己): 需要向地主支付过路费。如果金币不足,支付所有金币并破产。
自己所有: 无效果。
幸运格: 获得 150 金币。
惩罚格: 扣除 100 金币。如果金币不足,扣除所有金币并破产。
监狱格: 进入停牌状态(下一回合不行动)。
破产规则:
当需要支付金币(过路费或惩罚)时,如果当前金币不足以支付,则支付所有剩余金币,金币变为 0,并立即破产。
如果金币恰好足够,支付后金币变为 0,但不会破产。
玩家破产后:金币为 0,其所有地产变为无主,并永久退出游戏(不再参与后续回合)。
游戏结束条件:
场上仅剩 1 名玩家未破产。
所有骰子都已使用完毕。
输出:
游戏结束时,按玩家编号顺序输出所有玩家的最终状态(金币数量)。
解题思路
这是一个纯粹的模拟问题,关键在于准确地将题目规则转化为代码逻辑。
数据结构设计:
玩家 (Player): 需要一个结构体来存储每个玩家的状态,包括:当前金币、当前位置、是否破产、是否停牌、拥有的地产列表。
棋盘 (Board): 需要一个数组或向量来表示棋盘上的每个格子。每个格子需要存储其类型和相关信息(如地产的价格、过路费、地主ID)。
骰子 (D): 一个数组或向量,按顺序存储所有骰子点数。
模拟主循环:
使用一个循环来模拟游戏回合。
在循环内部,遍历所有玩家(从 1 到 n)。
对于每个玩家,首先检查其是否已破产,如果破产则跳过。
然后检查游戏是否应该结束(只剩一个玩家或骰子用完)。
如果玩家未破产且游戏未结束,则执行该玩家的回合:
处理停牌状态。
如果未停牌,则掷骰子、移动、触发落点效果。
在处理效果时,需要仔细处理金币的增减和破产判断。
完整代码
#include<bits/stdc++.h>
using namespace std;
enum celltype{
start,
grounds,
lucky,
punish,
jali,
};
struct ground{
long long price;
long long toll;
int owner_id;
ground(long long p, long long t) : price(p), toll(t), owner_id(-1) {}
};
struct cell{
celltype type;
ground* str;
cell() : type(start), str(NULL) {}
cell(celltype t) : type(t), str(NULL) {}
cell(ground* p) : type(grounds), str(p) {}
};
struct Player{
int id;
long long coins;
int pos;
bool is_broke;
bool is_ban;
vector<int> groundd;
Player(int i, long long c) : id(i), coins(c), pos(1), is_broke(false), is_ban(false) {}
};
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, m;
cin >> n >> m;
vector<Player> players;
for(int i = 1; i <= n; i++){
long long ci;
cin >> ci;
players.emplace_back(i, ci);
}
vector<cell> board(m + 1);
for(int i = 1; i <= m; i++){
int types;
cin >> types;
if(types == 0){
board[i] = cell(start);
} else if(types == 1){
long long p, t;
cin >> p >> t;
board[i] = cell(new ground(p, t));
} else if(types == 2){
board[i] = cell(lucky);
} else if(types == 3){
board[i] = cell(punish);
} else if(types == 4){
board[i] = cell(jali);
}
}
int k;
cin >> k;
vector<long long> d(k);
for(int i = 0; i < k; i++){
cin >> d[i];
}
int d_i = 0;
int player_nobroke = n;
while(d_i < k && player_nobroke > 1){
for(int i = 0; i < n; i++){
Player& player = players[i];
if(player.is_broke) continue;
if(d_i >= k || player_nobroke <= 1) break;
if(player.is_ban){
player.is_ban = false;
} else {
long long ds = d[d_i++];
long long new_pos = (long long)player.pos + ds;
player.pos = (int)((new_pos - 1) % m + 1);
cell& current_cell = board[player.pos];
switch(current_cell.type){
case start:
player.coins += 200;
break;
case grounds: {
ground* str = current_cell.str;
if(str->owner_id == -1){
if(player.coins >= str->price){
player.coins -= str->price;
str->owner_id = player.id;
player.groundd.push_back(player.pos);
}
}
else if(str->owner_id != player.id){
long long t = str->toll;
if(player.coins < t){
players[str->owner_id - 1].coins += player.coins;
player.coins = 0;
player.is_broke = true;
player_nobroke--;
for(int str_pos : player.groundd){
board[str_pos].str->owner_id = -1;
}
player.groundd.clear();
} else {
player.coins -= t;
players[str->owner_id - 1].coins += t;
}
}
break;
}
case lucky:
player.coins += 150;
break;
case punish:
if(player.coins < 100){
player.coins = 0;
player.is_broke = true;
player_nobroke--;
for(int str_pos : player.groundd){
board[str_pos].str->owner_id = -1;
}
player.groundd.clear();
} else {
player.coins -= 100;
}
break;
case jali:
player.is_ban = true;
break;
}
if(d_i >= k || player_nobroke <= 1) break;
}
}
}
for (int i = 0; i < n; ++i) {
if (players[i].is_broke) {
cout << "bankrupt 0";
} else {
cout << players[i].coins << " " << players[i].groundd.size();
}
if (i < n - 1) cout << "\n";
}
cout << endl;
for (int i = 1; i <= m; ++i) {
if (board[i].type == grounds){
delete board[i].str;
}
}
return 0;
}
牛逼
谢谢