【C++】B2112 石头剪子布

server/2025/1/16 18:37:34/

在这里插入图片描述

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳]
本文专栏: C++

文章目录

  • 💯前言
  • 💯题目描述
    • 游戏规则:
    • 输入格式:
    • 输出格式:
    • 输入输出样例:
    • 解题分析与实现
  • 💯我的做法
    • 实现逻辑
    • 优点与不足
  • 💯老师的做法
    • 实现逻辑
    • 优点与不足
  • 💯对比分析
  • 💯优化与扩展
    • 优化代码实现
    • 优化后的优点
    • 扩展场景
  • 💯总结


在这里插入图片描述


💯前言

  • "石头剪子布"是一种经典游戏,它不仅规则简单,还能引发复杂的编程逻辑讨论。在本篇文章中,我们将以一道 C++ 的编程题为例,深入剖析解题的思路、优化方法,以及延伸出的编程概念。通过对比两种实现方式(我的实现和老师的实现),结合扩展性和代码优化的思路,帮助读者全面理解这一题目及其潜在的编程技巧。
    C++ 参考手册
    在这里插入图片描述

💯题目描述

B2112 石头剪子布
在这里插入图片描述

石头剪子布,是一种猜拳游戏,起源于中国,然后传到日本,朝鲜等地,随着亚欧贸易的不断发展它传到西欧,到了现代化逐渐国际化的世界中。简单明了的规则,使得石头剪子布没有任何知识和规则漏洞可钻,单次玩法让比赛公平,容易且充满心理博弈,使得石头剪子布这个古老的游戏同时用于“意外”与“技术”两种特性,深受世界人民喜爱。

游戏规则:

石头剪子布,布包石头,石头砸剪刀,剪刀剪布。

现在,需要你写一个程序来判断石头剪子布游戏的结果。

输入格式:

第一行是一个整数 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;elsecout << "Tie" << endl;}else if(s1 == "Scissors")	{if(s2 == "Scissors")cout << "Tie" << endl;else if(s2 == "Paper")cout << "Player1" << endl;elsecout << "Player2" << endl;}else{if(s2 == "Scissors")cout << "Player2" << endl;else if(s2 == "Paper")cout << "Tie" << endl;elsecout << "Player1" << endl;}}return 0;
}

在这里插入图片描述

实现逻辑

  1. 输入处理:读取整数 n,表示对局次数,循环读取 Player1Player2 的选择。

  2. 判断规则:

    • 通过嵌套的 if-else 分支,根据 Player1 的选择 (Rock, Scissors, Paper) 逐步判断 Player2 的选择,从而决定胜负。
    • 平局条件 (s1 == s2) 被单独处理。
  3. 逐行输出:根据每场比赛的结果,输出 “Player1”、“Player2” 或 “Tie”。

优点与不足

  • 优点:

    • 逻辑清晰,适合初学者。
    • 每种情况都显式列出,容易理解。
  • 不足:

    • 冗余逻辑:大量的条件分支导致代码较为臃肿。
    • 可扩展性差:如果加入新规则(如 “Lizard” 和 “Spock”),代码需要大规模改动。

💯老师的做法

以下是老师的代码实现:

#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;elsecout << "Player2" << endl;}	return 0;
}

在这里插入图片描述

实现逻辑

  1. 使用 while 循环减少代码结构的复杂性,每次循环中处理一场比赛。
  2. 平局条件 (s1 == s2) 优先判断,避免进入更多分支。
  3. Player1 的胜利条件通过显式列举的方式判断。
  4. 如果上述条件都不满足,则默认为 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;
}

优化后的优点

  1. 逻辑简化:通过查表判断胜负,避免嵌套的 if-else
  2. 易扩展性:增加新规则只需扩展 map,无需修改核心逻辑。
  3. 代码简洁:主逻辑更清晰,减少冗余判断。

扩展场景

  1. 多种新规则:如引入 “Lizard” 和 “Spock”。
  2. 支持多轮游戏:记录每场比赛的胜利者,并统计最终胜负结果。
  3. 本地化支持:使用多语言输出结果。

💯总结

通过这道题目,我们探讨了两种不同的解法,以及如何优化代码逻辑。我的实现和老师的实现都能正确解决问题,但在简洁性和扩展性上存在一定不足。优化后的代码通过数据结构简化了逻辑,提高了代码的可维护性和可扩展性。

编程不仅仅是实现功能,还在于如何更优雅、更高效地实现。本题为我们提供了一个非常好的练习机会,希望读者在掌握了这些方法后,能更深入地理解编程的本质和技巧。


在这里插入图片描述


在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

1. 理解C++的基础
学习重点:

  1. 掌握基本语法
    • 学会声明变量、条件语句、循环、函数等核心语法。
    • 掌握数组、指针、引用等基础知识。
  2. 熟悉标准输入输出
    • 掌握 cincout 的用法。
    • 理解格式化输出,例如 std::setwstd::fixed
  3. 记住编译器的角色
    • 理解源代码如何通过编译器转换为可执行程序,选择一款好的IDE(如Visual Studio、Clion、VSCode)。

建议:用大量小程序练习这些基础语法,比如写一个计算器、模拟猜数字游戏等。


2. 深入学习C++的特性
学习重点:

  1. 面向对象编程(OOP)
    • 理解类和对象,熟悉如何定义类、成员变量和成员函数。
    • 掌握封装、继承、多态三大核心特性。
  2. 内存管理
    • 理解指针的用法,掌握动态内存分配(newdelete)。
    • 学习如何避免内存泄漏,熟悉智能指针(如std::unique_ptrstd::shared_ptr)。
  3. 标准模板库(STL)
    • 熟悉常用的容器(如vectormapset)和算法(如sortfind)。
    • 掌握迭代器的用法。
  4. 异常处理
    • 学习使用try-catch块处理异常。
    • 理解异常的用途以及如何设计健壮的代码。

建议:尝试开发一个小型项目,比如一个学生管理系统,综合应用类、STL、指针和动态内存分配。


3. 掌握进阶内容
学习重点:

  1. 模板
    • 理解函数模板和类模板,掌握泛型编程思想。
    • 学习模板特化和模板元编程的基本概念。
  2. 多线程与并发
    • 学习 C++11 提供的多线程支持(如std::thread)。
    • 熟悉互斥锁(std::mutex)和条件变量(std::condition_variable)。
  3. C++与C的兼容性
    • 学习如何在C++中使用C语言代码,理解C和C++的区别。
    • 掌握C风格字符串(char[])和C++字符串(std::string)的转换。

建议:在这一阶段,可以挑战更复杂的项目,比如开发一个小型的HTTP服务器,学习网络编程并结合多线程。


4. 学习资源与实践方法
学习资源:

  1. 书籍
    • 《C++ Primer》:非常适合初学者的经典书籍。
    • 《Effective C++》:进阶学习C++最佳实践的指南。
    • 《The C++ Programming Language》:Bjarne Stroustrup(C++之父)的权威著作。
  2. 在线课程
    • Coursera 上的 C++ 编程课程。
    • YouTube 上免费的 C++ 系列教程。
  3. 社区与文档
    • 参与C++相关的论坛(如CSDN、Stack Overflow)。
    • 阅读官方文档(https://en.cppreference.com)。

实践方法:

  1. 多写代码,多调试
    • 每学一个概念后,写至少两个示例代码并进行调试。
  2. 做小项目
    • 从简单的控制台程序开始,比如文件读写、计算器、小游戏等。
    • 慢慢过渡到图形界面或网络程序开发。
  3. 阅读他人代码
    • 阅读开源项目的代码,理解优秀代码的设计思路。
  4. 参加编程比赛
    • 比如 LeetCode 或 Codeforces,可以帮助你提升算法能力和C++的熟练度。

5. 保持耐心与兴趣
学习C++可能会面临以下困难:

  1. 复杂的语法:如模板、智能指针、多线程等。
  2. 调试困难:指针错误、内存泄漏、未定义行为可能让人头疼。

如何应对:

  • 将大问题拆解成小问题,逐步解决。
  • 不断重复基础知识,以加深理解。
  • 保持兴趣,尝试一些有趣的项目,比如写一个游戏、制作一个简单的图形程序。

小结
学习C++需要一个循序渐进的过程,从基础语法到面向对象编程,再到进阶的模板和并发编程,每一步都需要耐心和实践。通过充分利用学习资源、进行大量编码练习,以及挑战实际项目,你一定可以成为C++的高手。记住,学习的核心在于理解,而非死记硬背。

祝你学有所成,享受C++编程的乐趣!



http://www.ppmy.cn/server/158886.html

相关文章

【HM-React】08. Layout模块

基本结构和样式reset 结构创建 实现步骤 打开 antd/Layout 布局组件文档&#xff0c;找到示例&#xff1a;顶部-侧边布局-通栏拷贝示例代码到我们的 Layout 页面中分析并调整页面布局 代码实现 pages/Layout/index.js import { Layout, Menu, Popconfirm } from antd impor…

中等难度——python实现电子宠物和截图工具

import io # 文件处理 import nt # windows nt 库直接获取对应的磁盘空间 import time # 时间 import zlib # 加解密 import ctypes # 调用 import struct # 处理字节二进制 import base64 # 编解码 import threading # 线程 import tkinter as tk # tk from datetime…

golang单元测试

单元测试 类型前缀签名用途测试函数Testfunc TestXxx(t *testing.T)功能测试、验证逻辑正确性基准函数Benchmarkfunc BenchmarkXxx(b *testing.B)性能测试、效率评估示例函数Examplefunc ExampleXxx()用法展示、生成文档 testing框架 文件名以_test.go结尾&#xff0c;放在与…

32单片机综合应用案例——智能家居灯光控制系统(二)(内附详细代码讲解!!!)

"即使世界看似残酷&#xff0c;也要坚持自己的梦想&#xff0c;因为只有这样&#xff0c;你才能创造属于自己的奇迹。”“不要害怕失败&#xff0c;因为失败是成功的垫脚石。”“即使跌倒了一百次&#xff0c;也要勇敢地爬起来一百零一次。”“永远不要低估自己的潜力&…

在服务器上增加新网段IP的路由配置

在服务器上增加新网段IP的路由配置 前提条件步骤一:检查当前路由表步骤二:添加新路由步骤三:验证新路由步骤四:持久化路由配置脚本示例结论在网络管理中,路由配置是一项基本且重要的任务。它决定了数据包在网络中的传输路径。本文将详细介绍如何在服务器上增加新的路由配置…

我的年度总结

这一年的人生起伏&#xff1a;从曙光到低谷再到新的曙光 其实本来没打算做年度总结的&#xff0c;无聊打开了帅帅的视频&#xff0c;结合自己最近经历的&#xff0c;打算简单聊下。因为原本打算做的内容会是一篇比较丧、低能量者的呻吟。 实习生与创业公司的零到一 第一段工…

【Python通过UDP协议传输视频数据】(界面识别)

提示&#xff1a;界面识别项目 前言 随着网络通信技术的发展&#xff0c;视频数据的实时传输在各种场景中得到了广泛应用。UDP&#xff08;User Datagram Protocol&#xff09;作为一种无连接的协议&#xff0c;凭借其低延迟、高效率的特性&#xff0c;在实时性要求较高的视频…

Go-Zero整合Goose实现MySQL数据库版本管理

推荐阅读 【系列好文】go-zero从入门到精通&#xff08;看了就会&#xff09; 教程地址&#xff1a;https://blog.csdn.net/u011019141/article/details/139619172 Go-Zero整合Goose实现MySQL数据库版本管理的教程 在开发中&#xff0c;数据库迁移和版本管理是必不可少的工作。…