Initial upload, done, just need to polish things and make sure the style guide is good

This commit is contained in:
Tyler Beckman 2024-09-01 23:26:25 -06:00
commit 6bcba76cfa
Signed by: Ty
GPG key ID: 2813440C772555A4
9 changed files with 390 additions and 0 deletions

39
.clang-format Normal file
View file

@ -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

39
.class-clang-format Normal file
View file

@ -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

18
.vscode/c_cpp_properties.json vendored Normal file
View file

@ -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
}

24
.vscode/launch.json vendored Normal file
View file

@ -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
}
]
}
]
}

62
.vscode/settings.json vendored Normal file
View file

@ -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++"
]
}

24
Makefile Normal file
View file

@ -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)

71
hands.cpp Normal file
View file

@ -0,0 +1,71 @@
#include "hands.h"
#include <chrono>
#include <iostream>
#include <memory>
#include <random>
#include <cstdlib>
std::unique_ptr<Hand> Hand::fromChar(const char letter) {
switch (letter) {
case 'R':
case 'r':
return std::make_unique<Rock>();
case 'P':
case 'p':
return std::make_unique<Paper>();
case 'S':
case 's':
return std::make_unique<Scissors>();
default:
std::cout << "Invalid choice" << std::endl;
std::exit(1);
}
}
std::unique_ptr<Hand> Hand::generateRandom() {
std::mt19937 mt(
std::chrono::steady_clock::now().time_since_epoch().count());
std::uniform_int_distribution<int> intDist(0, 2);
switch (intDist(mt)) {
case 0:
return std::make_unique<Rock>();
case 1:
return std::make_unique<Paper>();
case 2:
return std::make_unique<Scissors>();
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;
}

39
hands.h Normal file
View file

@ -0,0 +1,39 @@
#include <istream>
#include <memory>
enum GameResult { Win, Tie, Loss };
class Hand {
public:
// Converts a user-inputted character to the correct instance of Hand.
static std::unique_ptr<Hand> fromChar(char);
// Randomly returns one of the variants of Hand.
static std::unique_ptr<Hand> 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;
};

74
main.cpp Normal file
View file

@ -0,0 +1,74 @@
#include "hands.h"
#include <iostream>
#include <memory>
#include <ostream>
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<Hand> userHand = Hand::fromChar(handLetter);
// Generate a random "computer" hand and display the two choices
const std::unique_ptr<Hand> 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);
}
}
}