Jump to content

Bugs in my Tic Tack Toe game

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
11 replies to this topic

#1
nicckk

nicckk

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 629 posts
Hi CodeCall.

I coded a little text based Tick Tack Toe game today and I have a few bugs with it. The rules are fairly simple:

Player one must move first
Player one uses X
Player two uses O
The game is over when you get three in a row.

The only problem is on the first run though of the game it acts differentally. Instead of asking for player ones move it asks for player 49's, and player 49 starts with O, then it moves to player 2 with X, then back to player one O. But then if you decide to start a new game, it runs the way it should. Heres my code,

#include <iostream>

using namespace std;


int main()

{

    char cSquare1('1');

    char cSquare2('2');

    char cSquare3('3');

    char cSquare4('4');

    char cSquare5('5');

    char cSquare6('6');

    char cSquare7('7');

    char cSquare8('8');

    char cSquare9('9');

    int iPlayerTurn('1');

    bool bGameOver('true');

    

    do {

        

        cout << cSquare1 << "|" << cSquare2 << "|" << cSquare3 << "\n";

        cout << "-+-+-+\n";

        cout << cSquare4 << "|" << cSquare5 << "|" << cSquare6 << "\n";

        cout << "-+-+-+\n";

        cout << cSquare7 << "|" << cSquare8 << "|" << cSquare9 << "\n";

        

        char cPlayerMark;

        if(iPlayerTurn == 1) {

           cPlayerMark = 'X';

        } else {

               cPlayerMark = 'O';

        }

        

        cout << "Player " << iPlayerTurn << "'s move";

        bool bValidMove;

        do {

            char cNextMove;

            cin >> cNextMove;

            bValidMove = true;

            

 			if (cNextMove == '1' && cSquare1 == '1') {

				cSquare1 = cPlayerMark;

			} else if (cNextMove == '2' && cSquare2 == '2') {

				cSquare2 = cPlayerMark;

			} else if (cNextMove == '3' && cSquare3 == '3') {

				cSquare3 = cPlayerMark;

			} else if (cNextMove == '4' && cSquare4 == '4') {

				cSquare4 = cPlayerMark;

			} else if (cNextMove == '5' && cSquare5 == '5') {

				cSquare5 = cPlayerMark;

			} else if (cNextMove == '6' && cSquare6 == '6') {

				cSquare6 = cPlayerMark;

			} else if (cNextMove == '7' && cSquare7 == '7') {

				cSquare7 = cPlayerMark;

			} else if (cNextMove == '8' && cSquare8 == '8') {

				cSquare8 = cPlayerMark;

			} else if (cNextMove == '9' && cSquare9 == '9') {

				cSquare9 = cPlayerMark;

			} else {

			cout << "Invalid Move. Try again.";

			bValidMove = false;

			}

		} while (!bValidMove);

        

        		bGameOver		= false;

		bool bWinGame	= true;

		// Check for end of game conditions

		if (cSquare1 != '1') {

			if (cSquare2 == cSquare1 && cSquare3 == cSquare1) {

				bGameOver = true;

			}

			if (cSquare4 == cSquare1 && cSquare7 == cSquare1) {

				bGameOver = true;

			}

		}

		if (cSquare5 != '5') {

			if (cSquare1 == cSquare5 && cSquare9 == cSquare5) {

				bGameOver = true;

			}

			if (cSquare2 == cSquare5 && cSquare8 == cSquare5) {

				bGameOver = true;

			}

			if (cSquare4 == cSquare5 && cSquare6 == cSquare5) {

				bGameOver = true;

			}

			if (cSquare3 == cSquare5 && cSquare7 == cSquare5) {

				bGameOver = true;

			}

		}

		if (cSquare9 != '9') {

			if (cSquare3 == cSquare9 && cSquare6 == cSquare9) {

				bGameOver = true;

			}

			if (cSquare7 == cSquare9 && cSquare8 == cSquare9) {

				bGameOver = true;

			}

		}

		// Need to check the board full (no-win condition)

		if (cSquare1 != '1' && cSquare2 != '2' && cSquare3 != '3' &&

			cSquare4 != '4' && cSquare5 != '5' && cSquare6 != '6' &&

			cSquare7 != '7' && cSquare8 != '8' && cSquare9 != '9' && !bGameOver)

		{

			bGameOver = true;

			bWinGame = false;

		}


		if (bGameOver) {

			if (bWinGame) {

				std::cout << "Player" << iPlayerTurn << " wins!" << std::endl;

			}

			system("CLS");


			std::cout << "Game Over!" << std::endl;

			std::cout << "Play again (y/n)?" << std::endl;

			char cPlayAgain;

			std::cin >> cPlayAgain;

            system("CLS");

			if (cPlayAgain == 'y') {

				bGameOver = false;

				// Clear the board

				cSquare1 = '1';

				cSquare2 = '2';

				cSquare3 = '3';

				cSquare4 = '4';

				cSquare5 = '5';

				cSquare6 = '6';

				cSquare7 = '7';

				cSquare8 = '8';

				cSquare9 = '9';

			}

			iPlayerTurn = 1;

		} else {

			// Alternate player turns

			if (iPlayerTurn == 1) {

				iPlayerTurn = 2;

			} else {

				iPlayerTurn = 1;

			}

		}

	} while (!bGameOver);

}




#2
dcs

dcs

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 775 posts
I think you're a little bit overzealous with single-quotes here:
    int iPlayerTurn('1');
    bool bGameOver('true');


#3
nicckk

nicckk

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 629 posts
I dont see how to single quote can mess with the player turn or the bool, unless im missing somthing?

#4
ZekeDragon

ZekeDragon

    Writes binary right handed and hex left handed

  • Moderators
  • 2,103 posts
The single quotes tell the compiler that it's a character. Since true and 1 are not characters (they're being saved as a bool and an int, respectively), then the code "int iPlayerTurn(1); bool bGameOver(true);" should work.

Also, system() requires <cstdlib>.
Wow I changed my sig!

#5
nicckk

nicckk

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 629 posts
Ah, thanks dcs and Zeke.

What a stupid error I made.

#6
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,715 posts
Do you know Perl, by any chance? That seems like a Perl-ish thing to do.
sudo rm -rf /

#7
nicckk

nicckk

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 629 posts

dargueta said:

Do you know Perl, by any chance? That seems like a Perl-ish thing to do.

I dont know Perl, I guess Im just a noob at C++:D

#8
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,715 posts
Perl doesn't have characters, only strings, so the single quote is used to indicate a non-interpreted string, while double quotes are to indicate interpreted strings. For example:

my $var = 'Hello';

print "$var, World!\n"; #note this is double quoted - interpreted string
print '$var, World!\n';  #note this is single quoted - not interpreted

The output is:
Hello, World!
$var, World!\n

sudo rm -rf /

#9
veda87

veda87

    Programmer

  • Members
  • PipPipPipPip
  • 126 posts
Can anyone tell me the difference between char cSquare1('1'); and char cSquare1 = '1';
also the diff between int iPlayerTurn('1'); and int iPlayerTurn = 1;

Do these syntax mean the same or is there any advantage or disadvantage of using former over the latter.....

#10
ZekeDragon

ZekeDragon

    Writes binary right handed and hex left handed

  • Moderators
  • 2,103 posts
Well, char cSquare1('1'); and char cSquare1 = '1'; has no functional difference in most situations. The difference to the compiler is what order things happen, with the former initializing the char data type with a value on '1', while the latter creates a blank char and assigns it '1'. In most situations, they're functionally identical (and may even produce the same assembly code), but with classes they become different. Many classes have some const members, and in those situations you need to use an initializer list that uses exclusively the former syntax:
class myClass {
    const int i;
public:
    myClass() : i(1) // i = 1 will NOT work
    {
        // i = 1; or i(1); here will also NOT work.
    }
};
You also need to use this syntax with inheritance, so it's generally a good idea to use it. But as far as I know in the other situation, there's no functional difference.
Wow I changed my sig!

#11
dcs

dcs

    Programming God

  • Members
  • PipPipPipPipPipPipPip
  • 775 posts

veda87 said:

Can anyone tell me the difference between char cSquare1('1'); and char cSquare1 = '1';
also the diff between int iPlayerTurn('1'); and int iPlayerTurn = 1;
Note that 1 is not the same as '1'.
#include <iostream>

int main()
{
   int a(1), b('1'), c = 1, d = '1';
   std::cout << "a = " << a << "\n";
   std::cout << "b = " << b << "\n";
   std::cout << "c = " << c << "\n";
   std::cout << "d = " << d << "\n";
   return 0;
}

/* my output
a = 1
b = 49
c = 1
d = 49
*/


#12
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,715 posts
I've seen people try to extend that concept this way, and then they wonder why it doesn't work.

class X {
protected:
    //this will break.
    int blah(5);
    //this will break as well.
    Y z(false, "Hello, World" );
public:
    X(void);
    ~X(void);
};

Your problem here is that the compiler thinks that you're declaring a function called blah that returns an integer. When it sees the 5 passed in as an argument--which it's not expecting--it chokes and throws an error. Same for the Y class. It thinks you're declaring a function called z that returns a Y, but then it sees arguments instead of type names and chokes again.

Nice catch by the way, dcs.
sudo rm -rf /