P-03
C++ Fundamentals Programming Showcase
A collection of C++ programs developed during my programming course, demonstrating various concepts including elementary data types, control structures, functions, arrays, strings, fundamental algorithms, computer organization, memory management, game logic, mathematical computations, data structures, and user interaction. Each program showcases different aspects of C++ programming fundamentals.
main.cpp
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include "conversions.hpp"
#include "blackjack.hpp"
#include "maya_numbers.hpp"
#include "factors.hpp"
#include "numbers.hpp"
using namespace std;
string inputCheck(string& input) {
while(true) {
if( (input == "exit" || input == "EXIT") ||
((input.size() == 1) && (input[0] == '1' || input[0] == '2' ||
input[0] == '3' || input[0] == '4' || input[0] == '5' || input[0] == '6')))
{
return input;
}
cin.clear();
cin.ignore(10000, '\n');
cout << '\n' << "Invalid Input. Please enter either 1, 2, 3, 4, 5, 6 or exit: ";
cin >> input;
}
}
int main() {
string input;
cout << "Hello! My name is Elijah and I completed several assignments in C++." << '\n';
cout << "I included them all here in one file for you to enjoy!" << '\n' << '\n';
do {
cout << "Please input a number from the list of options, or type exit to quit." << '\n' << '\n'
<< "MENU" << '\n'
<< "--------" << '\n' << '\n';
cout << "1) Circle Area" << '\n' << '\n'
<< "2) Distance Converter" << '\n' << '\n'
<< "3) Factors of Numbers" << '\n' << '\n'
<< "4) Convert Integer Numbers to Strings" << '\n' << '\n'
<< "5) Mayan Number Game" << '\n' << '\n'
<< "6) Blackjack" << '\n' << '\n';
cout << "Please select a game to play: ";
cin >> input;
input = inputCheck(input);
cout << endl;
if (input == "1") circleRadius();
else if (input == "2") distance();
else if (input == "3") factors();
else if (input == "4") numbers();
else if (input == "5") maya_numbers();
else if (input == "6") playBlackJackGame();
else if ((input == "exit" || input == "EXIT")) {
cout << '\n' << "Thank you for checking out my work!" << '\n';
return 0;
}
} while((input!= "exit") || input != "EXIT");
cout << '\n' << "Thank you for checking out my work!" << '\n';
return 0;
}Blackjack Game
struct Card // a struct is a way to group related information together
{
string suit;
string name;
int rank;
int value;
Card() // a constructor is having the form come with pre-filled boxes so pages arent blank
{
suit = "";
name = "";
rank = 0;
value = 0;
}
};
using namespace std;
// Creates new deck of cards (ordered)
vector<Card> getNewDeck()
{
vector<Card> deck; // new vector of called deck of Card objects
string suits[] = {"Spades", "Hearts", "Diamonds", "Clubs"}; // array of suits
char suitInitials[] = {'S', 'H', 'D', 'C'}; // array of suit initials
for(int suit = 0; suit < 4; suit++) // loops through each suit
{
for(int rank = 1; rank <= 13; rank++) // loops through each rank of card
{
Card newCard; // creates a new card
newCard.suit = suits[suit]; // assigns it the corresponding suit
newCard.rank = rank; // assigns it the corresponding rank
// Adds rank to cards name
if (rank == 1) newCard.name = "A"; // case for ace
else if (rank == 11) newCard.name = "J"; // case for jack
else if (rank == 12) newCard.name = "Q"; // case for queen
else if (rank == 13) newCard.name = "K"; // case for king
else newCard.name = to_string(rank); // converts integer r into a string to store in text
newCard.name += suitInitials[suit]; //assigns suit initial to name after the rank
if(rank == 1) newCard.value = 11; // gives aces a value of 11
else if (rank >= 11 && rank <= 13) newCard.value = 10; // gives face cards a value of 10
else newCard.value = rank; // assigns other cards the value of their rank
deck.push_back(newCard); // adds the card to the deck
}
}
return deck; // returns completed deck of cards once loops are finished
}
// Prints card deck
void printDeck(const vector<Card>& deck)
{
for(int i = 0; i < deck.size(); i++) // prints corresponding to size of vector deck
{
cout << setw(3) << deck[i].name << " "; // prints their name, spaced nicely with setw
if((i+1) % 13 == 0) cout << '\n'; // every 13th card, creates a newline
}
}
// Randomly rearranges the cards in a deck
void shuffleDeck(vector<Card>& deck)
{
for(int i = 0; i < deck.size(); i++) // loops through each card in the deck
{
int randomIndex = rand() % deck.size(); // generates random index from 0 to last index of deck
Card tempHolder = deck[i]; // temporary card variable to hold current card so it isnt lost during swap
deck [i] = deck [randomIndex]; // swaps current card with the card at the random index
deck [randomIndex] = tempHolder; // to hold card swapped with to not lose original
}
}
// Deals one card from a deck to a hand.
void deal(vector<Card>& deck, vector<Card>& hand)
{
// if the deck is empty, replace with a fresh shuffled deck
if (deck.empty())
{
deck = getNewDeck(); // new 52-card deck
shuffleDeck(deck); // shuffle before dealing
}
Card top = deck.back(); // copy last card
deck.pop_back(); // remove from deck
hand.push_back(top); // add to hand
}
// Calculates the sum of each cards value in a hand.
int handValue(const vector<Card>& hand)
{
int value = 0; // running total for hand value
int aceCount = 0; // tracks how many aces are in the hand
const int bustLimit = 21; // maximum total before busting
const int aceAdjustmentFactor = 10; // amount to reduce value when treating ace as 1 instead of 11
for(int i = 0; i < hand.size(); i++) // loops through every card in the hand
{
value += hand[i].value; // adds card value to running total
if ( hand[i].rank == 1) aceCount++; // counts aces by checking rank
}
while(value > bustLimit && aceCount > 0) // reduces value while over 21 and there are aces to adjust
{
value -= aceAdjustmentFactor; // converts one ace from 11 to 1
aceCount--; // one less ace available for adjustment
}
return value; // returns best hand value without busting if possible
}
// Checks for an endgame condition.
bool winCheck(const vector<Card>& handPlayer, const vector<Card>& handDealer, const int WIN_CONDITION)
{
if(handValue(handPlayer) == WIN_CONDITION && handValue(handDealer) == WIN_CONDITION) // checks for tie
{
cout << "Dealer Drew: " << handDealer[0].name << " " << handDealer[1].name << '\n' << '\n';
cout << "Draw! Both dealer and player drew blackjack" << '\n';
return true; // game is over, outcome decided
}
else if(handPlayer.size() > 2 && handValue(handPlayer) == WIN_CONDITION) // if player draws to 21 on their turn
{
cout << '\n' << "You drew to twenty-one. You win!" << '\n';
return true; // game ends with player win
}
else if(handDealer.size() > 2 && handValue(handDealer) == WIN_CONDITION) // if dealer draws to 21 on their turn
{
cout << '\n' << "Dealer got twenty-one. You lose!" << '\n';
return true; // game ends with dealer win
}
else if(handValue(handPlayer) == WIN_CONDITION && (handValue(handDealer) != WIN_CONDITION)) // checks for your blackjack
{
cout << "Dealer Drew: " << handDealer[0].name << " " << handDealer[1].name << '\n' << '\n';
cout << "Blackjack! You win." << '\n';
return true; // player blackjack ends game
}
else if(handValue(handPlayer) != WIN_CONDITION && handValue(handDealer) == WIN_CONDITION) // checks for dealers blackjack on game start
{
cout << "Dealer Drew: " << handDealer[0].name << " " << handDealer[1].name << '\n' << '\n';
cout << "Dealer got a blackjack. You lose!" << '\n';
return true; // dealer blackjack ends game
}
else if(handValue(handPlayer) > WIN_CONDITION) // if player busts on their turn
{
cout << "Dealer Drew: " << handDealer[0].name << " " << handDealer[1].name << '\n' << '\n';
cout << "Bust! You lose." << '\n';
return true; // game ends due to player bust
}
else if(handValue(handDealer) > WIN_CONDITION) // if dealer busts on their turn
{
cout << '\n' << "Dealer bust. You Win!" << '\n';
return true; // game ends due to dealer bust
}
return false; // no terminal condition yet, game continues
}
// Function used to return a value used for game-to-game score tracking if an endgame is detected.
int scoreTracker(const vector<Card>& handPlayer, const vector<Card>& handDealer, const int WIN_CONDITION)
{
if(handValue(handPlayer) == WIN_CONDITION && handValue(handDealer) == WIN_CONDITION) // checks for tie
{
return 0; // tie score
}
else if(handValue(handPlayer) == WIN_CONDITION && (handValue(handDealer) != WIN_CONDITION)) // checks for your blackjack
{
return 1; // player win
}
else if(handValue(handPlayer) != WIN_CONDITION && handValue(handDealer) == WIN_CONDITION) // checks for dealers blackjack
{
return -1; // dealer win
}
else if(handValue(handPlayer) > WIN_CONDITION)
{
return -1; // player busts, dealer wins
}
else if(handValue(handDealer) > WIN_CONDITION)
{
return 1; // dealer busts, player wins
}
else return 0; // default to tie in non-terminal case (used with winCheck)
}
// Function to draw and reveal the first card.
void firstCard(vector<Card>& deck, vector<Card>& handPlayer, vector<Card>& handDealer)
{
deal(deck, handPlayer); // deal first card to player
deal(deck, handDealer); // deal first card to dealer
cout << '\n' << "Deal first card" << '\n' << "---------------" << '\n';
cout << "Player Drew: " << handPlayer[0].name << '\n'; // show player's first card
cout << "Dealer Drew: " << handDealer[0].name << '\n' << '\n'; // show dealer's first card
}
// Function to draw and reveal the second card.
void secondCard(vector<Card>& deck, vector<Card>& handPlayer, vector<Card>& handDealer)
{
const string DEALER_UNKNOWN = "??"; // placeholder hides dealer's second card from player
deal(deck, handPlayer); // deal second card to player
deal(deck, handDealer); // deal second card to dealer
cout << "Deal second card" << '\n' << "---------------" << '\n';
cout << "Player Drew: " << handPlayer[0].name << " " << handPlayer[1].name << '\n'; // show both player cards
cout << "Dealer Drew: " << handDealer[0].name << " " << DEALER_UNKNOWN << '\n'; // only reveal dealer's first card
}
// Ensures the player inputted a valid character when asked if they would like to hit OR stand.
char choiceValidation(char choice)
{
while(cin.fail() || (choice != 'h' && choice != 's' && choice != 'H' && choice != 'S')) // repeats until valid hit/stand character
{
cin.clear(); // clears error state on cin
cin.ignore(10000, '\n'); // discards remaining invalid input
cout << "Invalid input, please enter h for hit OR s for stand: "; // prompt user again
cin >> choice; // get new input
}
return choice; // return validated choice
}
// Ensures that the player inputted a valid character when asked if they would like to play a new game.
char choicePlayBlackJackValidation(char choicePlayBlackjack)
{
while(cin.fail() || (choicePlayBlackjack != 'y' && choicePlayBlackjack != 'Y' && choicePlayBlackjack != 'n' && choicePlayBlackjack != 'N')) // repeats until valid yes/no input
{
cin.clear(); // clears error state on cin
cin.ignore(10000, '\n'); // discards remaining invalid input
cout << "Invalid input, please enter n for no OR y for yes: "; // prompt user again
cin >> choicePlayBlackjack; // get new input
}
return choicePlayBlackjack; // return validated yes/no choice
}
// Gives advice to the player on hitting OR standing based on their hand and the dealers upcard
void giveAdvice(const vector<Card>& playerHand, const vector<Card>& dealerHand)
{
int playerHandValue = handValue(playerHand); // stores played hand value as an int. Used in ace adjustment
int dealerUpcardRank = dealerHand[0].rank; // stores rank of the dealers visible card as an int (used for bool)
bool dealerStrong = dealerUpcardRank >= 7 || dealerUpcardRank == 1; // Dealers hand is strong if the upcard is an ace or greater than 6
bool dealerFair = (dealerUpcardRank <= 6 && dealerUpcardRank > 3); // Dealers hand is fair if the upcard is greater than 3 or less than 7
bool dealerWeak = dealerUpcardRank <= 3 && dealerUpcardRank > 1; // Dealers hand is poor of the upcard is 2 or 3
int aceCount = 0; // tracks how many aces are in the hand
for(int i = 0; i < playerHand.size(); i++) // loops through every card in the hand
{
if (playerHand[i].rank == 1) aceCount++; // counts aces by checking rank
}
// A softhand has specific strategy for the player. They should keep hitting until at least a total of 18.
bool softHand = aceCount > 0;
if(softHand)
{
if (playerHandValue < 18)
{
cout << "You should hit" << '\n' << "You have a soft hand (one or more aces), so taking another card is safe up until a total 18." << '\n';
}
else
{
cout << "You should stand" << '\n' << "You have a soft hand (one or more aces), and a hand with a value equal to or greater than 18. Standing is the best play." << '\n';
}
}
// If there is no softhand, it is a hardhand. This depends on the value in the dealers upcard.
else
{
if (dealerStrong) // If the dealer has a strong upcard-
{
if (playerHandValue < 17) // -and your card is less than 17.
{
cout << "You should hit." << '\n' << "The dealer shows a strong card. Since your total is less than 17, its likely you will lose." << '\n';
}
else // -and your card is greater than 17.
{
cout << "You should stand." << '\n' << "The dealer shows a strong card, and your hand is above 16. Hitting above 16 risks busting." << '\n';
}
}
else if (dealerWeak) // If the dealer has a weak upcard-
{
if (playerHandValue >= 12) // -and your total is greater or equal to 12.
{
cout << "You should stand." << '\n' << "The dealer shows a weak card, and your hand is fair. By standing you let the dealer risk busting." << '\n';
}
else // -and your total is less than 12.
{
cout << "You should hit." << '\n' << "The dealer shows a weak card. You should draw because your hand is too low to stay." << '\n';
}
}
else if (dealerFair) // If the dealer has a fair upcard-
{
if (playerHandValue >= 13) // -and your total is greater or equal to 13.
{
cout << "You should stand." << '\n' << "The dealer shows a fair card. Your total is 13 or higher. In this situation you should usually hold." << '\n';
}
else // -and your total is less than 13.
{
cout << "You should hit." << '\n' << "The dealer shows a fair card. You should draw because your hand is too low to stay." << '\n';
}
}
}
}
// Prints a hand showing each cards name
void printHand(const vector<Card>& hand)
{
for(int i = 0; i < hand.size(); i++) // loops through every card in the hand
{
cout << hand[i].name << " "; // prints cards name with a space
}
}
// Player's turn to hit or stand.
void playerTurn(vector<Card>& deck, vector<Card>& handPlayer, vector<Card>& handDealer)
{
const int WIN_CONDITION = 21; // target total in blackjack
char choice; // will store h for hit or s for stand
cout << '\n' << "Deal To Player" << '\n' << "---------------" << '\n';
giveAdvice(handPlayer, handDealer); // provide strategic advice
cout << "Enter h to hit or s to stand: "; // prompt for action
cin >> choice; // read input
choice = choiceValidation(choice); // ensure valid input
while(choice == 'h' || choice == 'H') // loop while player wants to hit
{
deal(deck, handPlayer); // give player another card
cout << "Player Drew: "; // announce new hand
printHand(handPlayer); // show all cards
cout << '\n'; // newline after hand
if(winCheck(handPlayer, handDealer, WIN_CONDITION)) return; // check for bust or 21
giveAdvice(handPlayer, handDealer); // provide advice again
cout << "Enter h to hit or s to stand: "; // prompt again
cin >> choice; // read input
choice = choiceValidation(choice); // validate input
}
}
// Dealer's turn to hit or stand.
void dealerTurn(vector<Card>& deck, vector<Card>& handPlayer, vector<Card>& handDealer)
{
const int WIN_CONDITION = 21; // target total in blackjack
const int DEALER_STAND = 17; // dealer must stand on 17 or higher
cout << '\n' << "Deal To Dealer" << '\n' << "---------------" << '\n';
cout << "Dealer Drew: "; // announce dealer's hand
printHand(handDealer); // show all dealer cards
cout << '\n'; // newline after hand
while(handValue(handDealer) < DEALER_STAND) // dealer must hit below 17
{
deal(deck, handDealer); // deal another card
cout << "Dealer Drew: "; // announce new hand
printHand(handDealer); // show all cards
cout << '\n'; // newline after hand
}
if(winCheck(handPlayer, handDealer, WIN_CONDITION)) return; // check for dealer bust or 21
}
// Compares player and dealer hands and announces the winner.
void announceWinner(const vector<Card>& handPlayer, const vector<Card>& handDealer)
{
int playerValue = handValue(handPlayer); // get player's total
int dealerValue = handValue(handDealer); // get dealer's total
if(playerValue > dealerValue) // player wins with higher total
{
cout << '\n' << "You win! Your hand value is " << playerValue << " and the dealer's is " << dealerValue << '\n';
}
else if(playerValue < dealerValue) // dealer wins with higher total
{
cout << '\n' << "You lose! Your hand value is " << playerValue << " and the dealer's is " << dealerValue << '\n';
}
else // totals are equal
{
cout << '\n' << "Push! Both you and the dealer have " << playerValue << '\n';
}
}
// Function used to return a value used for score tracking.
int announceWinnerScore(const vector<Card>& handPlayer, const vector<Card>& handDealer)
{
int playerValue = handValue(handPlayer); // get player's total
int dealerValue = handValue(handDealer); // get dealer's total
if(playerValue > dealerValue) // player wins
{
return 1; // positive for player win
}
else if(playerValue < dealerValue) // dealer wins
{
return -1; // negative for dealer win
}
else // push
{
return 0; // zero for tie
}
}
// Function to play a single game of Blackjack
void singleBlackJackGame(vector<Card>& deck, int& wins, int& losses, int& ties, int& gameNumber)
{
const int WIN_CONDITION = 21; // target total in blackjack
vector<Card> handPlayer; // player's hand starts empty
vector<Card> handDealer; // dealer's hand starts empty
int score = 0; // will hold result of this game
gameNumber++; // increment game count
firstCard(deck, handPlayer, handDealer); // deal first cards
secondCard(deck, handPlayer, handDealer); // deal second cards
if(winCheck(handPlayer, handDealer, WIN_CONDITION)) // check for natural blackjack
{
score = scoreTracker(handPlayer, handDealer, WIN_CONDITION); // get score
}
else
{
playerTurn(deck, handPlayer, handDealer); // player's turn
if(!winCheck(handPlayer, handDealer, WIN_CONDITION)) // if game continues
{
dealerTurn(deck, handPlayer, handDealer); // dealer's turn
if(!winCheck(handPlayer, handDealer, WIN_CONDITION)) // if still no winner
{
announceWinner(handPlayer, handDealer); // compare hands
score = announceWinnerScore(handPlayer, handDealer); // get score
}
else score = scoreTracker(handPlayer, handDealer, WIN_CONDITION); // dealer phase ended game
}
else score = scoreTracker(handPlayer, handDealer, WIN_CONDITION); // player phase ended game
}
if(score == 1) wins++; // increment wins
else if(score == -1) losses++; // increment losses
else ties++; // increment ties
}
// Main function to play Blackjack.
void playBlackJackGame()
{
srand(time(0)); // seed random number generator
int wins = 0; // track player wins
int losses = 0; // track player losses
int ties = 0; // track ties
int gameNumber = 0; // track total games
char choicePlayBlackjack = 'y'; // start with yes to play
cout << "BLACKJACK" << '\n' << "----------" << '\n';
cout << "Do you want to play a hand of blackjack (y to play)? "; // initial prompt
cin >> choicePlayBlackjack; // read choice
choicePlayBlackjack = choicePlayBlackJackValidation(choicePlayBlackjack); // validate
vector<Card> deck = getNewDeck(); // create new deck
cout << '\n' << "Unshuffled Deck:" << '\n'; // announce unshuffled
printDeck(deck); // show ordered deck
shuffleDeck(deck); // shuffle cards
cout << '\n' << "Shuffled Deck:" << '\n'; // announce shuffled
printDeck(deck); // show shuffled deck
while(choicePlayBlackjack == 'y' || choicePlayBlackjack == 'Y') // loop while player wants to play
{
singleBlackJackGame(deck, wins, losses, ties, gameNumber); // play one game
cout << "-----------------------------" << '\n'; // separator
cout << "Do you want to play another hand (y to play)? "; // prompt again
cin >> choicePlayBlackjack; // read choice
choicePlayBlackjack = choicePlayBlackJackValidation(choicePlayBlackjack); // validate
}
cout << '\n' << "You played " << gameNumber << " games." << '\n'; // total games
cout << "You won " << wins << " games." << '\n'; // total wins
cout << "You lost " << losses << " games." << '\n'; // total losses
cout << "You tied " << ties << " games." << '\n' << '\n'; // total ties
}
void playBlackJackGame()
{
srand((unsigned int) time(nullptr)); // sets seed for random number generation
vector<Card> deck = getNewDeck(); // generates a fresh deck of cards in order
cout << "Unshuffled Deck:" << '\n'; // text
printDeck(deck); // prints deck of cards in order
cout << '\n' << '\n' << "Shuffled Deck:" << '\n'; // spacing and text
shuffleDeck(deck); // shuffles deck
printDeck(deck); // prints now shuffled deck
cout << '\n';
playCasinoGame(deck); // starts blackjack session loop
}Mayan Number Game
// Libraries included
using namespace std;
// Ensures that the integer limit for guessing game inputted by user is correct time. Runs loop if until accepted value is entered.
int validateLimitInput(int upperLimit)
{
while(cin.fail()) // Loop to check type failure
{
cin.clear(); // resets error state
cin.ignore(10000, '\n'); // clears 10,000 characters or until a new line is found
cout << "Invalid Input. Enter another number, or less than 10 to exit: ";
cin >> upperLimit;
}
return upperLimit; // if loop is not triggered, returns int
}
// Returns a, b, c from user entered guess (case-insensitive). Re-prompts until valid.
char validateGuessInput(string guess)
{
while(true) // loop runs infinitely
{
if((guess.size() == 1) && //if statement ensures that size of string is one and is of allowed values
(guess[0] == 'a' || guess[0] == 'A' ||
guess[0] =='b' || guess[0] == 'B' ||
guess[0] == 'c' || guess[0] == 'C'))
{
return guess[0]; // if true returns the accepted letter as a char
}
// When the if statement is not satisfied, input validation occurs and user is re-prompted
cin.clear();
cin.ignore(10000, '\n');
cout << "Invalid Input. Please enter either a, b, or c ";
cin >> guess;
}
}
// Prints the Mayan base-20 digit extracted from a position: dots for 1-4, bars for 5s, "00" for zero.
void printMayanDigit(int value)
{
// Constants for consistent form with Mayan Character symbols
const string MAYAN_ZERO = "00"; // lack of specialized zero symbol. This string is used instead
const char* MAYAN_ONE = "o"; // dot is one
const char* MAYAN_FIVE = "\u2580\u2580\u2580\u2580\u2580\u2580\u2580"; // bar is five
if (value == 0) cout << MAYAN_ZERO << endl; // Special case for zero
else //Regular case)
{
const int DOTS_PER_BAR = 5; // In mayan number system, once 5 is reached, dots are swapped with a bar
int bars = value / DOTS_PER_BAR; // Integer division to find amount of bars
int dots = value % DOTS_PER_BAR; // Modulus to find the amount of dots
for(int i = 0;i < dots;i++) cout << MAYAN_ONE << " "; // Prints amount of dots
if(dots > 0) cout << endl; // newline once desired amount of dots is reached
for(int i = 0; i < bars; i++) cout << MAYAN_FIVE << endl; // Prints amount of bars
}
}
// Decomposes integer into base-20 digits, prints from most-significant to least with separators.
void printMayanNumber(int number)
{
const string PAGE_BREAK = "--------"; // Page break displays seperation of Mayan numbres decomposed into powers of 20
int digits[10]; // stores mayan digit for each position
int count = 0; // tracks how many positions (base-20 digits) there are in the number
if(number == 0) // Special case for when the number entered is zero. Not useful for game but useful for bulletproof print function
{
digits[0] = 0;
count = 1;
}
else
{
// Loop that uses integer division to store a digit in each position of the array.
while(number > 0 && count < 10) // Ends when number is empty, or size of the array is exceeded
{
digits[count++] = number % 20;
number /= 20;
}
}
// Loop to print the Mayan digit for each position in the array
for(int i = (count - 1); i >= 0; i--) // Loop ends when array is at its first slot. Starts from highest slot
{
printMayanDigit(digits[i]); //Calls digit print function
if(i > 0) cout << PAGE_BREAK << endl; // Creates page-break to show seperation between powers of 20
}
}
// Picks a random integer between minimum range and user inputted m.
int getRandomNumber(int min, int max)
{
return rand() % (max - min + 1) + min; // rand generates a random integer -> by modulus division it reduces the integer to value in the specified range -> min is then added so the smallest value is min -> Value is returned
}
// Mayan number game that takes the user's inputted limit and plays a guessing game for a randomly generated number within upperLimit (lower limit of 4)
void mayanNumberGame(int upperLimit)
{
const int EXIT_THRESHOLD = 10; // value used to exit program if input is under the limit
do // do-while loop so the game runs at least once through, but can run infinitely.
{
// if statement to check is limit inputted is within exit threshold to close program
if(upperLimit < EXIT_THRESHOLD)
{
cout << endl;
return;
}
const int RANDOM_LOWER_LIMIT = 4; // the lower limit of what a one of the answers in the game can be
const int NUM_OPTIONS = 3; // the number of options presented to the user in the game
int correctNumber = getRandomNumber(RANDOM_LOWER_LIMIT, upperLimit); // randomly generated correct answer, inclusively between lower limit and user specified upper limit
// range for how far the incorrect values can be from the correct answer
int lowerRange = correctNumber / 2;
int upperRange = correctNumber + correctNumber / 2;
// Generation of incorrect answers
int wrong1, wrong2;
wrong1 = getRandomNumber(lowerRange, upperRange);
while(wrong1 == correctNumber) wrong1 = getRandomNumber(lowerRange, upperRange); //regenerates first wrong answer if equal to correct
wrong2 = getRandomNumber(lowerRange, upperRange);
while(wrong2 == correctNumber || wrong2 == wrong1) wrong2 = getRandomNumber(lowerRange, upperRange); //regenerates second wrong answer if equal to either correct or first wrong answer
int options[NUM_OPTIONS] = {correctNumber, wrong1, wrong2}; // stores all answers in an array
// Randomly shuffles the array of answers so game 'doesn't have same answer each time
for(int i = 0; i < NUM_OPTIONS; i++)
{
int randomIndex = rand() % NUM_OPTIONS; // random value corresponding to size of array
int temporaryHolder = options[i];
options[i] = options[randomIndex];
options[randomIndex] = temporaryHolder;
}
// loop to find the index associated with the correct number post-shuffling
int correctIndex;
for(int i = 0; i < NUM_OPTIONS; i++)
{
if(options[i] == correctNumber)
correctIndex = i;
}
// Prompts user to guess which mayan number corresponds to the correct number and prints options
cout << "Which of these Mayan numbers is equal to " << correctNumber << "?" << endl;
cout << "a)" << endl;
printMayanNumber(options[0]);
cout << endl << endl;
cout << "b)" << endl;
printMayanNumber(options[1]);
cout << endl << endl;
cout << "c)" << endl;
printMayanNumber(options[2]);
cout << endl << endl;
// Gievs user options of which to guess
cout << "Enter a, b or c: ";
string guess; // string is used to store guess to account for if they enter more than one character
cin >> guess;
char validGuess = validateGuessInput(guess); // stores validated single-character guess as a char
int guessIndex; // guess index to correspond the character input with the mayan number
if (validGuess == 'a' || validGuess == 'A') guessIndex = 0;
else if (validGuess == 'b' || validGuess == 'B') guessIndex = 1;
else if (validGuess == 'c' || validGuess == 'C') guessIndex = 2;
// Prints if the user guesses correctly
if (guessIndex == correctIndex)
{
cout << "CORRECT! The Mayan representation of " << correctNumber << " is" << endl;
printMayanNumber(correctNumber);
}
// Prints if the user's guess is incorrect
else
{
cout << "INCORRECT! The Mayan representation of " << correctNumber << " is" << endl;
printMayanNumber(correctNumber);
}
// Asks the user if they want to play again or close the application. Validates for correct input
cout << "Enter another number, or less than 10 to exit: ";
cin >> upperLimit;
upperLimit = validateLimitInput(upperLimit);
} while(upperLimit >= EXIT_THRESHOLD); //Loop checks condition and runs again if true
}
void maya_numbers()
{
srand(time(0)); // sets seed for random number generation
const int JOHN_EDGAR_REQUESTED_NUMBER = 5212; // rubrik requested number to be converted and printed
cout << "Maya representation of 5,212:" << endl;
printMayanNumber(JOHN_EDGAR_REQUESTED_NUMBER);
cout << endl << endl;
// Game formatting and initial prompt for user input to begin game
const char* GAME_BAR = "\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580\u2580";
int upperLimit;
cout << "MAYAN NUMBER GAME" << endl;
cout << GAME_BAR << endl << endl;
cout << "Welcome to the Mayan Number Game!" << endl << endl;
cout << "Enter a number greater than 10. The game will choose a number" << endl;
cout << "less than or equal to what you entered. You will then have" << endl;
cout << "to match the decimal number to its Mayan equivalent." << endl;
cout << "Or, enter a number less than 10 to exit: ";
cin >> upperLimit;
// Validation of user input and running the game
upperLimit = validateLimitInput(upperLimit);
mayanNumberGame(upperLimit);
cout << '\n';
}Convert Integer Numbers to Strings
using namespace std;
// Inclusion of all the sub-functions used by intToString, as well as eachother (e.g. intToThousands uses intToHundreds)
string intToOnes(int number);
string intToTeens(int number);
string intToTens(int number);
string intToHundreds(int number);
string intToThousands(int number);
// FUNCTION 1L CONVERTS INTEGERS TO STRING AND RETURNS IT (not print)
// process broken down into sub functions
// If intToString is asked for a number outside of range (0 : 99,999) it returns the string "error"
string intToString(int number)
{
// Case when integer is zero
if(number == 0)
{
return("zero");
}
// If the integer is range zero - nine
else if(number > 0 && number < 10)
{
return(intToOnes(number));
}
// If the integer is in range 10 - 19
else if(number > 9 && number < 20)
{
return(intToTeens(number));
}
// If the integer is in range 20 - 99
else if(number > 19 && number < 100)
{
return(intToTens(number));
}
// If the integer is in range 100 - 999
else if(number > 99 && number <= 999)
{
return(intToHundreds(number));
}
// If the integer is in range 1000 - 99,999
else if(number >= 1000 && number <= 99999)
{
return(intToThousands(number));
}
// If the number is outside of the range
else
{
return("error");
}
}
// FUNCTION 2: PRINTING STRIGNS OF INTEGERS
//These three integers are important as it will print the number between the start and end on a specified interval
void printIntStrings(int start, int end, int interval)
{
// Ensuring program doesnt go on infinitely
if (interval <= 0)
{
return;
}
// Special case where start and end are equal, so only one output
else if(start == end)
{
cout << intToString(start) << endl;
}
// Special case for a descending interval
else if(end < start)
{
for(int x = start; x >= end; x = x - interval)
{
cout << intToString(x) << endl;
}
}
// Regular case
else
{
for(int x = start; x <= end; x = x + interval)
{
cout << intToString(x) << endl;
}
}
}
// MAIN FUNCTION I USED, NOW COMMENTED OUT
void numbers()
{
int start = 0, end = 0, interval = 0;
cout << "Enter a number to start: ";
cin >> start;
cout << "Enter a number to end: ";
cin >> end;
cout << "Enter an interval to go between them: ";
cin >> interval;
printIntStrings(start, end, interval);
cout << '\n';
}
// Sub-function for the ones
string intToOnes(int number)
{
// Intializes variables
string ones;
// Decides which case of integer input
switch(number)
{
case 1: ones = "one";
break;
case 2: ones = "two";
break;
case 3: ones = "three";
break;
case 4: ones = "four";
break;
case 5: ones = "five";
break;
case 6: ones = "six";
break;
case 7: ones = "seven";
break;
case 8: ones = "eight";
break;
case 9: ones = "nine";
break;
}
return(ones); // Outputs back to user
}
// Sub-function for the teens
string intToTeens(int number)
{
// Initializes variables
string teens;
// Decides which case depending on number
switch(number)
{
case 10: teens = "ten";
break;
case 11: teens = "eleven";
break;
case 12: teens = "twelve";
break;
case 13: teens = "thirteen";
break;
case 14: teens = "fourteen";
break;
case 15: teens = "fifteen";
break;
case 16: teens = "sixteen";
break;
case 17: teens = "seventeen";
break;
case 18: teens = "eighteen";
break;
case 19: teens = "nineteen";
break;
}
return(teens);
}
// Sub-function for the tens
string intToTens(int number)
{
// Initializes variables
int tensDigit = number / 10;
int tensRemainder = number % 10;
string tens;
// Deciding the amount in the tens column
switch(tensDigit)
{
case 2: tens = "twenty";
break;
case 3: tens = "thirty";
break;
case 4: tens = "forty";
break;
case 5: tens = "fifty";
break;
case 6: tens = "sixty";
break;
case 7: tens = "seventy";
break;
case 8: tens = "eighty";
break;
case 9: tens = "ninety";
break;
}
// CATEGORIZING OUTPUT
// Special case where there is no number in the ones column (e.g. 20, 40)
if(tensRemainder == 0)
{
return(tens);
}
// Normal case where there is a number in the ones column (e.g. 98, 45, 23)
else
{
return(tens+"-"+intToOnes(tensRemainder));
}
}
// Sub-function for the hundreds
string intToHundreds(int number)
{
// Initializes varaibles used for computations & output
string hundreds;
int hundredsDigit = number / 100;
int hundredsRemainder = number % 100;
// Decides how many hundreds
switch(hundredsDigit)
{
case 1: hundreds = "one hundred";
break;
case 2: hundreds = "two hundred";
break;
case 3: hundreds = "three hundred";
break;
case 4: hundreds = "four hundred";
break;
case 5: hundreds = "five hundred";
break;
case 6: hundreds = "six hundred";
break;
case 7: hundreds = "seven hundred";
break;
case 8: hundreds = "eight hundred";
break;
case 9: hundreds = "nine hundred";
break;
}
// CATEGORIZING OUTPUT
// Special case where nothing is in the tens/teens or ones column (100, 200, 300)
if(hundredsRemainder == 0)
{
return(hundreds);
}
// Special case for a the teens being occupied (e.g. 112, 118)
else if(hundredsRemainder > 9 && hundredsRemainder < 20)
{
return(hundreds + " and " + intToTeens(hundredsRemainder));
}
// Special case for the tens being occupied but the ones being empty (e.g. 220, 540)
else if((hundredsRemainder) % 10 == 0)
{
return(hundreds + " and " + intToTens(hundredsRemainder));
}
// Special case for the tens column being empty (e.g. 205, 209)
else if((hundredsRemainder) / 10 == 0)
{
return(hundreds + " and " + intToOnes(hundredsRemainder));
}
// The normal case (e.g. 437)
else
{
return(hundreds + " and " + intToTens(hundredsRemainder % 100));
}
}
// Sub-function for the thousands
string intToThousands(int number)
{
// Initializes variables used for calculation of the thousands
string thousands;
int thousandsDigit = number / 1000;
int thousandsRemainder = number % 1000;
// DECIDING HOW MANY THOUSANDS
// Categorizing how many thousands if its from 1-9 (ones)
if(thousandsDigit >= 1 && thousandsDigit <= 9)
{
thousands = intToOnes(thousandsDigit) + " thousand"; // Uses intToOnes
}
// Categorizing how many thousands if its from 10-19 (teens)
else if(thousandsDigit >= 10 && thousandsDigit <= 19)
{
thousands = intToTeens(thousandsDigit) + " thousand"; // Uses intToTeens
}
// Categorizing how many thousands if its from 20-99 (tens, as program cannot do above 99 thousand)
else if(thousandsDigit >= 20)
{
thousands = intToTens(thousandsDigit) + " thousand"; // Uses intToTens
}
// CATEGORIZING OUTPUT
// Special case where nothing is in other columns
if(thousandsRemainder == 0)
{
return(thousands);
}
// General case for the remainder being above 100 (e.g. 100-999). From here the intToHundreds will complete the output
else if(thousandsRemainder >= 100)
{
return(thousands + ", " + intToHundreds(thousandsRemainder));
}
// If nothing in hundreds, but some something in the tens (e.g. 20-99). From here intToTens completes the output
else if(thousandsRemainder <= 99 && thousandsRemainder >= 20)
{
return(thousands + " and " + intToTens(thousandsRemainder));
}
// If nothing in hundreds, but some something in the teens (e.g. 10-19). From here intToTeens completes the output
else if(thousandsRemainder < 20 && thousandsRemainder > 9)
{
return(thousands + " and " + intToTeens(thousandsRemainder));
}
// If there is nothing in the hundreds, tens/teens but there is remainder in the ones (1-9) (e.g. 2009, 4001)
else
{
return(thousands + " and " + intToOnes(thousandsRemainder));
}
}Factors of Numbers
// Program to prints the factors, and related information, of each number between, and including, two integers entered by the user
using namespace std;
void factors() // Begins the program
{
const int colwidth = 4; // Standardizes column width
// Setting up the bounds for input
const int FLOOR = 1; //minimum input
const int CEILING = 999; // maximum input
// Setting up values for user input
int firstvalue, secondvalue = 1; // user inputs
int start, end = 1; //starting and ending prime
// Prompt user to enter 2 numbers to be used for calculations
cout << "Enter a value between 1 and 999: ";
cin >> firstvalue;
while (firstvalue < FLOOR || firstvalue > CEILING) // Ensures its within the given range
{
cout << "The value must be greater than 0 and less than 1000: ";
cin >> firstvalue;
}
// Second prompt for user to input.
cout << "Enter a second value between 1 and 999: ";
cin >> secondvalue;
while (secondvalue < FLOOR || secondvalue > CEILING) // Ensures its within the given range
{
cout << "The value must be greater than 0 and less than 1000: ";
cin >> secondvalue;
}
cout << endl; //extra line for spacing
// Ensures that the start value is smaller then the end value
if (firstvalue > secondvalue)
{
start = secondvalue;
end = firstvalue;
}
else
{
start = firstvalue;
end = secondvalue;
}
// Begin Computation of factors section
for (int x = start; x <= end; x++) // Runs body for every integer between start and end, increasing by 1 each iteration
{
// Variable to keep track of how many factors for each iteration
int factorcount = 0; // Must be inside loop so it resets for each iteration
cout << setw(colwidth) << x; // Prints the number for which the factors are being identified
for (int y = 1; y <= x; y++) // Starts with a factor of 1, ends when factor is itself, trying every integer inbetween
{
if ((x % y) == 0) // if the remainder is zero (e.g. 2 / 4), a factor is identified and the value is printed
{
cout << setw(colwidth) << y; // Prints the identified factor of the number
factorcount++; // increases the factor count since one has now been identified
}
}
cout << setw(colwidth) << "(" << factorcount << ")"; //Prints factor count in line
// Additional output if a special case (prime or perfect square). Utilizes nested if's
if (factorcount == 2 || (factorcount%2) == 1) // If SpecialCase1 OR SpecialCase2
{
// Special Case 1: Prime Number
// A Prime number only has 2 factors: 1 and itself.
if (factorcount == 2)
{
cout << setw(colwidth) << " **prime**" << endl;
}
// Special Case 2: Perfect Square
// A perfect square is the only number with an odd number of factors since one of the factors is a repeated number.
if ((factorcount%2) == 1) //Integer divides by 2, is a resulting 1 then it is a perfect square
{
cout << setw(colwidth) << " **perfect square**" << endl;
}
}
// Standard output if not a Special Case
else
{
cout << endl;
}
}
cout << endl; // Spacing
// Now we are going to sum up the digits in start and end
// First we sum the digits, and product for the 'start' variable
// Creates a temporary value that will be used to store and alter the inputted value of start. Also creates associated values for sum and product
int temp_start = start;
int sum_start = 0;
int product_start = 1;
// As long as temp_start still has values in it we run this loop. It stores the value in the 1s column, then shifts the number down by a factor of 10 until all digits are stored.
while(temp_start > 0)
{
int digit_start = temp_start % 10; // create a integer in the loop that uses remainder integer division to keep only the digit in the 1s column. For example if start was 926, digit will be 6.
sum_start += digit_start; // Adds this value to the sum
product_start *= digit_start; // Multiplies this value to the product
temp_start /= 10; // Removes the last column so process moves onto the next digit
}
// Next we sum the digits, and product for the 'end' variable. This follows the exact same process as it did for the start variables.
int temp_end = end;
int sum_end = 0;
int product_end = 1;
while(temp_end > 0)
{
int digit_end = temp_end % 10;
sum_end += digit_end;
product_end *= digit_end;
temp_end /= 10;
}
// Now we print the sum of our start and end variables, with an optional text if the number is interesting
cout << setw(colwidth) << start << ": sum of digits = " << sum_start;
if (start == (sum_start + product_start)) // A number is interesting if the sum and product when added together is equal to the number the user inputted
{
cout << setw(colwidth) << " --interesting--" << endl;
}
else
{
cout << endl;
}
cout << setw(colwidth) << end << ": sum of digits = " << sum_end;
if (end == (sum_end + product_end))
{
cout << setw(colwidth) << " --interesting--" << endl;
}
else
{
cout << endl;
}
cout << '\n';
}Distance Converter & Circle Area
using namespace std;
void circleRadius()
{
// Part 1: Circle Area
// Establishes variables and constants needed for the computation
double radius = 0;
double area = 0;
const double PI = 3.141592653589793;
// Title Block
cout << "CIRCLE AREA" << endl;
cout << "-----------" << endl;
//Prompts the user to enter a radius and stores the value for computation
cout << "Enter radius: ";
cin >> radius;
// Computes corresponding circles area and prints the radius and area back to the user.
area = PI * radius * radius; // computation
cout << endl; // line for spacing
cout<< "a circle with radius = " << radius << " has an area = " << area << endl; // print to user
cout << endl;
}
void distance()
{
// Part 2: Distance
// Defines constants that will be used in distance conversions
const double MetreToInches = 39.37007874; // Converts Metres to Inches
const int InchesToFeet = 12; // Converts Inches to Feet
const double MetretoFurlong = 0.00497096; // Converts Metres to Furlongs
const double SpeedOfLight = 299792458; // Speed of Light in m/s
// Title Block
cout << "DISTANCE" << endl;
cout << "--------" << endl;
// Prompts the user to enter a distance and stores the value for computation
double distance = 0;
cout << "Enter distance in metres: ";
cin >> distance;
cout << endl;
// Conversions from M -> Inch, and Inch -> Feet
double TotalInches = distance * MetreToInches; // Variable for total feet from Metres
int feet = TotalInches / InchesToFeet; // Variable as an int of distance in feet
double inches = TotalInches - feet * InchesToFeet; // Magic number of inches in distance once integer of feet is subtracted
cout << distance << " metres = " << feet << "\' " << inches << "\"" << endl; // Relays computations back to user
// Conversions from M -> Furlongs
double furlong = distance * MetretoFurlong; // Variable that converts metres to furlongs
cout << distance << " metres = " << furlong << " furlongs" << endl; // Prints to user
// Conversions from M -> s at Speed of Light
double seconds = distance / SpeedOfLight; // since light is in m/s, m / (m/s) = s (seconds)
cout << "It takes " << seconds << "s for light to travel " << distance << "m in a vacuum" << endl; // Prints to user
}