C++面向对象501飞镖游戏无法显示玩家分数的调试求助
问题分析与修复方案
你的代码存在多个核心逻辑错误,导致分数无法显示且程序逻辑失效,以下是逐一分析和修复:
1. main函数参数完全错误
C++标准规定main函数的合法签名只能是:
int main() // 或 int main(int argc, char* argv[])
你当前的main函数带了一堆未初始化的参数,这些参数都是垃圾值,完全没有意义,程序启动时根本不会给它们赋值。必须改为标准签名,在函数内部初始化变量。
2. create_player函数无效且错误
- 该函数创建的
player对象是局部变量,函数结束后就被销毁,没有任何作用。 - C++的逗号表达式
return a,b,c只会返回最后一个值c,你的返回语句实际上只返回sidwon,其他变量完全被丢弃。 - 这个函数根本没在
main里调用,等于白写。
修复:给player类添加getter方法(当前只有setter,无法读取私有成员),直接在main里初始化玩家对象。
修改后的Player.h:
#pragma once #include <string> using namespace std; class player { private: string playername; int hitrate; int score; bool won; public: void setup_playername(string newplayername) { playername = newplayername; } void setup_hitrate(int newhitrate) { hitrate = newhitrate; } void setup_score(int newscore) { score = newscore; } void setup_won(bool newwon) // 修正参数类型:原代码是int,应改为bool { won = newwon; } // 添加getter方法,用于读取私有成员 string get_playername() const { return playername; } int get_hitrate() const { return hitrate; } int get_score() const { return score; } bool get_won() const { return won; } };
3. dartThrowLoop的致命问题
- 值传递导致分数不更新:你传递的
joescore是值拷贝,函数内部修改的是局部变量,外部的分数根本不会变。需要改为引用传递int& joescore,或者直接操作player对象。 - 死循环:
joewon是值传递,函数内部永远不会修改外部的joewon,循环条件joewon == false永远成立,程序会卡在循环里,永远执行不到后面的cout。 - 缺少策略更新:每次投掷后分数变化,需要重新判断策略,而不是只在最开始判断一次。
- 遗漏"throw double"分支:当前代码里没有处理这个策略,导致分数在42-131之间时没有任何投掷逻辑。
- randThrow范围错误:
rand()%(21)+10会生成10-30的数,飞镖盘只有1-20的区域,这里会出现无效值,应该改为rand()%20 +1生成1-20。 - throw_bull参数错误:原代码传入
randThrow,但该函数需要的是命中率p,应传入玩家的hitrate。
修复后的dartThrowLoop(改为操作player对象更符合面向对象设计):
void dartThrowLoop(player& p) // 引用传递玩家对象,修改会同步到外部 { while (!p.get_won()) { string strat = decide_stratagey(p.get_score(), 0); // 第二个参数传入对手分数,这里简化为0 for (int i = 0; i < 3; i++) { int currentScore = p.get_score(); int hitValue = 0; int randThrow = rand()%20 +1; // 生成1-20的有效区域 if (strat == "throwtreble20") { hitValue = throw_treble(20, p.get_hitrate()); } else if (strat == "throw treble") { hitValue = throw_treble(randThrow, p.get_hitrate()); } else if (strat == "throw double") { int reqdbl = currentScore / 2; hitValue = throw_double(reqdbl); } else if (strat == "throw single") { hitValue = throw_single(randThrow); } else if (strat == "bullseye") { hitValue = throw_bull(p.get_hitrate()); } // 遵循501规则:不能让分数变为负数,也不能是奇数(除了0) if (currentScore - hitValue >= 0 && (currentScore - hitValue == 0 || (currentScore - hitValue) % 2 == 0)) { p.setup_score(currentScore - hitValue); } // 判断是否获胜 if (p.get_score() == 0) { p.setup_won(true); break; } } // 每次3镖后输出当前分数,方便调试 cout << p.get_playername() << " 当前分数:" << p.get_score() << endl; } }
4. main函数逻辑完全缺失
原main函数只是调用了一堆函数但不接收返回值,也没有初始化变量,修复后的main函数应该:
- 初始化随机数种子(确保每次运行随机结果不同)
- 初始化玩家对象
- 调用投掷循环
- 输出最终结果
修复后的main:
int main() { srand(time(0)); // 初始化随机数种子 // 初始化玩家Joe player joe; joe.setup_playername("Joe"); joe.setup_hitrate(71); joe.setup_score(501); joe.setup_won(false); // 初始化玩家Sid player sid; sid.setup_playername("Sid"); sid.setup_hitrate(73); sid.setup_score(501); sid.setup_won(false); // 模拟游戏循环(这里简化为Joe先投掷,可扩展为轮流投掷) dartThrowLoop(joe); cout << endl << joe.get_playername() << " 获胜!最终分数:" << joe.get_score() << endl; return 0; }
5. 其他小问题
decide_stratagey拼写错误:应为decide_strategy(不影响运行,但建议修正)throw_treble注释里的(o<90)应为(p<90)
内容的提问来源于stack exchange,提问作者Danny Woods
相关产品推荐
相关产品推荐

