I'm trying to create a procedural that draws cards from a deck at random. The problem was that I needed to make the draw procedure actually random, as each draw is the same when using srand and rand when no other factors change. Thus I attached it to time_t seconds and was able to make the draw semi/ random. This is because I have to wait for a second to go by for the parameter of time_t seconds to change. The reason this is a problem is that my program is made to draw again if it draws the same card twice (which it's known to do). Thus if it does draw the same card twice it will be forced to draw around fifteen more times (or more or less) until the time_t second parameter changes. Is there a way to measure milliseconds or an otherwise smaller unit of time for time so I don't have this issue?
Here is the code, though the checking for match and organizing proceedures are not attached (those only occur after the initial draw anyway.)
int allow = 0;
string cards[] =
{"02hearts", "03hearts", "04hearts", "05hearts", "06hearts", "07hearts", "08hearts","09hearts", "10hearts", "11hearts", "12hearts", "13hearts", "14hearts",
"02clubs", "03clubs", "04clubs", "05clubs", "06clubs", "07clubs", "08clubs", "09clubs", "10clubs", "11clubs", "12clubs","13clubs", "14clubs","14clubs",
"02spades", "03spades", "04spades", "05spades", "06spades", "07spades", "08spades", "09spades", "10spades", "11spades", "12spades", "13spades", "14spades",
"02diamonds", "03diamonds", "04diamonds", "05diamonds", "06diamonds", "07diamonds", "08diamonds", "09diamonds", "10diamonds", "11diamonds", "12diamonds", "13diamonds", "14diamonds"};
string cardHand [5];
string cardnumbers [5];
int cardInts [5];
string handSuites [5];
char handSuitesChar [5];
//check deck
while(allow == 0)
{
//set clock
time_t seconds;
time(&seconds);
srand((unsigned int) seconds);
int type;
//initiate counters
int n = 0;
int n1 = 0;
int n2 = 0;
int n3 = 0;
int n4 = 0;
//draw cards
while(n < 5)
{
type = rand() % 52;
cardHand[n] = cards[type];
cout << cardHand[n] << ", ";
n++;
}
cout << endl;
//pull numbers from cards
while(n1 < 5)
{
string character2;
cardnumbers[n1] = cardHand[n1].at(0);
character2 = cardHand[n1].at(1);
cardnumbers[n1].append(character2);
cout << cardnumbers[n1] << ", ";
n1++;
}
cout << endl;
cout << endl;
//convert numbers to ints
while(n2 < 5)
{
stringstream convert(cardnumbers[n2]);
if( !(convert >> cardInts[n2]))
cardInts[n2] = 0;
cout << cardInts[n2] + 100 << ", ";
n2++;
}
cout << endl;
//pull out first letters for suites
while (n3 < 5)
{
handSuites[n3] = cardHand[n3].at(2);
cout << handSuites[n3]<< endl;
n3++;
}
//convert letters to chars
while (n4 < 5)
{
stringstream convert(handSuites[n4]);
if( !(convert >> handSuitesChar[n4]))
handSuitesChar[n4] = 0;
cout << handSuitesChar[n4] + 100 << ", ";
n4++;
}
Don't call srand() inside the loop. Call it once at the start of your program, and then just use rand() whenever you need a random number. That'll give you a fairly long pseudorandom sequence.
As Rob pointed out, the problem isn't with rand(), but with
the way you are drawing the cards. There's no reason to every
draw the same card twice. You can use Rob's suggestion, and
shuffle the deck, or you can pick a random card from an
unshuffled deck, and then remove it from the deck (swap with the
end, then pop_back), so that it can't be drawn again.
And of course, never seed the generator more than once in a
single process.
Related
I made a program that prompts the user to guess numbers (which I have programmed to produce a random number)ranging from 1-10, if the user guesses the number successfully which is the same as the random number generated it prints "congratulation", else it prompts the user to try again. but I want to stop the user from answering after a certain amount of time(like Game Over). But the prompt keeps coming, I tried using the break in my while loop but it doesn't work, I also tried using the exit function, which actually stopped the program from running but it stopped it after answering 2 times which is not what I want.
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
int a,b,c,d,e,f;
// generate a random number, prompt the user for any number if the users guess is in line with the random number generated the user wins else try again
//generate a random number between 1 - 10 store it in a variable
cout << "Random Number Generator \n \n";
srand(time(0));
for(int i = 1; i == 1; i++){
a = 1+(rand() % 10);
cout << a << endl;
}
//prompt the user for numbers ranging from 1 - 10
cout << "type in a number from (1 - 10)\n";
cin >> b;
c++;
//check if the number is the same as the random number
//this checks to see if the user gets the question, else it continues running till he gets it
while(a != b){
cout << "You're incorrect!\n";
cout << "type in a number from (1 - 10)\n";
cin >> b;
while(b <= 3){
exit(3);
}
}
//print result
if(a == b){
cout << "congratulations";
}
return 0;
}
how can I make this work?
You could count the number of times the user answers and stop when it has executed for the number of times you want.
//prompt the user for numbers ranging from 1 - 10
cout << "type in a number from (1 - 10)\n";
cin >> b;
int answer_count = 1; // variable to count answers (there is already 1 answer here)
const int max_attempts = 10; // number of attempts the user has
//check if the number is the same has the random number
//this checks to see if the user gets the question, else it continues running till he gets it
while(a != b){
cout << "You're incorrect!\n";
cout << "type in a number from (1 - 10)\n";
cin >> b;
answer_count++; // count this new answer
if (answer_count >= max_attempts){ // check if the count reached the "certain amount of time"
break; // exit from this loop
}
}
Alternatively, you could also give the user a certain amount of time to guess. For example, 10 seconds. This can easily be achieved using the C++ chrono library:
#include <chrono>
#include <iostream>
#include <random>
int main(int argc, char **argv)
{
const int max_time = 10; // seconds
const int min_secret = 1;
const int max_secret = 10;
// This generates a random number between min_secret and max_secret using the STL random library
std::random_device r;
std::default_random_engine e(r());
std::uniform_int_distribution<int> uniform_dist(min_secret, max_secret);
int secret = uniform_dist(e);
auto start = std::chrono::system_clock::now();
int guess;
do {
std::cout << "Type a number from (1 - 10)\n";
std::cin >> guess;
if (guess == secret)
break;
std::cout << "Your guess is incorrect!\n";
// See if the time elapsed since the start is within max_time
auto now = std::chrono::system_clock::now();
auto elapsed_time = std::chrono::duration_cast<std::chrono::seconds>(now - start);
if (elapsed_time.count() > max_time) {
std::cout << "You ran out of time.\n";
exit(0);
} else {
std::cout << "You still have " << max_time - elapsed_time.count() << " seconds left\n";
}
} while (guess != secret);
std::cout << "Your guess was correct, congratulations!";
}
Note that the time check is only performed after the user tried to guess, so if the time limit is 10 seconds and the user waits 30 to type, it will still allow. To kill the program entirely with a timer in C++, you could use the thread library to spawn a second thread that handles the elapsed time, or even use an interruption based scheme (see https://stackoverflow.com/a/4001261/15284149 for an example of timer).
Also, note that the user input is not sanitized, and if the user writes anything other than a number your program has undefined behavior.
You need to fix up several things in your code:
The variable c is kept uninitialized and incremented later to use nowhere. Remove this. Note that d, e, f are unused as well.
In the loop:
for(int i = 1; i == 1; i++) {
a = 1 + (rand() % 10);
cout << a << endl;
}
You have told the compiler to iterate until i == 1, increment it by one, it is only done once – and that you might not want to do but i < 10.
Also, You are not using an array to store those 10 random numbers, but the last one. You need to make an array of 10 rooms and assign it to each of them:
int a[10];
// Since the array index begins at zero
for (int i = 0; i < 10; i++) {
a[i] = (rand() % 10) + 1;
cout << a[i] << endl;
}
After the successful assignment, it's time to introduce a randomly chosen index as the right answer (it should be put before the while loop):
// To choose the random index
int shuffle = a[rand() % 10];
Also, replace the congratulating statement:
// It was a == b previously
if (shuffle == b)
cout << "congratulations";
Lastly, to quit after three incorrect attempts, replace the while loop:
int count = 0;
while (shuffle != b) {
count++;
cout << "You're incorrect!\n";
cout << "type in a number from (1 - 10)\n";
cin >> b;
if (count == 2) {
cout << "Game Over" << endl;
exit(0);
}
}
I'm making a program to get the average number of dice rolls to get a 6, but there seems to be an issue with the RNG. I suspect it's the seed, as while the number is different each time I compile and run the code, it doesn't change in each individual attempt, so the average doesn't change. Heres my code:
#include <iostream>
#include <cstdlib> // random numbers header file//
#include <ctime> // used to get date and time information
using namespace std;
int main()
{
int roll = 0; //declare a variable to keep store the random number
int i = 0;
int counter = 0;
int resume = 1;
int average = 0;
int totalrolls = 0;
srand(time(0)); //initialise random num generator using time
while (resume != 0) {
while (roll != 6) {
roll = rand() % 6 + 1; // generate a random number between 1 and 6
i++;
}
counter++;
totalrolls += i;
average = totalrolls / counter;
cout << "the average number of rolls to get a 6 is " << average << ", based on " << counter << " sixes." << endl;
cout << "do you wish to keep rolling? ";
cin >> resume;
cout << endl;
}
return 0;
}
Anyone got any idea what's going on?
Notice that roll only gets updated inside this loop:
while (roll != 6) {
...
}
This means that after that loop finishes running with roll set to 6, it will never run again, even if the outer loop executes another time.
To fix this, you could either
change this to be a do ... while loop so that it always executes at least once; or
manually reset roll to a value other than 6 on each iteration through the outer while loop; or
change where roll is defined so that it's local to the outer while loop and so you get a fresh copy of it per outer loop iteration, which is basically a better version of option (2).
I had to program a game of blacjack for class. Everything seems to be working fine, except shuffling the card deck when initializing the game (drawing the first two cards). Everything from then on out seems random.
I'll provide all necessary code. The randomWithLimits-function I am using:
int randomWithLimits(int upperLimit, int lowerLimit)
{
return (std::rand() % (upperLimit - lowerLimit + 1) + lowerLimit);
}
Simple enough, it is seeded in the main, like this:
int main()
{
srand(time(nullptr));
Blackjack bj;
bool play = true;
while (play == true) play = bj.playGame();
return 0;
}
The blackjack function itself is quite long, but here's the part that doesn't work properly (the first round):
bool Blackjack::playGame() {
CardDeck deck = CardDeck();
std::cout << "The dealer shuffles the deck\n";
deck.shuffle();
drawInitialCards();
std::cout << "\nYour hand is currently " << playerHand << ".";
{...}
std::string cont;
std::cout << "\n\n\nDo you wish to play another round? (y/n) ";
std::cin >> cont;
while (cont != "y" && cont != "n") {
std::cout << "\nNot a valid choice, choose again: (y/n) ";
std::cin >> cont;
}
if (cont == "y") return true;
else return false;
}
CardDeck is a class with this function
CardDeck::CardDeck() {
int count = 0;
for (int s = CLUBS; s <= SPADES; s++) {
for (int r = TWO; r <= ACE; r++) {
Card card(static_cast<Suit>(s), static_cast<Rank>(r));
cards.push_back(card);
}
}
currentCardIndex = 0;
}
which creates the deck. currentCardIndex keeps track of how many cards have been drawn, s is an enum-type called Suit and r is an enum-type called Rank. This seems to work fine.
It uses this shuffle function,
void CardDeck::shuffle() {
int count = 0;
while (count < 100) {
int a = randomWithLimits(51, 0);
int b = randomWithLimits(51, 0);
swap(a, b);
count++;
}
}
which uses the randomWithLimits-function from earlier and this swap-function
void CardDeck::swap(int a, int b) {
Card temp = cards[a];
cards[a] = cards[b];
cards[b] = temp;
}
It's not a big issue, but it still bothers me. Whenever I compile and run the function for the first time, the first output is always:
The dealer shuffles the deck
You drew a Two of Clubs.
The dealer drew a card.
You drew a Four of Clubs.
The dealer drew a card.
Your hand is currently 6.
From then every card seems to be random.
The draw card function:
Card CardDeck::drawCard() {
currentCardIndex++;
return cards[currentCardIndex - 1];
}
The drawInitialCards-function:
void Blackjack::drawInitialCards() {
Card card = deck.drawCard();
std::cout << "\nYou drew a " << card.toString() << ".";
playerHand = getPlayerCardValue(&card);
card = deck.drawCard();
std::cout << "\nThe dealer drew a card.";
dealerHand = getDealerCardValue(&card, dealerHand);
card = deck.drawCard();
std::cout << "\n\nYou drew a " << card.toString() << ".";
playerHand += getPlayerCardValue(&card);
card = deck.drawCard();
std::cout << "\nThe dealer drew a card.";
dealerHand += getDealerCardValue(&card, dealerHand);
}
I've tried messing around with how many times the shuffle-function swaps cards, whether I place the seed in main or the playGame-function etc. but I always get this result. Any help?
Found the mistake. This
bool Blackjack::playGame() {
CardDeck deck = CardDeck();
should simply be written
bool Blackjack::playGame() {
deck = CardDeck();
seems that I created a new deck as I thought.
Since the first cards you are generating are in fact clubs, starting with the two of clubs, it would seem that the shuffle isn't actually touching the top cards of the deck.
One thing that your current code doesn't guarantee is that every card will be hit in the shuffle. Rather than doing it 100 times to a random pair, try swapping each card with a random one in a loop from card 0 to card 51.
void CardDeck::shuffle() {
for(int a = 0; a < 52; a++) {
int b = randomWithLimits(51, 0);
swap(a, b);
}
}
This should ensure that every card is touched in the shuffle, and that every location has an equal likelihood of holding any card. Under your previous system there was a high probability that not all cards would be shuffled.
I'm beginning with C++. The question is: to write a program to input 20 natural numbers and output the total number of odd numbers inputted using while loop.
Although the logic behind this is quite simple, i.e. to check whether the number is divisible by 2 or not. If no, then it is an odd number.
But, what bothers me is, do I have to specifically assign 20 variables for the user to input 20 numbers?
So, instead of writing cin>>a>>b>>c>>d>>.. 20 variables, can something be done to reduce all this calling of 20 variables, and in cases like accepting 50 numbers?
Q. Count total no of odd integer.
A.
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
int n,odd=0;
cout<<"Number of input's\n";
cin>>n;
while(n-->0)
{
int y;
cin>>y;
if(y &1)
{
odd+=1;
}
}
cout<<"Odd numbers are "<<odd;
return 0;
}
You can process the input number one by one.
int i = 0; // variable for loop control
int num_of_odds = 0; // variable for output
while (i < 20) {
int a;
cin >> a;
if (a % 2 == 1) num_of_odds++;
i++;
}
cout << "there are " << num_of_odds << " odd number(s)." << endl;
If you do really want to save all the input numbers, you can use an array.
int i = 0; // variable for loop control
int a[20]; // array to store all the numbers
int num_of_odds = 0; // variable for output
while (i < 20) {
cin >> a[i];
i++;
}
i = 0;
while (i < 20) {
if (a[i] % 2 == 1) num_of_odds++;
i++;
}
cout << "there are " << num_of_odds << " odd number(s)." << endl;
Actually, you can also combine the two while-loop just like the first example.
Take one input and then process it and then after take another intput and so on.
int n= 20; // number of input
int oddnum= 0; //number of odd number
int input;
for (int i = 0; i < n; i ++){
cin >> input;
if (input % 2 == 1) oddnum++;
}
cout << "Number of odd numbers :"<<oddnum << "\n";
Here's what I want my program to do. Prompt the user to input 10 integers. Then my program adds up the even integers, adds up the odd integers, then displays both sums. Simple beginner's exercise. To do this, I'm using a while loop with a control variable. Here is the entirety of my code:
#include <iostream>
using namespace std;
int main()
{
int evenSum = 0;
int oddSum = 0;
int num;
int control = 0;
cout << "Enter 10 integers: " << endl;
cin >> num;
while (control <= 10)
{
if (num%2 == 0)
{
evenSum = evenSum + num;
}
else
{
oddSum = oddSum + num;
}
control++;
cin >> num;
}
cout << "The sum of the even integers is " << evenSum << endl;
cout << "The sum of the odd integers is " << oddSum << endl;
return 0;
}
To test this code, I'm using as input the first 10 positive integers, 1-10. However, I'm having a couple headaches. First, control never passes from the while loop, i.e. the program never gets to the point where it displays the evenSum and outSum variable values. I'm having a hell of a time figuring out why the while loop never terminates. As I've written it, the while condition will become false as soon as control = 11, and the control variable is incremented at the end of the while body, so it should not keep going. Yet it does.
My second headache (probably related) is that the sum of the even numbers in my input should be 30, and the sum of the odd numbers should be 25. However, while my program gets the oddSum correct, it only sums the evens up to 20, so it is not counting the last number (10) for some reason.
I have walked through this program carefully several times on paper. Also, I've had it display the variable values as it goes, so I can track what it is doing with each while loop. Eventually, it just stops displaying output, but without ever actually terminating. And it sums the evens and odds correctly, just without adding that last number.
It seems to me there is at least one off-by-one error here, possible 2 that are compounding each other. But I have tried adjusting my various values and it's nothing doing. My other thought is that I'm suspicious of the way I have set up my input stream. I.e. I'm unsure of what value will be assigned to num in the final iteration of the while loop.
Can anyone shed some light on either of these problems?
Read at the top of your loop (after checking the count)
// cin >> num;
while (control <= 10)
{
cin >> num;
if (num%2 == 0)
{
evenSum = evenSum + num;
}
else
{
oddSum = oddSum + num;
}
control++;
// cin >> num;
}
Try to trace the code execution. Manually. That is the best way to learn how computers think.
You’ll realize, that the loop condition is broken. You start counting from 0, continue up to 10 including, stop at 11. 0..10, that’s 11 numbers!
Furthermore, you are reading input once at the beginning and then once at the end of each iteration. That makes 12 reads.
When trying to read more input than supplied, the program blocks and waits for more input. A program in infinite loop is active, it consumes all your CPU resources. In this case the program is blocked and uses close to no resources.
ask to enter numbers inside the loop,its easy to understand when to input particular number
int control = 1;
while (control <= 10)
{
cout << "Enter integer at position:"+Control << endl;
cin >> num;
if (num%2 == 0)
{
evenSum = evenSum + num;
}
else
{
oddSum = oddSum + num;
}
control++;
}
I could not see an error. Only the issue that you have to put 11 numbers instead of 10. Have you tried to type 11 numbers?
hey i am also a beginner but i tried to answer your question. you could also use compound assignment i.e. += instead of repeating evenSum and oddSum twice.
#include <iostream>
using namespace std;
int main()
{
int evenSum = 0;
int oddSum = 0;
int num;
int control = 0;
cout << "Enter 10 integers: " << "\n";
while (control <= 9 )
{
cin >> num;
if (num % 2 == 0)
{
evenSum += num;
}
else
{
oddSum += num;
}
control++;
}
cout << "The sum of the even integers is: " << evenSum << "\nThe sum of the odd integers is: " << oddSum << "\n";
return 0;
}