C++ pull a card from deck - c++

I'm trying to create a program that will pull a card from a deck of 52 regular playing cards.
Suits: Heart, Spad, Diamond, Club.
Rank: A,2,3,4,5,6,7,8,9,10,J,Q,K.
This should be the output:
Let's pull a card!
This time we got AH
Wanna pull a card again?
y
This time we got 3J
Wanna pull a card again?
n
My output is:
Let's pull a card!
DKThis time we got 00
Wanna pull a card again?
n
This is my code:
#include <iostream>
#include <ctime>
using namespace std;
// Function Declaration
int rankCard(), suitCard();
int main()
{
srand(time(0));
char answer;
cout << "Let's pull a card!" << endl;
do {
cout << "This time we got " << rankCard() << suitCard() << endl;
cout << "Wanna pull a card again?" << endl;
cin >> answer;
} while ((answer == 'y') || (answer == 'Y'));
return 0;
}
int rankCard() {
int rank = (rand() % 13) + 1;
switch (rank) {
case 1: cout << "A";
break;
case 10: cout << "T";
break;
case 11: cout << "J";
break;
case 12: cout << "Q";
break;
case 13: cout << "K";
break;
default: cout << rank;
break;
}
return 0;
}
int suitCard() {
int suit = (rand() % 4) + 1;
switch (suit) {
case 1: cout << "H";
break;
case 2: cout << "D";
break;
case 3: cout << "C";
break;
case 4: cout << "S";
break;
}
return 0;
}
I can't figure out why the cards pulled (DK) are in that position and why I also get the 00. What am I doing wrong? Thanks

Your calls to rankCard() and suitCard() always return 0.
That 0 value is what's passed to cout in your main function.
The weird 'DK' is caused by the calls to cout inside rankCard and suitCard.
You could modify your functions to avoid the confusion:
#include <string>
std::string rankCard() {
int rank = (rand() % 13) + 1;
switch (rank) {
case 1: return "A";
case 10: return "T";
case 11: return "J";
case 12: return "Q";
case 13: return "K";
default: return std::to_string( rank );
}
return "";
}
std::string suitCard() {
int suit = (rand() % 4) + 1;
switch (suit) {
case 1: return "H";
case 2: return "D";
case 3: return "C";
case 4: return "S";
}
return "";
}

This line:
cout << "This time we got " << rankCard() << suitCard() << endl;
So those functions print the card, and then they return 0, so if you call them in cout, they will do their thing witch is printing the card and then print the return value witch is 0.
What you can do is to call them outside the cout, just do:
//...
cout << "This time we got ";
rankCard();
suitCard();
cout << endl;
cout << "Wanna pull a card again?" << endl;
//...
Personally I would refactor the functions to return the respective card char:
Live sample
const char rankCard() {
int rank = (rand() % 13) + 1;
switch (rank) {
case 1: return 'A';
case 10: return 'T';
case 11: return 'J';
case 12: return 'Q';
case 13: return 'K';
default: return rank + 48; // convert to decimal digit
}
}
const char suitCard() {
int suit = (rand() % 4) + 1;
switch (suit) {
case 1: return 'H';
case 2: return 'D';
case 3: return 'C';
case 4: return 'S';
default: return 0; //ASCII code for null character
}
}

Related

ASCII Strength Game will not calculate "Bot" word value

I'm making a game that tests the ASCII strength of a user versus a bot. (There is also a 2 player mode but that's working fine.) The full description is given at the top of my .cpp file. As a basic breakdown, the bot opens a txt file with 500 common four letter words and inserts them into a size 500 array. It then randomly generates a number to pick a random one, and then goes through the process of tovalue() to recieve its ASCII value, where in tovalue() runs through chartoint() four times, one for each character of the word. My issue is that the program calculates the ASCII value perfectly fine of the user generated word, but always returns 0 (0000) for the botword, no matter what the word.
I've tried a few iterations of the generateword() function including using a vector but always get the same resutls. I've done a lot of digging about this and haven't quite found any solutions, although I suspect that the chartoint() function could be better optimized, just not sure how to impliment any better solutions for this specific case. Also, don't think the problem is with chartoint() since it works fine for user input, but I'm pretty sure the problem is with generateword(). Suggestions for making chartoint() would be helpful, but its not my main priority right now since I just need the program to 100% work first. Also, I've confirmed that all of the words in my .txt file are all caps and only four characters per line.
// Write the code for a game called “ASCII Strength” of a four-letter word selected by Player 1
// followed by a four-letter word selected by Player 2. The result would be the sum
//of the ASCII value of each of the letters of the selected words and whoever has higher sum (called ASCII strength) wins.
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;;
int chartoint(char a) {
switch (a) {
case 'A':
return 1;
break;
case 'B':
return 2;
break;
case 'C':
return 3;
break;
case 'D':
return 4;
break;
case 'E':
return 5;
break;
case 'F':
return 6;
break;
case 'G':
return 7;
break;
case 'H':
return 8;
break;
case 'I':
return 9;
break;
case 'J':
return 10;
break;
case 'K':
return 11;
break;
case 'L':
return 12;
break;
case 'M':
return 13;
break;
case 'N':
return 14;
break;
case 'O':
return 15;
break;
case 'P':
return 16;
break;
case 'Q':
return 17;
break;
case 'R':
return 18;
break;
case 'S':
return 19;
break;
case 'T':
return 20;
break;
case 'U':
return 21;
break;
case 'V':
return 22;
break;
case 'W':
return 23;
break;
case 'X':
return 24;
break;
case 'Y':
return 25;
break;
case 'Z':
return 26;
break;
}
return 0;
}
int tovalue(string input) {
int first = chartoint(input[0]);
int second = chartoint(input[1]);
int third = chartoint(input[2]);
int fourth = chartoint(input[3]);
cout << first << second << third << fourth; // EXISTS TO TEST CALCULATION
int value = first + second + third + fourth;
return value;
}
string generateword() {
string arr[500];
ifstream file("words.txt");
if (file.is_open())
{
for (int i = 0; i < 500; i++) {
string temp;
getline(file, temp);
arr[i] = temp;
}
file.close();
}
else
{
cout << "Error: Unable to open file.";
exit(0);
}
srand(time(0));
int random_index = rand() % 500;
string random_word = arr[random_index];
return random_word;
}
int main()
{
cout << "Welcome to ASCII strength, a game where the strongest word wins!";
cout << "\nTo play, you must enter a four letter word. The program will calculate the 'ASCII strength' of your word and compare it to your opponent.";
cout << "\nWhoever has the higher sum will win!";
char another;
another = 'y';
while (another == 'y' || another == 'Y') {
cout << "\nWould you like to play against a friend, or against a bot? (F/B)";
char mode;
cin >> mode;
if (mode == 'F' || mode == 'f') {
cout << "\nPlayer 1, please input your four letter word in all caps: ";
string answer1;
cin >> answer1;
int value1;
value1 = tovalue(answer1);
cout << "\nPlayer 2, please input your four letter word in all caps: ";
string answer2;
cin >> answer2;
int value2;
value2 = tovalue(answer2);
if (value1 > value2) {
cout << "\nPlayer 1 wins!";
}
else if (value2 > value1) {
cout << "\nPlayer 2 wins!";
}
else if (value1 == value2) {
cout << "\nTie!";
}
}
else if (mode == 'B' || mode == 'b') {
cout << "\nPlease input your four letter word in all caps: ";
string answer;
cin >> answer;
int valueanswer;
valueanswer = tovalue(answer);
string botword;
botword = generateword();
cout << "\nThe bot generates a random word based on a list of popular four letter words.";
cout << "\nThe bot has generated this word: " << botword;
int valuebot;
valuebot = tovalue("botword");
cout << valueanswer << " " << valuebot; // THIS EXISTS PURELY TO TEST WHETHER THE VALUES ARE PROPERLY CALCULATING
if (valueanswer > valuebot) {
cout << "\nYou win!";
}
else if (valuebot > valueanswer) {
cout << "\nThe bot wins!";
}
else if (valueanswer == valuebot) {
cout << "\nTie!";
}
}
cout << "\nWould you like to start a new game? (y/n)";
cin >> another;
}
}
Your problem is this line:
valuebot = tovalue("botword");
Since all characters in "botword" are lowercase, you get all 0 score. You probably meant to write
valuebot = tovalue(botword);

Why do I keep getting this error: exception Unhandled : Unhandled exception thrown: read access violation. this was 0x4

I am currently working on the BlackJack project, but there is an error showing "exception Unhandled: Unhandled exception thrown: read access violation. this was 0x4.". I am not quite sure which part I did wrong, and the program sometimes runs normally sometimes shows that exception. In draw_card function, it returns a value of a random number. For example: if we get 13, the value will be 10. It also returns the name of the card and the type of the card such as 13 corresponds to king.
int main()
{
srand(time(0));
unsigned bet;
int player = 0 , dealer = 0;
string card , type;
cout << "You have $100. Enter bet: ";
cin >> bet;
cout << "Your cards are:" << endl;
player += draw_card(card, type, player);
cout << " "+card + " of " + type << endl;
player += draw_card(card, type, player);
cout << " " + card + " of " + type << endl << endl << endl;
}
int draw_card(string& card, string& type, int drawer_points) {
int randomNumber; //between 1 and 13
int suite; //between 1 and 4 to determine the suite of the card.
randomNumber = rand() % 13 + 1;
suite = rand() % 4 + 1;
card = getRank(randomNumber);
type = getSuit(suite);
if (randomNumber == 13 || randomNumber == 12 || randomNumber == 11) {
return 10;
}else if (randomNumber == 1) {
int ace1 = 21 - (drawer_points + 1);
int ace2 = 21 - (drawer_points + 11);
return ace1 < ace2 ? 1 : 11;
}
else
{
return randomNumber;
}
}
string getSuit(int suit) {
switch (suit)
{
case 0:
return "spades";
break;
case 1:
return "clubs";
break;
case 2:
return "diamonds";
break;
case 3:
return "hearts";
break;
default:
break;
}
}
string getRank(int rank) {
switch (rank)
{
case 13:
return "King";
break;
case 12:
return "Queen";
break;
case 11:
return "Jack";
break;
case 1:
return "Ace";
break;
case 2:
return "Two";
break;
case 3:
return "Three";
break;
case 4:
return "Four";
break;
case 5:
return "Five";
break;
case 6:
return "Six";
break;
case 7:
return "Seven";
break;
case 8:
return "Eight";
break;
case 9:
return "Nine";
break;
case 10:
return "Ten";
break;
default:
break;
}
You generate
suite = rand() % 4 + 1;
This is a random number between 1 and 4 inclusive.
You then call
getSuit(suite);
But getSuit only has switch branches for values between 0 and 3 inclusive:
switch (suit)
{
case 0:
return "spades";
break;
case 1:
return "clubs";
break;
case 2:
return "diamonds";
break;
case 3:
return "hearts";
break;
default:
break;
}
Not returning a value from a function that is declared to return a value is undefined behaviour.
A few functions like getSuit and getRank in your code don't return a value if only the default case of their switch statement is executed.
You can return an empty string in the default cases:
default:
return ""; // empty string
And in the call site, check to see if the returned value is empty using the empty function.
Another way is to use std::optional<T> like below:
std::optional<string> getSuit( const int suit )
{
switch (suit)
{
case 0:
return "spades";
case 1:
return "clubs";
case 2:
return "diamonds";
case 3:
return "hearts";
default:
return { }; // empty optional
}
}
And in the call site:
std::optinal<std::string> type { getSuit(suite) };
if ( type ) // if optional has value
{
// extract and use the value inside of optional
type.value( );
}
Keep in mind that if the optional does not have a value, using value() will throw. You can use value_or() instead which does not throw.

Guessing Game with functions c++

I am writing a guessing game program using functions for each thing, I keep getting errors saying function isn't set so when I try to call it, it isn't working. I can't figure out what I am doing wrong.
I know I have arguments for the functions that aren't being used but I cant seem to figure out where or how I should include those in the function themself.
I am fairly new to programming/c++ so please no negative comments I am just trying to get as much help as I can.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int getGuess(string prompt);
string getRank(int guessCount);
bool getPlayAgain(string prompt);
void playOneGame();
int main(){
srand(time(0));
int number = rand() % 100 + 1;
string prompt = getGuess();
do(
playOneGame();
)while(getPlayAgain())
return EXIT_SUCCESS;
}
int getGuess(string prompt){
int num;
int guessCount = 0;
prompt = cout << "Please enter a number between 1-100: ";
cin >> num;
if(num > 100){
cout << "Please enter a number between 1-100: " << endl;
}
if(num < 1){
cout << "Please enter a number between 1-100: " << endl;
}
if(num <= 100){
cout << "The number you guessed is: " << num << endl;
guessCount++;
}
}
string getRank(int guessCount){
switch(guessCount){
case 1:
case 2:
case 3: cout << "Lucky!" << endl;
break;
case 4:
case 5:
case 6: cout << "Awesome";
break;
case 7:
case 8:
case 9: cout << "Good";
break;
case 10:
case 11:
case 12: cout << "Meh";
break;
case 13:
case 14:
case 15: cout <<"Poor";
break;
default: cout << "Pathetic";
}
}
bool getPlayAgain(string prompt){
bool done = false;
int num1;
while(!done){
cout << "Enter 1 to play again or 2 to quit: ";
cin >> num1;
if(num1 == 2){
break;
}
else(
getGuess();
)
}
}
void playOneGame(){
getGuess();
getRank();
getPlayAgain();
}
No return statement in getguess() function but function signature is int return type.
Getguess() accepts prompt parameter as input but not used inside the function.

Error C2679: binary '+' : no operator found which takes a right-hand operand of type

First up, yes, this is homework that I'm struggling with, so help would be appreciated. We're making a calculator in C++ that is supposed to function differently on the + and - operators.
With '+' it is supposed to to add the two numbers together (i.e., 45 + 54 = 4554).
With '-' it is supposed to remove the first digit of the first element from the second element (i.e., 1217 - 1 = 27) We're supposed to do this by overloading the + and - operators, which I seem to be struggling with. Thanks in advance for the help!
class WhackyRPN
{
public:
int value;
int operator+ (WhackyRPN a[]);
int operator- (WhackyRPN s[]);
int getValue();
void setValue(int);
};
void WhackyRPN::setValue(int val){
value = val;
}
int WhackyRPN::getValue(){
return value;
}
int WhackyRPN::operator+ (WhackyRPN a[]){
string combinedNum = to_string(a[1].getValue()) + to_string(a[0].getValue());
int finalNum = stoi(combinedNum);
return finalNum;
}
int WhackyRPN::operator- (WhackyRPN s[]){
int minusNum;
string firstNum = to_string(s[0].getValue());
string secondNum = to_string(s[1].getValue());
string minusString = to_string(minusNum);
for (int i = 0; i < firstNum.length(); i++){
if (firstNum.at(0) != secondNum.at(i)){
minusString.at(i) += secondNum.at(i);
}
}
minusNum = stoi(minusString);
return minusNum;
}
int main()
{
WhackyRPN stackPos[4];
string indent = " ";
string userInput;
stackPos[0].setValue(0);
stackPos[1].setValue(0);
stackPos[2].setValue(0);
stackPos[3].setValue(0);
while (1){
system("cls");
cout << "---STACK---" << endl;
cout << indent << stackPos[3].getValue() << endl;
cout << indent << stackPos[2].getValue() << endl;
cout << indent << stackPos[1].getValue() << endl;
cout << indent << stackPos[0].getValue() << endl;
cout << "CMD: ";
cin >> userInput;
if (userInput == "exit" || userInput == "Exit" || userInput == "EXIT"){
exit(0);
}
switch (userInput[0]){
case 'q':
case 'Q':
exit(0);
case 'p':
case 'P':
stackPos[0] = stackPos[1];
stackPos[1] = stackPos[2];
stackPos[2] = stackPos[3];
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '0':
stackPos[3].setValue(stackPos[2].getValue());
stackPos[2].setValue(stackPos[1].getValue());
stackPos[1].setValue(stackPos[0].getValue());
stackPos[0].setValue(stoi(userInput));
break;
case '+': //combine pos[1] and pos[0];
int finalNum = stackPos[1] + stackPos[0];
stackPos[3].setValue(stackPos[2].getValue());
stackPos[2].setValue(stackPos[1].getValue());
stackPos[1].setValue(stackPos[0].getValue());
stackPos[0].setValue(finalNum);
break;
case '-': //remove pos[0].firstNum from pos[1]
int minusNum = stackPos[0] - stackPos[1];
stackPos[3].setValue(stackPos[2].getValue());
stackPos[2].setValue(stackPos[1].getValue());
stackPos[1].setValue(stackPos[0].getValue());
stackPos[0].setValue(minusNum);
break;
case '/': //divide pos[1] by pos[0]
if (stackPos[0].getValue() == 0){
cout << "Cannot divide by 0" << endl;
system("pause");
break;
}
int endQuotient = stackPos[1].getValue() / stackPos[0].getValue();
stackPos[3].setValue(stackPos[2].getValue());
stackPos[2].setValue(stackPos[1].getValue());
stackPos[1].setValue(stackPos[0].getValue());
stackPos[0].setValue(endQuotient);
break;
case '*': //multiply pos[1] by pos[0]
int endProduct = stackPos[1].getValue() * stackPos[0].getValue();
stackPos[3].setValue(stackPos[2].getValue());
stackPos[2].setValue(stackPos[1].getValue());
stackPos[1].setValue(stackPos[0].getValue());
stackPos[0].setValue(endProduct);
break;
default:
break;
}
}
system("pause");
return 0;
}
You get the error that you do because there really is no overload of operator+ which stackPos[1] + stackPos[0] could resolve to. The only overload you have is of type WhackyRPN::operator+(WhackyRPN*);(it is a pointer even though you have written an array - read here and here. But that isn't relevant to this question.) The signature should be WhackyRPN::operator+(WhackyRPN). More idiomatic would be WhackyRPN::operator+(const WhackyRPN&). For more, read this great answer.
replace
int finalNum = stackPos[1] + stackPos[0];
with
int finalNum = stackPos[1].getValue() + stackPos[0].getValue();
In your program, you have the array of objects stackPos[], which has functions setValue() and getValue() which take and return integer respectively. You need to use getValue() here as the array elements themselves are not integer, they are objects.
This is exactly what your error statement is saying as well. But you seem to already know that because you have implemented it in * and / operations.
Hope this helps.

class initialization in C++

I tried to initialize an array of a class then use a loop to change the data members in each of the objects. I'm not sure how to get the values to stick, because after I changed the values, I tried to print a random object out and it's just the default values and not the changed values. Any help would be appreciated, Thanks!
#include <iostream>
#include <string>
#include <time.h>
using namespace std;
class card {
private:
int rank;
int suit;
////////////////////////////////////////////////////////////
public:
/////////////////////////////////////////////////////////////
// default constructor with initialization list
card(int userRank = (2,3,4,5,6) , int userSuit=15)
:rank(userRank), suit(userSuit){}
///////////////////////////////////////////////////////////
// function to validate user's rank choice.
int cardcheckRank(int pRank){
while(pRank<2 || pRank>14)
{
cout << "Choose a playing card rank between 2-14, where 11=Jack, "
"12=Queen, 13=King, 14=Ace"<<endl;
cin >> pRank;
}
return pRank;
}
/////////////////////////////////////////////////////////////
// function to validate user's suit choice.
int cardcheckSuit(int pSuit){
while(pSuit<15 || pSuit>18)
{
cout << "Choose a playing card suit "
"between 15-18, where 15=Diamond, 16=Club, 17=Heart, 18=Spades.";
cin >> pSuit;
}
return pSuit;
}
//////////////////////////////////////////////////////////////////
// functioin to get a card value from user.
void storeCard(int pRank, int pSuit){
card(cardcheckRank(pRank),cardcheckSuit(pSuit) );
}
/////////////////////////////////////////////////////////////////
// translates
string faceRank(int translateRank){
switch (translateRank) {
case 2:
return "Two";
case 3:
return "Three";
case 4:
return "Four";
case 5:
return "Five";
case 6:
return "Six";
case 7:
return "Seven";
case 8:
return "Eight";
case 9:
return "Nine";
case 10:
return "Ten";
case 11:
return "Jack";
case 12:
return "Queen";
case 13:
return "King";
case 14:
return "Ace";
default: return "Invalid";
}
}
///////////////////////////////////////////////////////////
// translate integer suit value into a word.
string faceSuit(int translateSuit){
switch (translateSuit){
case 15:
return "Diamonds";
break;
case 16:
return "Clubs";
break;
case 17:
return "Hearts";
break;
case 18:
return "Spades";
break;
default: return "Invalid";
}
}
///////////////////////////////////////////////////////
// Function to print the current card.
void printCard(){
cout << "The rank of the card is ";
cout << faceRank(rank);
cout << " and the suit is " << faceSuit(suit) << "." << endl;
}
}; // End of card class.
//////////////////////////////////////////////////////
// main function.
int main()
{
srand (time(NULL)); // initialize random seed.
card deck[52];
char choice = 'n';
int h = 0; // card number.
for(int i = 15; i < 19; i++)
{
int y = i;
for(int j =2; j < 15; j++)
{
int z = j;
(deck [h]).storeCard(z,y);
cout << "Card rank " << (deck [h]).faceRank(z);
cout << ", suit " << (deck [h]).faceSuit(y) <<endl;
++h;
}
}
do{
cout <<"Would user like to play?(y/n)"<<endl;
cin >> choice;
int ranNum = (rand()% 51 + 0);
if(choice == 'y')
{
cout << "User: ";
deck[7].printCard();
}
}
while(choice == 'y');
return 0;
}
Values are not sticking because your storeCard function doesn't really store the card, it creates a new card object and throws it away. If you really want to express this by invoking the card constructor, then assign the constructed object to the current one:
void storeCard(int pRank, int pSuit){
*this = card(cardcheckRank(pRank),cardcheckSuit(pSuit) );
}
A more idiomatic approach would be for storeCard to directly modify the object's attributes, much like the constructor does:
void storeCard(int pRank, int pSuit){
rank = cardcheckRank(pRank);
suit = cardcheckSuit(pSuit);
}