cant seem to get players decision working - tictactoe

Started by
10 comments, last by Zahlman 14 years, 10 months ago
This feels like a dumb logical error that im missing, but I cannot seem to figure it out at the moment. I have a 2d array that is filled with 1-9 as a tic tac toe board. I loop through it with two for loops, and compare the number the user entered in with, with the value. However, this if statement to set the new value of the board does not ever meet a condition. It would be at the end of TakeATurn function Heres my code:

#include <iostream>
#include <string>
#include <vector>
#include <sstream>

typedef std::string TicTacToeBoard[3][3];

class Game 
{
public:
	Game(){}
	
	void FillTheBoard();
	void DrawBoard();
	void StartGame();
	void TakeATurn();
	void SetIsPlaying(bool isPlaying);
	void CheckForAWinner();
	void GiveInstructions();
	bool CheckAvailability(int place);
	void ComputerTakeTurn();

private:
	TicTacToeBoard theBoard;
	bool m_isPlaying;
};

void Game::StartGame() 
{
	std::cout << "Welcome to another Tic-Tac-Toe Clone!\n";
	std::cout << "To play: specify the space in the board where you wish to place your move\n";
	FillTheBoard();
	GiveInstructions();
	do
	{
		TakeATurn();
		//ComputerTakeTurn();
		DrawBoard();
		CheckForAWinner();
	} while(m_isPlaying);
}

void Game::FillTheBoard()
{
	int counter = 1;
	for(int i = 0; i < 3; i++)
	{
		for(int j = 0; j < 3; j++)
		{
			std::stringstream stm;
			stm << counter;
			theBoard[j] = stm.str();
			counter++;
		}
	}
}
void Game::DrawBoard()
{
	std::cout << "\n " << theBoard[0][0] << " | " << theBoard[0][1] << " | " << theBoard[0][2] << " " << "\n";
	std::cout << "-----------\n";
	std::cout << " " << theBoard[1][0] << " | " << theBoard[1][1] << " | " << theBoard[1][2] << " " << "\n";
	std::cout << "-----------\n";
	std::cout << " " << theBoard[2][0] << " | " << theBoard[2][1] << " | " << theBoard[2][2] << " " << "\n";
}

void Game::SetIsPlaying(bool isPlaying)
{
	m_isPlaying = isPlaying;
}

void Game::TakeATurn()
{
	bool validSpot = false;
	int placeAt = 0;
	do 
	{
		std::cout << "Please specify a value of where you wish to place X\n";
		std::string input;
		std::getline(std::cin, input);
		int placeAt = atoi(input.c_str());
		validSpot = CheckAvailability(placeAt);
		if(!validSpot)
		{
			std::cout << "Please enter a spot that has not been taken yet.\n";
		}
	} while(((placeAt < 1) && (placeAt > 9)) || !validSpot);

	// add the user's choice to the board
	for(int i = 0; i < 3; i++)
	{
		for(int j = 0; j < 3; j++)
		{
			if(atoi(theBoard[j].c_str()) == placeAt) 
			{
				theBoard[j] = "X";
			}
		}
	}	
}

void Game::CheckForAWinner() 
{

}

void Game::GiveInstructions() 
{
	std::cout << "To put a piece at the first spot on row 1, type 1. For the next one, type 2, than 3.\n";
	std::cout << "For the second row, first one type 4, the second one 5, and etc.\n";
	std::cout << "such as below:\n";
	DrawBoard();
}

bool Game::CheckAvailability(int place)
{
	bool isAvailable = false;
	for(int i = 0; i < 3; i++)
	{
		for(int j = 0; j < 3; j++)
		{
			if(atoi(theBoard[j].c_str()) == place) 
			{
				isAvailable = true;
			}
		}
	}
	return isAvailable;
}

void Game::ComputerTakeTurn() 
{
	for(int i = 0; i < 3; i++)
	{
		for(int j = 0; j < 3; j++)
		{
			if(theBoard[j] != "X") 
			{
				theBoard[j] = "O";
				break;
			}
		}
	}
}

int main() 
{
	Game g;
	g.StartGame();
}


Advertisement
Edit: I need to read the code a little better, =p

if(atoi(theBoard[j].c_str()) == place)

your checking the string if its equal to a int, if the previous section you take the string and convert it to a int, as the poster below said this is probably the cause of your problem.

[Edited by - yewbie on June 20, 2009 7:26:51 PM]
just as a question why are you bothering with atoi? surely you can compare all the required characters as strings instead of converting some to int. I'm a noob but that seems to add an unnecessary level of complexity to the code that could be causing your issue. Please do explain your reason I would love to know.
tbh, i really dont know lol. I guess it just kind of made sense that they enter a number placement of where to put it, so i put the variable types as integers.

But yeah, I fixed it now. I think something was wrong with my CheckAvailability()

No, (placeAt > 1) && (placeAt < 9) is wrong. Basically it's a loop that checks to see if the user's input is valid. If it's not, it continues. But the while statement is wrong. You should be using ||, not &&, so it should be (placeAt < 1) || (placeAt > 9) || !validSpot.

The rest looks ok, but you should seriously reconsider you usage of atoi. Why do you set each board tile equal to it's numerical number? You have a design flaw, but I'm too rushed to help more. I'd be happy to later.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
Thanks mike.

I initially had them all set to a hyphen. Then i decided to populate them with their value, rather than have another function that displays the instruction board (shows all the numbers so the user know what one to type). It's also easier to have an if statement to check values, rather than coordinate the one number they enter with the 2 dimensional array (at least I think so anyways).
Quote:Original post by agm_ultimatex
Thanks mike.

I initially had them all set to a hyphen. Then i decided to populate them with their value, rather than have another function that displays the instruction board (shows all the numbers so the user know what one to type). It's also easier to have an if statement to check values, rather than coordinate the one number they enter with the 2 dimensional array (at least I think so anyways).

You can have their numbers there and still not use atoi. If a space has been used, it will be either 'X' or 'O'. So you can just do theBoard[j] == "X" || theBoard[j] == "O" and get rid of messy atoi-ness.
[size=2][ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]
yeah i did, it is a lot nicer now actually. Currently trying to think of the best way to determine a winner. I made a local array of integers storing all the possible winning scenarios. Its an 8x6 due to the fact 2 numbers determine a spot on the board, and there are 8 possible ways to win. However, im trying to get my head around how to loop through it, as a nested for loop will only bring back 1 number per iteration, i need 2. I realize I can probably store it, but I imagine there's a better way.

Heres my CheckForWinner() function as is, and the rest of the code afterwards

void Game::CheckForAWinner() {	int winningCombos[8][6] = {		{0, 0, 0, 1, 0, 2}, 		{1, 0, 1, 1, 1, 2},		{2, 0, 2, 1, 2, 2},		{0, 0, 1, 0, 2, 0},		{0, 1, 1, 1, 2, 1}, 		{0, 2, 1, 2, 2, 2},		{0, 0, 1, 1, 2, 2},		{0, 2, 1, 1, 2, 0}	}; }


#include <iostream>#include <string>#include <vector>#include <sstream>typedef std::string TicTacToeBoard[3][3];class Game {public:	Game(){}		void FillTheBoard();	void DrawBoard();	void StartGame();	void TakeATurn();	void SetIsPlaying(bool isPlaying);	void CheckForAWinner();	void GiveInstructions();	bool CheckAvailability(std::string place);	void ComputerTakeTurn();private:	TicTacToeBoard theBoard;	bool m_isPlaying;};void Game::StartGame() {	std::cout << "Welcome to another Tic-Tac-Toe Clone!\n";	std::cout << "To play: specify the space in the board where you wish to place your move\n";	FillTheBoard();	GiveInstructions();	do	{		TakeATurn();		ComputerTakeTurn();		DrawBoard();		CheckForAWinner();	} while(m_isPlaying);}void Game::FillTheBoard(){	int counter = 1;	for(int i = 0; i < 3; i++)	{		for(int j = 0; j < 3; j++)		{			std::stringstream stm;			stm << counter;			theBoard[j] = stm.str();			counter++;		}	}}void Game::DrawBoard(){	std::cout << "\n " << theBoard[0][0] << " | " << theBoard[0][1] << " | " << theBoard[0][2] << " " << "\n";	std::cout << "-----------\n";	std::cout << " " << theBoard[1][0] << " | " << theBoard[1][1] << " | " << theBoard[1][2] << " " << "\n";	std::cout << "-----------\n";	std::cout << " " << theBoard[2][0] << " | " << theBoard[2][1] << " | " << theBoard[2][2] << " " << "\n";}void Game::SetIsPlaying(bool isPlaying){	m_isPlaying = isPlaying;}void Game::TakeATurn(){	bool validSpot = false;	std::string input;	do 	{		std::cout << "Please specify a value of where you wish to place X\n";				std::getline(std::cin, input);		validSpot = CheckAvailability(input);		if(!validSpot)		{			std::cout << "Please enter a spot that has not been taken yet.\n";		}	} while (((atoi(input.c_str()) < 1) || (atoi(input.c_str()) > 9)) || !validSpot);	// add the user's choice to the board	for(int i = 0; i < 3; i++)	{		for(int j = 0; j < 3; j++)		{			if(theBoard[j] == input) 			{				theBoard[j] = "X";			}		}	}	}void Game::CheckForAWinner() {	int winningCombos[8][6] = {		{0, 0, 0, 1, 0, 2}, 		{1, 0, 1, 1, 1, 2},		{2, 0, 2, 1, 2, 2},		{0, 0, 1, 0, 2, 0},		{0, 1, 1, 1, 2, 1}, 		{0, 2, 1, 2, 2, 2},		{0, 0, 1, 1, 2, 2},		{0, 2, 1, 1, 2, 0}	}; }void Game::GiveInstructions() {	std::cout << "To put a piece at the first spot on row 1, type 1. For the next one, type 2, than 3.\n";	std::cout << "For the second row, first one type 4, the second one 5, and etc.\n";	std::cout << "such as below:\n";	DrawBoard();}bool Game::CheckAvailability(std::string place){	bool isAvailable = false;	for(int i = 0; i < 3; i++)	{		for(int j = 0; j < 3; j++)		{			if(theBoard[j] == place) 			{				isAvailable = true;			}		}	}	return isAvailable;}void Game::ComputerTakeTurn() {	for(int i = 0; i < 3; i++)	{		for(int j = 0; j < 3; j++)		{			if(theBoard[j] != "X" && theBoard[j] != "O") 			{				theBoard[j] = "O";				break;			}		}		break;	}}int main() {	Game g;	g.StartGame();}

for (i = 0; i &lt; 3; i++){   if (board[0] == "X" && board[1] == "X" && board[2] == "X")      playerWins = true;}for (i = 0; i &lt; 3; i++){   if (board[0] == "X" && board[1] == "X" && board[2] == "X")      plyaerWin = true;}if (board[0][0] == "X" && board[1][1] == "X" && board[2][2] == "X")   playerWin = true;if (board[0][2] == "X" && board[1][1] == "X" && board[2][0] == "X")   playerWin = true;


then change conditions for "O" win for the computer and run it again
Thanks, that works.

Heres my finished code (it seems impossible to lose, id like to actually have an smart computer for this rather than just putting an O in the first available spot). Feel free to comment for suggestions on how to improve it and so forth practice wise and what not. I mainly did this as a quick test, as I have done more complicated games than this before.

#include <iostream>#include <string>#include <vector>#include <sstream>typedef std::string TicTacToeBoard[3][3];class Game {public:	Game(){}		void FillTheBoard();	void DrawBoard();	void StartGame();	void TakeATurn();	void SetIsPlaying(bool isPlaying);	bool IsThereAWinner();	void GiveInstructions();	bool CheckAvailability(std::string place);	void ComputerTakeTurn();	void PlayAgain();private:	TicTacToeBoard theBoard;	bool m_isPlaying;};void Game::StartGame() {	std::cout << "Welcome to another Tic-Tac-Toe Clone!\n";	std::cout << "To play: specify the space in the board where you wish to place your move\n";	FillTheBoard();	GiveInstructions();	do	{		bool gameInPlay = true;		int iterations = 0;		do		{			TakeATurn();			// the user can only put up to 5 times, so count it			iterations++; 			ComputerTakeTurn();			DrawBoard();			gameInPlay = IsThereAWinner();		} while(gameInPlay || iterations == 5);		if(iterations == 5 && gameInPlay)		{			std::cout << "Stalemate!\n";		}		PlayAgain();	}while(m_isPlaying);}void Game::FillTheBoard(){	int counter = 1;	for(int i = 0; i < 3; i++)	{		for(int j = 0; j < 3; j++)		{			std::stringstream stm;			stm << counter;			theBoard[j] = stm.str();			counter++;		}	}}void Game::DrawBoard(){	std::cout << "\n " << theBoard[0][0] << " | " << theBoard[0][1] << " | " << theBoard[0][2] << " " << "\n";	std::cout << "-----------\n";	std::cout << " " << theBoard[1][0] << " | " << theBoard[1][1] << " | " << theBoard[1][2] << " " << "\n";	std::cout << "-----------\n";	std::cout << " " << theBoard[2][0] << " | " << theBoard[2][1] << " | " << theBoard[2][2] << " " << "\n";}void Game::SetIsPlaying(bool isPlaying){	m_isPlaying = isPlaying;}void Game::TakeATurn(){	bool validSpot = false;	std::string input;	do 	{		std::cout << "Please specify a value of where you wish to place X\n";				std::getline(std::cin, input);		validSpot = CheckAvailability(input);		if(!validSpot)		{			std::cout << "Please enter a spot that has not been taken yet.\n";		}	} while (((atoi(input.c_str()) < 1) || (atoi(input.c_str()) > 9)) || !validSpot);	// add the user's choice to the board	for(int i = 0; i < 3; i++)	{		for(int j = 0; j < 3; j++)		{			if(theBoard[j] == input) 			{				theBoard[j] = "X";			}		}	}	}bool Game::IsThereAWinner() {	/*int winningCombos[8][6] = {		{0, 0, 0, 1, 0, 2}, 		{1, 0, 1, 1, 1, 2},		{2, 0, 2, 1, 2, 2},		{0, 0, 1, 0, 2, 0},		{0, 1, 1, 1, 2, 1}, 		{0, 2, 1, 2, 2, 2},		{0, 0, 1, 1, 2, 2},		{0, 2, 1, 1, 2, 0}	}; */		bool playerWins = false;	bool computerWins = false;	for (int i = 0; i < 3; i++)	{		if (theBoard[0] == "X" && theBoard[1] == "X" && theBoard[2] == "X")		{			playerWins = true;		}	}	for (int i = 0; i < 3; i++)	{		if (theBoard[0] == "X" && theBoard[1] == "X" && theBoard[2] == "X")		{			playerWins = true;		}	}	if (theBoard[0][0] == "X" && theBoard[1][1] == "X" && theBoard[2][2] == "X")	{		playerWins = true;	}	else if (theBoard[0][2] == "X" && theBoard[1][1] == "X" && theBoard[2][0] == "X")	{			playerWins = true;	}	// checks if computer won	for (int i = 0; i < 3; i++)	{		if (theBoard[0] == "O" && theBoard[1] == "O" && theBoard[2] == "O")		{			computerWins = true;		}	}	for (int i = 0; i < 3; i++)	{		if (theBoard[0] == "O" && theBoard[1] == "O" && theBoard[2] == "O")		{			computerWins = true;		}	}	if (theBoard[0][0] == "O" && theBoard[1][1] == "O" && theBoard[2][2] == "O")	{		computerWins = true;	}	else if (theBoard[0][2] == "O" && theBoard[1][1] == "O" && theBoard[2][0] == "O")	{			computerWins = true;	}	if(playerWins) 	{		std::cout << "You won the game!\n";		return false;	}	else if(computerWins)	{		std::cout << "The computer beat you, too bad :( \n";		return false;	}	else	{		return true;	}}void Game::GiveInstructions() {	std::cout << "To put a piece at the first spot on row 1, type 1. For the next one, type 2, than 3.\n";	std::cout << "For the second row, first one type 4, the second one 5, and etc.\n";	std::cout << "such as below:\n";	DrawBoard();}bool Game::CheckAvailability(std::string place){	bool isAvailable = false;	for(int i = 0; i < 3; i++)	{		for(int j = 0; j < 3; j++)		{			if(theBoard[j] == place) 			{				isAvailable = true;			}		}	}	return isAvailable;}void Game::ComputerTakeTurn() {	for(int i = 0; i < 3; i++)	{		for(int j = 0; j < 3; j++)		{			if(theBoard[j] != "X" && theBoard[j] != "O") 			{				theBoard[j] = "O";				i = 3;				j = 3;			}		}	}}void Game::PlayAgain(){	std::string ans;	do	{		std::cout << "Play again?y/n\n";		std::getline(std::cin, ans);	} while(ans != "n" && ans != "N" && ans != "y" && ans != "Y");	if(ans == "n" || ans == "N")	{		m_isPlaying = false;	}	else	{		FillTheBoard();	}}int main() {	Game g;	g.StartGame();}

This topic is closed to new replies.

Advertisement