石头剪子布,是一种猜拳游戏,起源于中国,然后传到日本,朝鲜等地,随着亚欧贸易的不断发展它传到西欧,到了现代化逐渐国际化的世界中。简单明了的规则,使得石头剪子布没有任何知识和规则漏洞可钻,单次玩法让比赛公平,容易且充满心理博弈,使得石头剪子布这个古老的游戏同时用于“意外”与“技术”两种特性,深受世界人民喜爱。
石头剪子布,布包石头,石头砸剪刀,剪刀剪布。
现在,需要你写一个程序来判断石头剪子布游戏的结果。
第一行是一个整数 N,表示一共进行 N 次游戏。1 <= N <= 100。 接下来 N 行的每一行包括两个字符串,表示游戏参与者 Player1,Player2 的选择(石头、剪刀或者布):S1,S2。
字符串之间以空格隔开 S1 S2 只可能取值在 [Rock, Scissors, Paper](大小写敏感)中。
输出包括 N 行,每一行对应一个胜利者(Player1 或者 Player2),或者游戏出现平局,则输出 Tie。
输入 #1
3
Rock Scissors
Paper Paper
Rock Paper
输出 #1
Player1
Tie
Player2
接下来,我们将从两个实现方式出发:我的做法、老师的做法,逐步剖析解决问题的不同方式,最后对比两种实现,并延展出优化和扩展思路。
以下是我的代码实现:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n;
cin >> n;
string s1, s2;
for(int i = 0; i < n; i++)
{
cin >> s1 >> s2;
if(s1 == "Rock")
{
if(s2 == "Scissors")
cout << "Player1" << endl;
else if(s2 == "Paper")
cout << "Player2" << endl;
else
cout << "Tie" << endl;
}
else if(s1 == "Scissors")
{
if(s2 == "Scissors")
cout << "Tie" << endl;
else if(s2 == "Paper")
cout << "Player1" << endl;
else
cout << "Player2" << endl;
}
else
{
if(s2 == "Scissors")
cout << "Player2" << endl;
else if(s2 == "Paper")
cout << "Tie" << endl;
else
cout << "Player1" << endl;
}
}
return 0;
}
n
,表示对局次数,循环读取 Player1
和 Player2
的选择。
if-else
分支,根据 Player1
的选择 (Rock
, Scissors
, Paper
) 逐步判断 Player2
的选择,从而决定胜负。s1 == s2
) 被单独处理。以下是老师的代码实现:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int n = 0;
cin >> n;
int i = 0;
string s1;
string s2;
while(n--)
{
cin >> s1;
cin >> s2;
if(s1 == s2)
cout << "Tie" << endl;
else if (s1 == "Rock" && s2 == "Scissors")
cout << "Player1" << endl;
else if (s1 == "Scissors" && s2 == "Paper")
cout << "Player1" << endl;
else if (s1 == "Paper" && s2 == "Rock")
cout << "Player1" << endl;
else
cout << "Player2" << endl;
}
return 0;
}
while
循环减少代码结构的复杂性,每次循环中处理一场比赛。s1 == s2
) 优先判断,避免进入更多分支。Player1
的胜利条件通过显式列举的方式判断。Player2
胜出。对比点 | 我的做法 | 老师的做法 |
---|---|---|
代码结构 | 使用嵌套 if-else,分支较多 | 使用单层 if-else,逻辑更清晰 |
冗余程度 | 条件分支更多,显式判断所有情况 | 条件分支较少,但仍有显式判断 |
可扩展性 | 新规则需要大规模修改 | 新规则需要大规模修改 |
适合初学者 | 逻辑直观,适合初学者练习 | 逻辑简化,更适合掌握基本结构的学生 |
为了进一步优化和扩展,我们可以使用数据结构来简化逻辑,提高可扩展性。
通过使用 map
存储胜负规则,可以避免显式列举所有情况。
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main() {
int n;
cin >> n;
// 定义胜负规则
map<string, string> winRules = {
{"Rock", "Scissors"},
{"Scissors", "Paper"},
{"Paper", "Rock"}
};
string s1, s2;
while (n--) {
cin >> s1 >> s2;
if (s1 == s2) {
cout << "Tie" << endl;
} else if (winRules[s1] == s2) {
cout << "Player1" << endl;
} else {
cout << "Player2" << endl;
}
}
return 0;
}
if-else
。map
,无需修改核心逻辑。通过这道题目,我们探讨了两种不同的解法,以及如何优化代码逻辑。我的实现和老师的实现都能正确解决问题,但在简洁性和扩展性上存在一定不足。优化后的代码通过数据结构简化了逻辑,提高了代码的可维护性和可扩展性。
编程不仅仅是实现功能,还在于如何更优雅、更高效地实现。本题为我们提供了一个非常好的练习机会,希望读者在掌握了这些方法后,能更深入地理解编程的本质和技巧。
1. 理解C++的基础 学习重点:
cin
和 cout
的用法。std::setw
和 std::fixed
。建议:用大量小程序练习这些基础语法,比如写一个计算器、模拟猜数字游戏等。
2. 深入学习C++的特性 学习重点:
new
和 delete
)。std::unique_ptr
和 std::shared_ptr
)。vector
、map
、set
)和算法(如sort
、find
)。try-catch
块处理异常。建议:尝试开发一个小型项目,比如一个学生管理系统,综合应用类、STL、指针和动态内存分配。
3. 掌握进阶内容 学习重点:
std::thread
)。std::mutex
)和条件变量(std::condition_variable
)。char[]
)和C++字符串(std::string
)的转换。建议:在这一阶段,可以挑战更复杂的项目,比如开发一个小型的HTTP服务器,学习网络编程并结合多线程。
4. 学习资源与实践方法 学习资源:
实践方法:
5. 保持耐心与兴趣 学习C++可能会面临以下困难:
如何应对:
小结 学习C++需要一个循序渐进的过程,从基础语法到面向对象编程,再到进阶的模板和并发编程,每一步都需要耐心和实践。通过充分利用学习资源、进行大量编码练习,以及挑战实际项目,你一定可以成为C++的高手。记住,学习的核心在于理解,而非死记硬背。
祝你学有所成,享受C++编程的乐趣!