Yeah, you got lost. It is because you are trying to comprehend it
all at once. No one can do that. You have to take it a piece at a time.
You started out quite nicely. You wrote functions to:
- display the current state of the game (progress)
- determine if someone has won the game (and, supposedly, determine if the game is over)
- check for a valid move
- determine whether or not to play the game again
However, you began mixing things up. For example,
go_on() is supposed to tell you whether or not the user wants to play again. But the way it is currently written, it doesn't tell you anything you didn't already know. You could have just skipped the function and written:
1 2
|
cin >> game;
if (game) main();
|
(Don't do that with main(), BTW. It is illegal in C++ and very bad karma otherwise --like running around with a sharp knife in your hand. Sooner or later you or someone else will get cut.)
Another thing is that you are using
int for boolean values, when C++ provides you with a
bool type. Always use types to improve clarity.
So, with that preamble, I'll help you refine your design goals and you can start fixing things up. Let's start with the over-all structure.
main()
This is the "controller" of the program. It doesn't actually run the game --we'll palm that off to another function. What it does is greet the user, initialize things, call the function that runs the game, tell the user who won and who lost (and keep track of how many times each), and ask the user if he/she wants to play again.
We'll also have to define the way the gameboard is represented to the user. I'll say that we do it naturally for people, and number rows and columns 1..3. We'll just subtract one from whatever they give us to access the actual item.
We'll store the gameboard the same way you did (nice job, BTW), as a 3 x 3 array of char, with values ' ', 'X', or 'O'.
Let's write that out in a simple version of code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
#include <iostream>
using namespace std;
// This defines who we have playing:
enum players { draw, player1, player2 };
int main()
{
// This will only display when the program is first run
cout << "You, are about to witness the program of the century.\n\n";
// This tracks the number of times each player has won.
int number_of_wins[ sizeof( players ) ] = {0};
// And this tells us whether or not to play again.
bool done = false;
while (!done)
{
// This will display before each game
cout << "COMMENCE TIC TAC TOE!!!!\n\n"
"Ladies first, please pick the row then the column (1 through 3).\n\n";
// Play a game and remember who won (if anyone)
int winner = playgame();
// Update it
number_of_wins[ winner ]++;
// Display it
display_winner_stats( number_of_wins, winner );
done = ask_to_play_again();
}
// Finish
cout << "\n\nThank you for playing!\n";
return 0;
}
|
Well, I've given you that... Now that we've got top-level stuff at a good idea state, let's flesh-out some of those functions we made-up.
playgame()
This function actually plays a game. It runs until either someone wins or until there are no more moves (and a draw occurs).
It displays the current gameboard, asks each player for his move in turn (and keeps asking until he enters a valid one), updates the gameboard, looks for a winner, and if none, repeats (suggesting another loop). Before returning, it displays the gameboard one more time (so the players can see the winning move).
It returns who won as an integer value of
draw,
player1, or
player2.
(Notice how more functions were suggested: your
progress() and
winlose() and
check, etc. Don't worry about how they work inside, figure out what they should do for
this function--what they should return and what arguments they need to do it.
display_winner_stats()
Does what it says. Congradulates the winner and also tells how many times each player has won and how many draws there were.
ask_to_play_again()
Does what it says. Asks the user if he/she wants to play again and returns a boolean value:
true if yes and
false if no.
Notice how we can keep things simple by considering it abstractly from the top. (This is called the "top-down" approach.)
Whew. I've got to get some sleep. I'll help more later.