From 6bcba76cfad4935b572c8aad8c8de49df38e74db53f5c235c06353cc92e001b4 Mon Sep 17 00:00:00 2001 From: Tyler Beckman Date: Sun, 1 Sep 2024 23:26:25 -0600 Subject: [PATCH] Initial upload, done, just need to polish things and make sure the style guide is good --- .clang-format | 39 ++++++++++++++++++ .class-clang-format | 39 ++++++++++++++++++ .vscode/c_cpp_properties.json | 18 +++++++++ .vscode/launch.json | 24 ++++++++++++ .vscode/settings.json | 62 +++++++++++++++++++++++++++++ Makefile | 24 ++++++++++++ hands.cpp | 71 +++++++++++++++++++++++++++++++++ hands.h | 39 ++++++++++++++++++ main.cpp | 74 +++++++++++++++++++++++++++++++++++ 9 files changed, 390 insertions(+) create mode 100644 .clang-format create mode 100644 .class-clang-format create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 Makefile create mode 100644 hands.cpp create mode 100644 hands.h create mode 100644 main.cpp diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..345138d --- /dev/null +++ b/.clang-format @@ -0,0 +1,39 @@ +IndentWidth: 4 +UseTab: Always +TabWidth: 4 +InsertBraces: false +SortIncludes: true +IncludeBlocks: Regroup +IncludeCategories: + # System headers from C + - Regex: '<(cassert|ccomplex|cctype|cerrno|cfenv|cfloat|cinttypes|ciso646|climits|clocale|cmath|csetjmp|csignal|cstdalign|cstdarg|cstdatomic|cstdbool|cstddef|cstdint|cstdio|cstdlib|cstdnoreturn|cstring|ctgmath|cthreads|ctime|cuchar|cwchar|cwctype)>' + Priority: 3 + # System headers without extension. + - Regex: '<([A-Za-z0-9\Q/-_\E])+>' + Priority: 2 + # Local headers with extension. + - Regex: '"([A-Za-z0-9\Q/-_\E])+\.h(pp)?"' + Priority: 1 +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +IndentCaseLabels: true +IntegerLiteralSeparator: + Binary: 0 + Decimal: 3 + Hex: -1 \ No newline at end of file diff --git a/.class-clang-format b/.class-clang-format new file mode 100644 index 0000000..8f34370 --- /dev/null +++ b/.class-clang-format @@ -0,0 +1,39 @@ +IndentWidth: 2 +UseTab: Never +TabWidth: 2 +InsertBraces: true +SortIncludes: true +IncludeBlocks: Regroup +IncludeCategories: + # System headers from C + - Regex: '<(cassert|ccomplex|cctype|cerrno|cfenv|cfloat|cinttypes|ciso646|climits|clocale|cmath|csetjmp|csignal|cstdalign|cstdarg|cstdatomic|cstdbool|cstddef|cstdint|cstdio|cstdlib|cstdnoreturn|cstring|ctgmath|cthreads|ctime|cuchar|cwchar|cwctype)>' + Priority: 3 + # System headers without extension. + - Regex: '<([A-Za-z0-9\Q/-_\E])+>' + Priority: 2 + # Local headers with extension. + - Regex: '"([A-Za-z0-9\Q/-_\E])+\.h(pp)?"' + Priority: 1 +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +IndentCaseLabels: true +IntegerLiteralSeparator: + Binary: -1 + Decimal: -1 + Hex: -1 \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..357fb81 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,18 @@ +{ + "configurations": [ + { + "name": "linux-gcc-x64", + "includePath": [ + "${workspaceFolder}/**" + ], + "compilerPath": "/usr/bin/gcc", + "cStandard": "${default}", + "cppStandard": "${default}", + "intelliSenseMode": "linux-gcc-x64", + "compilerArgs": [ + "" + ] + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d199ded --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "C/C++ Runner: Debug Session", + "type": "cppdbg", + "request": "launch", + "args": [], + "stopAtEntry": false, + "externalConsole": false, + "cwd": "/home/ty/Dev/School/CSCI200/Sets/1/A1", + "program": "/home/ty/Dev/School/CSCI200/Sets/1/A1/build/Debug/outDebug", + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..09a8106 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,62 @@ +{ + "C_Cpp_Runner.cCompilerPath": "gcc", + "C_Cpp_Runner.cppCompilerPath": "g++", + "C_Cpp_Runner.debuggerPath": "gdb", + "C_Cpp_Runner.cStandard": "", + "C_Cpp_Runner.cppStandard": "", + "C_Cpp_Runner.msvcBatchPath": "", + "C_Cpp_Runner.useMsvc": false, + "C_Cpp_Runner.warnings": [ + "-Wall", + "-Wextra", + "-Wpedantic", + "-Wshadow", + "-Wformat=2", + "-Wcast-align", + "-Wconversion", + "-Wsign-conversion", + "-Wnull-dereference" + ], + "C_Cpp_Runner.msvcWarnings": [ + "/W4", + "/permissive-", + "/w14242", + "/w14287", + "/w14296", + "/w14311", + "/w14826", + "/w44062", + "/w44242", + "/w14905", + "/w14906", + "/w14263", + "/w44265", + "/w14928" + ], + "C_Cpp_Runner.enableWarnings": true, + "C_Cpp_Runner.warningsAsError": false, + "C_Cpp_Runner.compilerArgs": [], + "C_Cpp_Runner.linkerArgs": [], + "C_Cpp_Runner.includePaths": [], + "C_Cpp_Runner.includeSearch": [ + "*", + "**/*" + ], + "C_Cpp_Runner.excludeSearch": [ + "**/build", + "**/build/**", + "**/.*", + "**/.*/**", + "**/.vscode", + "**/.vscode/**" + ], + "C_Cpp_Runner.useAddressSanitizer": false, + "C_Cpp_Runner.useUndefinedSanitizer": false, + "C_Cpp_Runner.useLeakSanitizer": false, + "C_Cpp_Runner.showCompilationTime": false, + "C_Cpp_Runner.useLinkTimeOptimization": false, + "C_Cpp_Runner.msvcSecureNoWarnings": false, + "clang-tidy.compilerArgsBefore": [ + "-xc++" + ] +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fb630b7 --- /dev/null +++ b/Makefile @@ -0,0 +1,24 @@ +TARGET = A1 +SRC_FILES = main.cpp hands.cpp + +# NO EDITS BELOW THIS LINE +CXX = g++ -g +OBJECTS = $(SRC_FILES:.cpp=.o) + +ifeq ($(shell echo "Windows"), "Windows") + TARGET := $(TARGET).exe + DEL = del +else + DEL = rm -f +endif + +all: $(TARGET) + +$(TARGET): $(OBJECTS) + $(CXX) -std=c++17 -o $@ $^ + +%.o: %.cpp + $(CXX) -std=c++17 -o $@ -c $< + +clean: + $(DEL) $(TARGET) $(OBJECTS) \ No newline at end of file diff --git a/hands.cpp b/hands.cpp new file mode 100644 index 0000000..bb97e04 --- /dev/null +++ b/hands.cpp @@ -0,0 +1,71 @@ +#include "hands.h" + +#include +#include +#include +#include +#include + +std::unique_ptr Hand::fromChar(const char letter) { + switch (letter) { + case 'R': + case 'r': + return std::make_unique(); + case 'P': + case 'p': + return std::make_unique(); + case 'S': + case 's': + return std::make_unique(); + default: + std::cout << "Invalid choice" << std::endl; + std::exit(1); + } +} + +std::unique_ptr Hand::generateRandom() { + std::mt19937 mt( + std::chrono::steady_clock::now().time_since_epoch().count()); + std::uniform_int_distribution intDist(0, 2); + + switch (intDist(mt)) { + case 0: + return std::make_unique(); + case 1: + return std::make_unique(); + case 2: + return std::make_unique(); + default: + std::cerr << "An invalid random number was generated, this should be impossible" << std::endl; + std::exit(1); + } +} + +// List of function implementations for all of the different types of Hand + +std::string Rock::getHandName() const { return "rock"; } +GameResult Rock::compareAgainst(const Hand &other) { + const std::string otherName = other.getHandName(); + + if (otherName == "rock") return GameResult::Tie; + if (otherName == "scissors") return GameResult::Win; + else return GameResult::Loss; +} + +std::string Paper::getHandName() const { return "paper"; } +GameResult Paper::compareAgainst(const Hand &other) { + const std::string otherName = other.getHandName(); + + if (otherName == "paper") return GameResult::Tie; + if (otherName == "rock") return GameResult::Win; + else return GameResult::Loss; +} + +std::string Scissors::getHandName() const { return "scissors"; } +GameResult Scissors::compareAgainst(const Hand &other) { + const std::string otherName = other.getHandName(); + + if (otherName == "scissors") return GameResult::Tie; + if (otherName == "paper") return GameResult::Win; + else return GameResult::Loss; +} \ No newline at end of file diff --git a/hands.h b/hands.h new file mode 100644 index 0000000..55e933f --- /dev/null +++ b/hands.h @@ -0,0 +1,39 @@ +#include +#include + +enum GameResult { Win, Tie, Loss }; + +class Hand { + public: + // Converts a user-inputted character to the correct instance of Hand. + static std::unique_ptr fromChar(char); + // Randomly returns one of the variants of Hand. + static std::unique_ptr generateRandom(); + + // Returns the lowercase name of this type of hand, for example "rock" or + // "scissors". + virtual std::string getHandName() const = 0; + // Returns if this instance of Hand wins against another instance. The + // returned value is from the perspective of this instance of hand. For + // example, if GameResult::Win is returned, the instance of Hand wins + // against the passed argument Hand. + virtual GameResult compareAgainst(const Hand&) = 0; +}; + +class Rock : public Hand { + public: + std::string getHandName() const override; + GameResult compareAgainst(const Hand&) override; +}; + +class Paper : public Hand { + public: + std::string getHandName() const override; + GameResult compareAgainst(const Hand&) override; +}; + +class Scissors : public Hand { + public: + std::string getHandName() const override; + GameResult compareAgainst(const Hand&) override; +}; \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..65cba09 --- /dev/null +++ b/main.cpp @@ -0,0 +1,74 @@ +#include "hands.h" + +#include +#include +#include + +int main(void) { + int wins = 0; + int losses = 0; + int ties = 0; + + while (true) { + // Take a letter input and convert it to the correct class type for + // later + // use + char handLetter; + std::cout << "Welcome to a round of Rock Paper Scissors! Please enter " + "a hand to play (R/P/S): "; + std::cin >> handLetter; + const std::unique_ptr userHand = Hand::fromChar(handLetter); + + // Generate a random "computer" hand and display the two choices + const std::unique_ptr computerHand = Hand::generateRandom(); + + std::cout << std::endl + << "Player chose " << userHand->getHandName() << std::endl + << "Computer chose " << computerHand->getHandName() + << std::endl + << std::endl; + + // Compare the two hands, add to statistics, and give the correct output + // and explanation + switch (userHand->compareAgainst(*computerHand)) { + case Win: + std::cout << "The player wins, as " << userHand->getHandName() + << " beats " << computerHand->getHandName() << "!" + << std::endl; + wins++; + break; + case Tie: + std::cout << "No one wins, as " << userHand->getHandName() + << " is the same as " << computerHand->getHandName() + << "." << std::endl; + ties++; + break; + case Loss: + std::cout << "The computer wins, as " + << computerHand->getHandName() << " beats " + << userHand->getHandName() << "." << std::endl; + losses++; + break; + } + + // Ask if the user would like to play again or exit + char playAgain; + std::cout << "Do you want to play again (Y/N)? "; + std::cin >> playAgain; + switch (playAgain) { + case 'Y': + case 'y': + std::cout << std::endl; + continue; + case 'N': + case 'n': + default: + std::cout << std::endl + << "Thanks for playing!" << std::endl + << "You won " << wins << " game(s), lost " << losses + << " game(s), and tied " << ties << " time(s)." + << std::endl; + std::exit(0); + } + } +} \ No newline at end of file