outputting to a file in a recursive function - c++

I have a program that is a game tournament that battles recursively and deletes players from a player container until there is only 1 player left. It is the card game War, and for every battle I need to output the winner of each battle in the game to a file. So for example it would look something like this
John vs James
Battle 1: James wins
Battle 2: John wins
...
Battle 5: James wins, John is out of cards. James wins the game
but then since this is a tournament, John gets removed from the container and the next two people battle so we go from 16 to 8 to 4 to 2 players and then lastly the winner. I already have the code for this all worked out I need need to know how I can do this part recursively:
ofstream outFile;
outFile.open(argv[2]);
outFile << player1Name << " vs. " << player2Name << endl;
outFile << "Battle" << //number battle & winner etc, etc
I want to do this so that every time the PROGRAM is ran, it overrides everything in the file, but everytime a GAME is played within the tournament it just adds to the end of the previous battle. I have a few ideas but I'm not sure what's the best way to go about this. I was thinking about putting
ofstream outFile;
outFile.open(argv[2]);
In the driver.cpp file, then calling the recursive function game.tournament() but passing in game.tournament(outFile), into void Game::tournament(ofstream& outFile) then using the outFile << statements and calling doing the recursive call tournament(outFile) and once the recursive function ends, .close() the file back in the driver.cpp. Would this work the way I think it would? As in it opens and closes in the driver, but I have access to print out to it in the recursive function
Also to be clear the base case is when the queue of players has a .size() < 2, meaning it has only 1 player left in it and thus that player is the winner, that's why my recursive function has a void return value. This is not the part I need help with but I figured I'd include it in case people were wondering

At the beginning of your program, before calling the recursion open your file like this
outFile.open(argv[2], std::ofstream::trunc);
This will truncate everything from the file, then close it.
Next in your recursive function, open the file for appending like this
outFile.open(filename, std::ofstream::app);
See the reference for ofstream here

Related

An automatic grader in c++

I am trying to write an automatic grading program for a C++ course I am teaching. Usually, automatic graders use (input,output) pairs: the submitted program reads from standard input and writes to standart output, and the grader compares it with the expected output. But I want my students to practice specific C++ constructs (and not e.g. write a program in C), so the tests are written in C++. In a simple example, I give them a main program such as:
#include "func.hpp"
...
int main() {
test(func(1)==2);
test(func(2)==33);
...
/* some 100 tests, including some randomized tests */
...
cout << "Grade: " << grade << endl;
}
The students have to submit the files func.hpp and func.cpp (for more complex assignments, some more files are required).
There is a bash script that compiles main.cpp with func.cpp, runs the program and reads the grade from the last line (It is run within a docker container, to prevent inadvertent damage to the host computer).
The problem is that a student can, from within func, print "Grade: 100" and exit.
Is there a simple way to make the grader more reliable?
I don't want to go crazy with this, but if you want to make it safe, you should put the student work in a "clean room" so to speak. This is a tedious exercise, but once done, it will be very safe. You said you run in a docker container, so I would run the student's work in a sub-process with IO redirected (to a pipe, file, or to /dev/null, depending on whether some of your assignments involve console output). That way a smart-ass student can print whatever they want, but they will only be piping it to you, not printing to the console. I'm not going to go into the code for this - I saw lots of examples I liked here on Stack Overflow by searching for "fork with redirected stdout" and it's a classic forumula you probably know.
In pseudo code, it would look something like:
main() {
<tedious setup for stdin/stdout/stderr redirection>;
int ch = fork();
if (ch == 0) {
test(func(1)==2);
test(func(2)==33);
.
.
// test clearly generates "grade" so use it as an exit code as an
// easy way to return the information you want
exit(grade);
} else {
for (;;) {
<wait on and read stdout and stderr and do whatever you want to it - it won't go to the console, so no dirty tricks.>;
<you could analyze the student's output as part of grading, or pass it to the console with a highlight, so you know it's not your grade output>
<wait on ch to exit, get the exit code, display it as the grade and break>;
<generate some input if you want to have an assignment where the students read from stdin>;
<add a time-out on waiting for the child to exit. That way evil student can't just hang or busy-loop, whether on purpose by accident.>;
<if it seems to be hanging, you have to process id and can kill it.>;
}
}
}
Obviously the above is sketchy. When you loop on managing a child process, you have to check on everything simultaneously with select or something similar, but you sound like a pretty senior engineer. You get the basic idea. The students can't get away with anything if you keep their run-time environment in a child process that you manage. Plus it gives you you a platform to pull the strings of their code anyway you see fit.
Easy. When you do the analysis, just use a different main than what you gave the students as a reference program. Your version prints your secret key.
int main() {
test(func(1)==2);
test(func(2)==33);
...
/* some 100 tests, including some randomized tests */
...
cout << "The student doesn't know my version prints this next line" << endl;
cout << "Secret validation code: NCC-1701" << endl;
cout << "Grade: " << grade << endl;
}
A clever student who does what you suggests (prints 100 and exits), won't know about the secret message that your version prints and script validates for.
True story. When I was teaching a networking class, there was a homework assignment to implement a "stop and wait" protocol with UDP sockets. My code implemented the "client". The student's version implemented the "server". One student didn't have the networking calls working, but was clever enough to just print the expected output with sleep calls in between print statements. He would have gotten away with it if I hadn't of stopped my client program first and noticed his was still printing our lines of "incoming" data being received.

c++ how to read and write within a file

i want to make a text based rpg game, but ive run into a problem, im fairly "new" to c++, know a few concepts but still learning.
So what i want to know is; how do i open a file and edit the values in it?
say i have a file called health, for my characters health and its set to 100. I know you can just subtract the variable by the damage you set the monsters to do, but i dont know how i store the health and edit it, while my program goes along.
ie. this is the farthest i got:
ifstream objectFile("health.txt");
string health;
double NoH;
cout << "welcome" << endl;
objectFile >> health >> NoH;
cout << health << ' ' << NoH - 15;
NoH = Number of health. So far all my program does, is read the file, and subtract 15 from 100 because thats the damage the monster do. But how do i make it "take out" the value and subtract 15 from it? then store it back so it's 85, and next time i get hit its 65 for example etc, so it makes it the objective of the game is about surviving, ie avoiding getting hit and stuff. i mean avoiding your hp to reach 0, but also i want to learn how to implement simple text based creatures you can kill, by letting their hp reach 0.
thanks
what about using ini /properties file?
or using json?
if you are making rpg, player save the values (hp,mp,item, map(x,y) etc) to file when saving the game? and the rest of the time should store/calculate those value in memory I guess.
about json
https://code.google.com/p/vjson/
about ini file
http://www.hyperrealm.com/libconfig/

When I use a value from a dictionary instead of coming out as a flat 65 it comes out as a scientific notation. How do I prevent this?

I am making a text based game experiment thing for fun because I just started learning about a week ago, when I use the value of health that the player has instead of 65 it comes up as 6.500000e+01 which, doesn't read very well how do I prevent this? This is my first time here should I post my whole code?
if 'eat' in food:
print "Then starts the feast, you eat everything you can reach. After a while you become to tired and need to rest."
print "You wake up with no sense of how much time has passed. You ate too much but feel healthier. You continue on into through the only doors you can see."
player["health"] += 15
print "You are now at %(health) health." % player
"Try %d" % (player ["health"])

C++ File outputting strange number, and part of code not running

Yeah. So, I'm trying to make a code for a guessing game. In this game, there's a hard mode. In hard mode, you have 15 guesses, and have to guess between 1 and 500. But my problem is this:
I'm trying to have hard mode save & display your wins/losses, but when it outputs the contents of wins.txt it outputs something like this:
Wins: 0x7fffee26df78
Losses: 0x7fffee26e178
It's really confusing me. Here's the part of the code I have for that:
ifstream losses_var("losses.txt");
ifstream wins_var("wins.txt");
losses_var>> loss;
wins_var>> win;
wins_var.close();
losses_var.close();
Then it gets called with:
cout<<"Wins: "<< wins <<"\nLosses: "<< losses <<"\n"
If you would like to see the full source code, it's here: http://pastebin.com/gPT37uBJ
My second problem:
Hard mode won't display when you win. That's pretty much the whole problem. In my code, the loop for asking users for input uses
while (guess != randNum)
So at the end bracket I have what I want the code to display when a user wins, but it just doesn't run. It just stops. I would like it if someone could help me with this. The line that has the bug is line 97 through 105. Again, source code is here: http://pastebin.com/gPT37uBJ
You've got your variable names confused
cout<<"Wins: "<< wins <<"\nLosses: "<< losses <<"\n";
should be
cout<<"Wins: "<< win <<"\nLosses: "<< loss <<"\n";
It's important to pick good variable names. One reason is so that you don't confuse yourself about what your variables mean (if you confuse yourself think how it's going to be for someone else looking at your code).
Others have already answered the output problem (win vs. wins). The other problem is probably in your logic of while loop nesting. The outer loop (while (guess != randNum)) starts, but its body contains the entire inner loop (while (guesses_left != 0)). This means that the outer condition is not checked again until the inner loop terminates, which means you've run out of guesses. Also note that if you guess correctly, inner loop will never terminate. You probably want something like this:
while (guesses_left > 0) {
// input user's guess
if (guess < randNum) {
// process it
} else if (guess > randNum) {
// process it
} else {
// it's equal, user won
// do what's necessary for a win
return 0;
}
}
// ran out of guesses
// do what's necessary for a loss
return 0;
You are not writing your variables win and loss to cout. From your pasted code, I can see that wins and losses are ofstream objects, which means you are probably seeing addresses there. I would advise you to choose more informative variable names to avoid hard to spot mistakes like this.

Automatic cout flushing

Good day,
I wrote a Java program that starts multiple C++ written programs using the Process object and Runtime.exec() function calls. The C++ programs use cout and cin for their input and output. The Java program sends information and reads information from the C++ programs input stream and outputstream.
I then have a string buffer that builds what a typical interaction of the program would look like by appending to the string buffer the input and output of the C++ program. The problem is that all the input calls get appended and then all the output calls get posted. For example, and instance of the StringBuffer might be something like this...
2
3
Please enter two numbers to add. Your result is 5
when the program would look like this on a standard console
Please enter two numbers to add. 2
3
Your result is 5
The problem is that I am getting the order of the input and output all out of wack because unless the C++ program calls the cout.flush() function, the output does not get written before the input is given.
Is there a way to automatically flush the buffer so the C++ program does not have to worry about calling cout.flush()? Similiar to as if the C++ program was a standalone program interacting with the command console, the programmer doesn't always need the cout.flush(), the command console still outputs the data before the input.
Thank you,
In case someone comes looking for a way to set cout to always flush. Which can be totally fair when doing some coredump investigation or the like.
Have a look to std::unitbuf.
std::cout << std::unitbuf;
At the beginning of the program.
It will flush at every insertion by default.
I can't guarantee that it will fix all of your problems, but to automatically flush the stream when you're couting you can use endl
e.g.:
cout << "Please enter two numbers to add: " << endl;
using "\n" doesn't flush the stream, like if you were doing:
cout << "Please enter two numbers to add:\n";
Keep in mind that using endl can be (relatively) slow if you're doing a lot of outputting
See this question for more info