Taking an intro to C++ class in University and we got this project to 'model' a tennis game.
The user will first need to enter the probability that player a will win.
Then generate a number between 1 and 100 until a player has more than 4 points and has 2 more points than the other player.
My problem is that sometimes around the 50% win rate area the output will come out as 4-4.
I am wondering why this is happening?
Any help would be greatly appreciated!!
int prob;
int scoreA = 0;
int scoreB = 0;
int randNB = 0;
srand(time(NULL));
cout <<"---------------\n"
"FAKE TENNIS!\n"
"---------------" <<endl;
cout <<"What is the chance that player \'A\' will win a point?(Enter whole #between 1 - 100): " ;
cin >> prob;
do{
if((scoreA >= 4 || scoreB >= 4) && ((scoreA - scoreB) >= 2 || (scoreB - scoreA) >= 2)) break;
randNB = rand()%100+1;
if (randNB <= prob){
cout<<"A";
scoreA++;
}
else if(randNB > prob){
cout<<"B";
scoreB++;
}
}
while((scoreA <= 3|| scoreB <= 3) && ((scoreA - scoreB) !=2 || (scoreB - scoreA) !=2 ));
cout<<"The final score is " <<scoreA <<" (A) - " << scoreB <<" (B)" <<endl;
if(scoreA > scoreB){
cout <<"A is the winner!!!";
}
else{
cout <<"B is the winner!!!";
}
return 0;
}
You've written the end-loop test twice.
Once as a positive inside the loop (correctly) and once as a negative at the end of the loop.
1) Write it only once. (The "break" will end the loop.) That is, replace the do { ... } while(...) with just while(true) { ... }
2) If you want to write it twice, check <2 rather than != 2 in the second test. The negation of x>=2 is not x!=2
Related
I'm having this strange issue where my code does exactly what I want it to when I run it through my debugger, but it doesn't work when I run it normally. What's stranger is that I am not getting a runtime error either. This is where the issue might be, but I'm not 100% sure on this:
void calcMostMissed (double *ptr, int totalContestants, int arrSize)
{
//output header
cout << endl << "MOST MISSED QUESTIONS" << endl;
//check how many times a question is missed and its percentage, then output it if it's above 60%
double curQuest = *ptr;
int freq = 0;
int j = 0;
double percentMissed;
for (int i = 0; i <= arrSize; i++) //loop through the missed questions array
{
if (*(ptr + i) > 0) //if pointer is pointing at a question number (extra space in array is set to 0)...
{
if (*(ptr + i) == curQuest) //then check how often it occurs in the array
freq++;
}
else //if the pointer is not pointing at a question number anymore...
{
//calculate percent missed and output it if its 60% or greater
percentMissed = (static_cast<double>(freq) / totalContestants) * 100;
if (percentMissed >= 60)
{
cout << static_cast<int>(curQuest) << "\t" << fixed << setprecision(2) << percentMissed << "%" << endl;
}
// check if the question's percentage missed has already been calculated and evaluated
j++;
curQuest = *(ptr + j);
int r = 0;
while (r < j)
{
if (*(ptr + r) == curQuest)
{
if (j < arrSize - 1)
{
j++;
curQuest = *(ptr + j);
}
}
r++;
}
if (!(j == arrSize - 1 && r == arrSize - 1))
{
i = 0;
}
freq = 0;
}
//if the current question variable has been through all missed question, then leave loop
if (curQuest < 1)
{
break;
}
}
}
What this function is supposed to do overall is find the percent missed on all missed questions and output only the ones that are above 60% inclusive.
This is what my debugger outputs (and what I want it to look like):
Enter name of answer key file: batch7a.txt
Enter name of contestant's answers file: allWrongContestants.txt
oo12345678 - 0.00
1 2 3
C A B
A B C
0012387654 - 0.00
1 2 3
C A B
A B C
0012364213 - 0.00
1 2 3
C A B
A B C
Mean: 0.00
Median: 0.00
Mode: 0.00
MOST MISSED QUESTIONS
1 100.00%
2 100.00%
3 100.00%
This is what a normal execution ouputs:
Enter name of answer key file: batch7a.txt
Enter name of contestant's answers file: allWrongContestants.txt
oo12345678 - 0.00
1 2 3
C A B
A B C
0012387654 - 0.00
1 2 3
C A B
A B C
0012364213 - 0.00
1 2 3
C A B
A B C
Mean: 0.00
Median: 0.00
Mode: 0.00
MOST MISSED QUESTIONS
Process returned 0 (0x0) execution time : 14.442 s
Press any key to continue.
My debugger runs through all the way to the end of my program just fine, but for some reason the normal execution is still flawed. Any suggestions are welcome and I'll clarify anything that I may have forgotten to mention.
If it helps, I am using Code::Blocks as my IDE
Some other info about my code: there are 3 questions and all contestants scored a 0% on the test, meaning all questions have the incorrect answers.
Output: The numbers are the contestant's ID, next to that is their score, the list of numbers underneath is the question number they got wrong, underneath that are the contestant's answers, and under that are the correct answers.
This is the function that calls the calcMostMissed function:
void statReport (double *ptr, int totalScores, double *mmqPtr, int arrSize)
{
//calculate mean of scores
double mean = calcMean(ptr, totalScores);
//calculate median of scores
double median = calcMedian(ptr, totalScores);
//calculate mode of scores
double *mode = calcMode(ptr, totalScores);
//output to console the data
cout << "Mean: " << fixed << setprecision(2) << mean << endl;
cout << "Median: " << median << endl;
cout << "Mode: ";
sort(mode, mode + totalScores);
int j = 0;
for (int i = 0; i < totalScores; i++)
{
if (*(mode + i) != -1)
{
if (j == 0)
{
cout << *(mode + i);
}
else
{
cout << ", " << *(mode + i);
}
j++;
}
}
cout << endl;
//call calcMissedQuestions function
calcMostMissed(mmqPtr, totalScores, arrSize);
//delete pointers
delete[] mode;
mode = nullptr;
delete[] mmqPtr;
mmqPtr = nullptr;
}
And this is the main function:
int main()
{
string answerKeyName;
string contestantAnswerName;
ifstream answerKeyFile;
ifstream contestantAnswerFile;
//ask for file names
cout << "Enter name of answer key file: ";
cin >> answerKeyName;
cout << "Enter name of contestant's answers file: ";
cin >> contestantAnswerName;
//check if files can be opened properly
answerKeyFile.open(answerKeyName, ios::binary);
contestantAnswerFile.open(contestantAnswerName, ios::binary);
if(!answerKeyFile)
{
cout << "Answer key file could not be opened" << endl;
exit(EXIT_FAILURE);
}
if (!contestantAnswerFile)
{
cout << "Contestant's answers file could not be opened" << endl;
exit(EXIT_FAILURE);
}
//find how many contestant's there are
int i = 0;
string temp;
while (contestantAnswerFile.good())
{
getline(contestantAnswerFile, temp);
if (temp != "")
{
i++;
}
}
contestantAnswerFile.clear();
contestantAnswerFile.seekg(0, ios::beg);
//create contestant's score array
double *scorePtr = new double[i];
//create pointer for all missed questions
double *mmqPtr = nullptr;
int arrSize;
//compare the contestant's answers to the answer key, then fill array with score
double score;
for (int c = 0; c < i; c++)
{
score = compareAnswers (contestantAnswerFile, answerKeyFile, mmqPtr, i, arrSize);
*(scorePtr + c) = score;
}
//create the statistics report
statReport(scorePtr, i, mmqPtr, arrSize);
//delete dynamically allocated array
delete[] scorePtr;
scorePtr = nullptr;
//close files
answerKeyFile.close();
contestantAnswerFile.close();
return 0;
}
Below is where I think the issue resides, however I still cannot properly compile it because other functions and input files are not provided, probably rightly so in order not to further congest the question:
double *mmqPtr = nullptr; is defined in main(), then it's passed to the statReport() function without having been associated with any object.
Afterward it acts as first parameter for function calcMostMissed() and gets dereferenced inside it, but is still a nullptr, so this produces undefined behaviour.
There is also the issue of an out-of-bounds index inside a loop, as pointed at in the comments.
So I'm making a sudoku solver to kind of test myself, and I have seem to hit a wall.
I'm trying to get the user to input values into a grid, and it'll automatically update every couple of seconds to see the next value they put in the grid.
I don't know how to get the user input into the grid itself.
Here is my code for the grid itself.
void draw()
{
int given;
cout << endl;
for (int i = 0; i < 13; i++)
{
for (int j = 0; j <= 9; j++)
{
if (j == 0)
{
cout << "|";
}
if (j == 3 || j == 6 || j == 9 )
{
cout << "|";
}
if (i == 0 || i == 4 || i == 8 || i == 12)
{
cout << "#";
}
else
{
cout << " ";
}
}
cout << endl;
}
}
To get this to refresh, I have this loop.
while (gameOver != TRUE)
{
system("cls");
draw();
cout << "\nEnter the next given number, or 0 for a blank space: ";
Sleep(600);
}
So I need help getting the user input value to both
Display on the grid
Save in any way (I think an array might work best?)
Thanks.
I personally think that the easiest way to visualize (and store) the values would be in a two-dimensional array.
You can declare and n * m array like this :
int x[n][m];
Then access elements (i,j) like this in your for loop to display it :
x[i][j]
By this line I guess you're programming on Windows:
system("cls");
So my answer will be based on that and utilize a lot of WinAPI.
Normally, you can stick to cin and update the grid after user presses Enter. But since you want a real-time display refresh, this doesn't seem optimal. You have conio.h on Windows so go for it:
#include <conio.h>
...
char ch;
while (true) {
while (!kbhit()); // Wait for user input
ch = getch();
switch (ch) {
// Process input here.
}
}
I have a homework assignment that requires me to calculate a percentage chance from an user input of the numbers 1 to 3. However, I'm not sure how to do this.
This is my code, not all of it though:
void SwingAtBall( Ball *tBall ) {
std::cout << "How hard do you want to hit the ball? Please enter a number between 1 to 3." << std::endl;
int tBallHit;
std::cin >> tBallHit;
if ( tBallHit > 3 || tBallHit < 1 ) {
std::cout << "That is not a valid value. Please enter a number between 1 to 3." << std::endl;
std::cin >> tBallHit;
}
}
// Prompt for 1 to 3. There is a (input * 15) percent chance the ball only goes 5 feet. Otherwise the ball is hit a random number between 0 and (input * 150). Print how far it went.
If my understanding is correct that there is an (input * 15) percent chance the ball will go 5 feet and an (100 - (input * 15)) percent chance it will go anywhere from 0 to (input * 150) feet, then the following code will calculate what you are looking for...
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
int inp, chance1, dist1, dist2, dist_final;
do {
cout << "Enter integer between 1 and 3: ";
cin >> inp;
} while (inp < 0 || inp > 3);
dist1 = 5;
srand(time(0));
dist2 = rand() % (inp * 150);
chance1 = (inp * 15) / 100;
dist_final = chance1 * dist1 + (1 - chance1) * dist2;
cout << "It went this far: " << dist_final << endl;
// system("pause");
return 0;
}
There's a whole <random> header for things like this.
Simple percentages are easy, you can use integers for that. Pick either 0-99 or 1-100, and use that in a uniform_int_distribution. Sure, 15% is 3/20 so you could also use a uniform_int_distribution(1,20) but that's more obscure.
"0 to (input * 150)" is a uniform_int_distribution(0,input*150).
I'm making a coin toss program for my c++ class and we are required to make a function that flips a coin and prints out if it is heads or tails, and print 10 per line. When I ran the program though the if statements I used to detect if the coin was heads or tails weren't enough to pick from the two.
#include <iostream>
#include <ctime>
using namespace std;
void coinToss(int times);
int main()
{
srand(time(0));
int times;
cout << "How many times would you like to toss the coin?" << endl;
cin >> times;
coinToss(times);
return 0;
}
void coinToss(int times)
{
int toss = 0, count = 0;
for(int i = 0; i < times;i++)
{
toss = rand()%2;
if(toss == 1)//Detects if coin is heads.
{
cout << "H";
}
if(toss == 0)//Detects if coin is tails.
{
cout << "T";
}
else //I had to include this for the program to run, further explanation below the code.
{
cout << "Ya done goofed.";
}
count++; //Counts to ten
if(count == 10) //Skips to the next line if the coin has been tossed ten times.
{
cout << endl;
count = 0;
}
}
}
At one point I replaced the heads or tails with "cout << toss;" and the only numbers returned were 1 and 0. I don't understand how if I'm getting only the two numbers I'm checking for some of them aren't being caught by my if statements.
To complete the assignment I've changed the second if statement into an else statement and everything seems peachy, but I'd really like to understand what's going on here.
What happens with your code is:
Is the result 1 ? Then print H. Keep going. Is the result 0 ? Then print T. Else, if it's not 0, print "Ya done goofed.".
You need to keep your if statements linked together:
if (toss == 1) {
cout << "H";
} else if (toss == 0) {
cout << "T";
} else {
cout << "Ya done goofed.";
}
You won't fall in the else case anymore and will be able to remove it.
As a sidenote, regarding your overall program structure: your coinToss function shouldn't do everything. Your code should be more splitted: a function which returns H or T, a function which calls this function X times as requested by the user and formatting the output would be a good start.
Another small note: your count variable, allowing you to add a new line every 10 flips, could be removed. i % 10 will give you the same result: every ten increments, i % 10 would be equal to 0.
You're probably printing the output properly, then terminating without writing a newline on the last line, and your shell prompts clearing back to the left margin and overwriting your output (clearing the rest of the line to boot). If you have less than 10 tosses, your only line of output may appear lost, otherwise it'll be the last line.
Try adding an extra std::cout << '\n'; before main returns.
(Separately, you can say std::cout << "HT"[rand() % 2];, or std::cout << (rand() % 2 ? 'H' : 'T'); and do away with the ifs, but it's no big deal... whatever's clearest for you at this stage)
Well, rand()%2 will produce only two numbers: 1 and 0, this seems to be in line with your task as a coin is a boolean number generator, isn't it? :)
Therefore this seems to do the job you are looking for:
#include <iostream>
#include <ctime>
using namespace std;
void coinToss(int times);
int main()
{
srand(time(0));
int times;
cout << "How many times would you like to toss the coin?" << endl;
cin >> times;
coinToss(times);
return 0;
}
void coinToss(int times)
{
int toss = 0, Count = 0;
for(int i = 0; i < times;i++)
{
toss = rand() % 2;
// Choose:
cout << ((toss) ? "H" : "T"); // if you want a character
// or
cout << toss; // if you want the number
Count++; //Counts to ten
if(Count == 10) //Skips to the next line if the coin has been tossed ten times.
{
cout << endl;
Count = 0;
}
}
}
if(toss == 1)//Detects if coin is heads.
{
cout << "H";
}
else if(toss == 0)//Detects if coin is tails.
{
cout << "T";
}
You need to use else-if statement. You also need not use else after the toss==0 because rand()%2 will either be 0 or 1. There is no third option.
rand() returns a pseudo-random integral number in the range between 0 and RAND_MAX. And, rand() % 2 will be 0 or 1. So, there would be:
if(toss == 1)//Detects if head
{
cout << "H";
}
else // tail
{
cout << "T";
}
I don't think there is anything wrong with this. Well not that I can see... If I add some debug then I see what I think you're expecting...
#include <iostream>
#include <ctime>
using namespace std;
void coinToss(int times);
int main() {
srand(time(0));
int times;
cout << "How many times would you like to toss the coin?" << endl;
cin >> times;
coinToss(times);
return 0;
}
void coinToss(int times) {
int toss = 0, count = 0;
for(int i = 0; i < times;i++) {
toss = rand() % 2;
cout << "Toss: " << toss << endl;
if(toss == 1)//Detects if coin is heads.
{
cout << "H (" << toss << ")" << endl;
}
if(toss == 0)//Detects if coin is tails.
{
cout << "T (" << toss << ")" << endl;
}
count++; //Counts to ten
if(count == 10) //Skips to the next line if the coin has been tossed ten times.
{
//cout << endl; count = 0;
}
}
}
And compile it
g++ coin_toss.cc
And run it
./a.out
How many times would you like to toss the coin?
4
Toss: 1
H (1)
Toss: 0
T (0)
Toss: 0
T (0)
Toss: 0
T (0)
Then this is exactly what I expect or am I missing something?
You don't need an "if else if" statement.
You can also use a switch:
switch( rand() % 2 )
{
case 0:
cout << "T";
break;
case 1:
cout << "H";
break;
default:
cout << "oops you goofed!;
}
// continue within for loop
If you "forgot" the break after case 1 you would again get the "oops you goofed!" message after each head toss.
For some reason my met variable cannot be used as a function in my last while statement, even though my other two variables can be. When i compile I get the error: '(met <= 2.0e+1)' cannot be used as a function|. How do i fix this?
// Garbage Collection. Michael Heusner.
#include <iostream>
#include <cmath>
using namespace std;
int main(){
int reg_lim, met_lim, glass_lim;
double reg, glass, met;
double total;
double reg_ratio, glass_ratio, met_ratio;
reg_lim= 50;
glass_lim= 20;
met_lim= 20;
cout << "How much regular, glass, and metal garbage do you have?" << endl;
cin>> reg;
cin>> glass;
cin>> met;
total= met+glass+reg;
cout<< "The total number of bags is "<< total<< endl;
met_ratio= met/total;
reg_ratio= reg/total;
glass_ratio= glass/total;
cout<< "The metal ratio is "<< met_ratio<< endl;
cout<< "The glass ratio is "<< glass_ratio<< endl;
cout<< "The regular ratio is "<< reg_ratio<< endl;
if( met==reg==glass)
{
cout<< "All garbage amounts are the same."<< endl;
}
else if (reg> glass && met)
{
cout<< "Regular is the largest."<< endl;
}
else if (glass> met && reg)
{
cout<< "Glass is the largest."<< endl;
}
else if (met> glass && reg)
{
cout<< "Metal is the largest."<< endl;
}
while( reg <= 50) (met <= 20) (glass <= 20);{
while( reg <= 50) (met <= 20) (glass <= 20);{
would be your problem!
That is not a valid while loop statement.
Instead, you should write:
while (( reg <= 50) && (met <= 20) && (glass <= 20)) {
//Statements for loop
}
You may want to balance some parentheses and add some logical operators in that while() condition. Once you do that, perhaps losing the semi-colon before the opening brace will actually break the infinite loop you're about to start executing with the appropriate values for reg, met, and glass.
while (( reg <= 50) && (met <= 20) && (glass <= 20))
{
}
You'll need to use && to chain together your conditions:
while ((reg <= 50) && (met <= 20) && (glass <= 20))
You have a similar problem in your earlier if statement:
if( met==reg==glass)
This should be:
if ((met==reg) && (reg==glass))
But since these are floating point numbers, you should instead check that they differ only by a minimum difference.