Advertisement

SFML tick tack toe help

Started by May 28, 2014 06:21 AM
8 comments, last by Evan Gordon 10 years, 8 months ago

ok, so i'm just about done with my simple crappy tick tack toe game, however i'm running into a problem that i just cant seem to fix when the game reaches the last turn (note: as of right now the game doesn't check for victory at all, the player chooses and then the computer chooses) for some reason on turn 9 when the player is trying to make his final move the game just kinda gets stuck near the bottom of main, when the event for mouse being clicked is polled, the function call for the button class, well, it just just sits there. i'm not really sure why, and the debugging menu is just confusing me more right now. i know my problem is probably extremely stupid, but i'm still a noob so i hope you can fogive me, any advice on my predicament would be appreciated.



//global var for counting when a turn for the computer or player has passed
int globalturns = 0;


//mutex makes locked data only able to be accessed by one thread
// sf::Mutex mutex;

// class that determines if a sprite is drawn or not, and is used to draw the right sprites
class Drawn
{
private:
	int state = 0;
	sf::Sprite buttonpressed, button, compo;
	// sf::Sprite hovored  use for later
	float buttonh, buttonw;
	sf::Vector2f location1;
public:
	

	int getState()
	{
		return state;
	}
	void setState(int sstate)
	{
		state = sstate;
	}
	//button function, must edit
	bool V2i_inRange(sf::Vector2i a)
	{

		sf::Vector2i mousePos=a;
		if (location1.x + buttonw >= mousePos.x && location1.y + buttonh >= mousePos.y && state == 0)
			if (location1.x <= mousePos.x && location1.y <= mousePos.y)
			{
				state = 3;
				globalturns++;

				return true;
			}
			else
			{
				return false;
			}
			else
			{
				return false;
			}
	}
	void setbutton(sf::Sprite pressed, sf::Sprite butto, sf::Sprite comp, sf::Vector2f location)
	{
		location1 = location;
		buttonpressed = pressed;
		button = butto;
		compo = comp;
		buttonh = butto.getGlobalBounds().height;
		buttonw = butto.getGlobalBounds().width;
		button.setPosition(location);
		buttonpressed.setPosition(location);
		compo.setPosition(location);
		
	}
	

	sf::Sprite draw()
	{
		if (state==3)
		{
			return buttonpressed;
		}
		else if (state==4)
		{
			return compo;
		}
		else
		{
			return button;
		}
	}
	


};

//function that generates turn for computer
int randomChoice()
{
	unsigned int choice=0;
	choice = rand() % 9;
	return choice;

};

void computerChoice(Drawn arr[])
{
	if (globalturns < 9)
	{
		bool found = false;
		unsigned int choice = 0;
		choice = randomChoice();
		while (found == false)
		{
			if (arr[choice].getState() == 0)
			{
				found = true;
				arr[choice].setState(4);
				globalturns++;
				return;
			}
			else
			{
				choice = randomChoice();
			}

		}
	}
	return;

}
int main()
{
	srand(time(NULL)); //rand numb
	Drawn butt[10];	  //arraw of buttons
	sf::RenderWindow window;
	sf::Clock clock;
	sf::Time t1;
	float secon=0;
	window.create(sf::VideoMode(800, 600, 32), "Loading...", sf::Style::Default);
	while (secon<1)
	{
		t1 = clock.getElapsedTime();
		secon = t1.asSeconds();
	}
	sf::Font font;
	if (!font.loadFromFile("Medici Text.ttf"))
		{
		cout << "Error loading file :(\n";
		}
	window.setVerticalSyncEnabled(true);

	//Position var of mouse
	sf::Vector2i mousePosition;
	
	//Graphic add
	sf::Texture ttt;
	sf::Sprite gameb, x1,o1;
	if (!ttt.loadFromFile("tttsprite.png"))
	{
		std::cout << "Sorry, bro your sprites didnt load/n";
	}
	sf::Texture button;
	sf::Sprite button1;
	if (!button.loadFromFile("norm.png"))
	{
		std::cout << "you be buttonless foo!";
	}
	gameb.setTexture(ttt);
	gameb.setPosition(150, 100);


	//sprites for X's and O's
	x1.setTexture(ttt);
	x1.setScale(0.75f, 0.75f);
	x1.setTextureRect(sf::IntRect(35, 88, 54, 54));
	x1.setColor(sf::Color(255, 255, 255, 128));
	o1.setTexture(ttt);
	o1.setScale(0.75f, 0.75f);
	o1.setTextureRect(sf::IntRect(35, 192, 54, 56));
	o1.setColor(sf::Color(255, 255, 255, 128));
	
	 //make buttons for where player will click to add x
	button1.setTexture(button);
	button1.setScale(0.5f, 0.5f);
	button1.setPosition(310, 180);
	
	//array of button locations
	sf::Vector2f arrayl[9];
	arrayl[0] = { 310, 180 };
	arrayl[1] = { 370, 180 };
	arrayl[2] = { 430, 180 };
	arrayl[3] = { 310, 240 };
	arrayl[4] = { 370, 240 };
	arrayl[5] = { 430, 240 };
	arrayl[6] = { 310, 300 };
	arrayl[7] = { 370, 300 };
	arrayl[8] = { 430, 300 };

	//assigning values to the array of Drawn buttons
	for (int n = 0; n < 9; n++)
	{
		butt[n].setbutton(x1, button1, o1, arrayl[n]);
	}

		
			
		
	sf::Text text;
	text.setFont(font);
	text.setString("Press any key to continue");
	text.setCharacterSize(32);
	text.setColor(sf::Color::Red);
	//text.setStyle(sf::Text::Bold);

	
	text.setString("Welcome to Basic Tick Tack Toe 2.0!");

	window.setTitle("Tick Tack Toe 2.0");

	text.setCharacterSize(32);

	sf::Music theme;
	theme.setVolume(50);
	theme.setLoop(true);
	if (!theme.openFromFile("theme.ogg"))
	{
		std::cout << "Poor you, your theme won't play :(/n";
	}
	theme.play();

	//Main Program	 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	while (window.isOpen())
	{
		sf::Event event;
		while (globalturns < 9)
		{

			while (window.pollEvent(event))
			{
				switch (event.type)
				{
				case sf::Event::Closed:
					window.close();
					break;
				case sf::Event::KeyPressed:
					break;
				case sf::Event::MouseButtonPressed:
					if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
					{
						// left mouse button is pressed: is it in range of button
						// get position of mouse, pass to button class for each button
						mousePosition = sf::Mouse::getPosition(window);
						bool pressed = false;
						for (int n = 0; n < 9; n++)
						{
							cout << n << endl;
							if (globalturns < 9)
							{
//problem occurs over here----
								pressed = butt[n].V2i_inRange(mousePosition);
							}
							if (pressed)
							{
								n = 9;
							}
						}
						if (globalturns<9)
							{
								if (pressed)
								{
									computerChoice(butt);
									pressed = false;
								}
							}
						else
						{
							break;
						}
					}
					break;
				case sf::Event::MouseMoved:
					break;
				default:
					break;
				}




			}
			window.clear(sf::Color::Red);
			window.draw(text);
			window.draw(gameb);
			for (int n = 0; n < 9; n++)
			{
				window.draw(butt[n].draw());

			}

			window.display();
		}

	}



	cout << "The game is over!";
	return 0;
}

Hey, it's likely that in your for loop (in main where you say the problem is occurring), it's looping through it ten times (0 -9) though it appears you may only want it to go through 9 times. Try changing it to "n < 8" and see if that fixes things. I have to admit I haven't taken a close look at the code, but that seems like the likely culprit. If not, I'll take a closer gander.

Cheers,

smile.png

Edit**

nevermind, on a closer look that doesn't seem to be a problem.

Beginner here <- please take any opinions with grain of salt

Advertisement

Hey, it's likely that in your for loop (in main where you say the problem is occurring), it's looping through it ten times (0 -9) though it appears you may only want it to go through 9 times. Try changing it to "n < 8" and see if that fixes things. I have to admit I haven't taken a close look at the code, but that seems like the likely culprit. If not, I'll take a closer gander.

Cheers,

smile.png

Edit**

nevermind, on a closer look that doesn't seem to be a problem.

hey thanks anyways for trying! any imput is appreciated, it gets the ideas flowing, ive been sitting here staring at these lines for way too long trying to catch this nastly little bugger.

Wait, actually, I was close, or more specifically it's your globalturns variable. It's set to 0 to start, and runs through 10 turns, if that makes sense. So, in your if statement, when you set


if (globalturns < 9)

That's actually asking for ten turns (0-9). I'm going to go out on a limb and guess that tic-tac-toe only has 9 turns tongue.png So, your program is waiting around for a turn that never arrives.

And, that should be why it's getting stuck on the last turn.

Set those to 8, or initialize globalturns with a value of 1 and you should be good.

Cheers,

smile.png

Beginner here <- please take any opinions with grain of salt

see thats what ive thought, but originally i had globalturns set to 1. but when this is the case it wont let me take the last turn, and then gets stuck in relatively the same position

Eh, I was wrong again anyhow. I'm used to using "<=" in my loops and wasn't paying enough attention (sorry!). So, you're correct already in doing "globalturns < 9) as that actually still is 0-8 (9 turns).

Sadly, I'm late for work and out of ideas at the moment. Perhaps try adding a victory condition, or at least an "else" to your if statement in that section, as if your globalturns == 9, then your loop is doing nothing. You could try debugging it with a few "std::cout<<"stuffhere""<<std::endl; statements placed throughout portions of that section to try to pin down what's actually going on. I know that's not the most helpful advice at this point, but it's

Hopefully someone with more knowledge than I can swoop in here and help you in the meantime smile.png

The last thing I can think of, is that when it calls that last button push, that function (pressed = butt[n].V2i_inRange(mousePosition);)pushes your globalturns to 9, which makes next segment now untrue and it doesn't run:


if (globalturns<9)
							{
								if (pressed)
								{
									computerChoice(butt);
									pressed = false;
								}
							}

so, on your last turn it's not running this portion? I'd have to check more carefully, but again, I'm running late already and can't really examine it.

Good luck! I'll take a gander this evening if someone else hasn't solved it in the meantime.

Beginner here <- please take any opinions with grain of salt

Advertisement

if 9 turns have gone by then it shouldnt be going into there because every space is taken... as long as im not mistaken. i dont know, hour more spent and i still cant find this stupid bug

So, on your last turn,

pressed = butt[n].V2i_inRange(mousePosition);
will push your globalturns to 9. This is breaking your while loop above:

while (globalturns < 9)
which pushes you out of the loop. But, this is nested within your

while (window.isOpen())
So, unless I'm reading this wrong (which after several embarassing tries here, is entirely possible tongue.png ) you're still within the while window is open loop, but not running any other code.
You'll need to add something outside of the "globalturns < 9" loop that closes the window, shows a win/loss screen, anything etc. Right now, your global turns is too high for anything inside the other loop to run but you're still within the

while(Window.isOpen())

so it's not returning "0" yet and closing the program, and you've given your program nothing else to do while in there.

Essentially, when your turns hit 9, you're still within the "while(Window.isOpen())" loop, but there is nothing within that loop for your program to do. You could add a simple window.close() command outside of the "globalturns < 9" loop if you simply want to exit the game after the last turn, or put any other code there (win/loss, etc). You could just move the:

cout << "The game is over!";

command up a couple lines so it's inside the bracket above and it should be working like you expect it to.

So, your code is working fine, it's not actually hanging on that last function where you think it is, that's just the last place you tell it to do anything so it just kind of hangs out until you close it. tongue.png
Also, let me offer my apologies for the multiple times I've given you bad advice, etc. I have to admit I wasn't fully giving it that much attention or reading very closely as I kept coming across the thread right before I had to head out to work tongue.png That's on me, so my genuine apologies there. Hopefully this time I'm not mistaken yet again tongue.png It's a little weird for me with that much code and not being able to run it and play with it myself(I tried to build on my system, but I lacked the sprites and didn't have time to edit the code to ignore them. Also, your error codes for missing sprites made me smile smile.png).
Lastly, if its any consolation, there's someone out there reading this thread and laughing at how dumb we both are smile.png because in hindsight this should have been pretty obvious to us :)

Beginner here <- please take any opinions with grain of salt

Lastly, if its any consolation, there's someone out there reading this thread and laughing at how dumb we both are smile.png because in hindsight this should have been pretty obvious to us smile.png

I wouldn't call it that obvious, if I had one thing to say about the code he's posted is that it would be -much- easier to debug(if not just follow along with) if he split it up more logically into functions and such. There's quite a few guidelines out there for how to make code "flow" and be more self documenting, as it stands its basically a giant do everything function with one or two parts broken off rather arbitrarily.

Might also want to work on the variable naming a bit, no real use writing "second" if you're going to stop at "secon" and just confuse anyone reading what that possibly could be, or ttt for that matter, or t1. Very vague.

So, on your last turn,

pressed = butt[n].V2i_inRange(mousePosition);
will push your globalturns to 9. This is breaking your while loop above:

while (globalturns < 9)
which pushes you out of the loop. But, this is nested within your

while (window.isOpen())
So, unless I'm reading this wrong (which after several embarassing tries here, is entirely possible tongue.png ) you're still within the while window is open loop, but not running any other code.
You'll need to add something outside of the "globalturns < 9" loop that closes the window, shows a win/loss screen, anything etc. Right now, your global turns is too high for anything inside the other loop to run but you're still within the

while(Window.isOpen())

so it's not returning "0" yet and closing the program, and you've given your program nothing else to do while in there.

Essentially, when your turns hit 9, you're still within the "while(Window.isOpen())" loop, but there is nothing within that loop for your program to do. You could add a simple window.close() command outside of the "globalturns < 9" loop if you simply want to exit the game after the last turn, or put any other code there (win/loss, etc). You could just move the:

cout << "The game is over!";

command up a couple lines so it's inside the bracket above and it should be working like you expect it to.

So, your code is working fine, it's not actually hanging on that last function where you think it is, that's just the last place you tell it to do anything so it just kind of hangs out until you close it. tongue.png
Also, let me offer my apologies for the multiple times I've given you bad advice, etc. I have to admit I wasn't fully giving it that much attention or reading very closely as I kept coming across the thread right before I had to head out to work tongue.png That's on me, so my genuine apologies there. Hopefully this time I'm not mistaken yet again tongue.png It's a little weird for me with that much code and not being able to run it and play with it myself(I tried to build on my system, but I lacked the sprites and didn't have time to edit the code to ignore them. Also, your error codes for missing sprites made me smile smile.png).
Lastly, if its any consolation, there's someone out there reading this thread and laughing at how dumb we both are smile.png because in hindsight this should have been pretty obvious to us smile.png

thanks for your help i finally changed everything around in a way that makes it all flow a bit better, and got it all working, hopefully ill be done with this game by the end of the day :)

Lastly, if its any consolation, there's someone out there reading this thread and laughing at how dumb we both are smile.png because in hindsight this should have been pretty obvious to us smile.png

I wouldn't call it that obvious, if I had one thing to say about the code he's posted is that it would be -much- easier to debug(if not just follow along with) if he split it up more logically into functions and such. There's quite a few guidelines out there for how to make code "flow" and be more self documenting, as it stands its basically a giant do everything function with one or two parts broken off rather arbitrarily.

Might also want to work on the variable naming a bit, no real use writing "second" if you're going to stop at "secon" and just confuse anyone reading what that possibly could be, or ttt for that matter, or t1. Very vague.

thank you for the feedback, im sure i could do things a lot better, however i havent been coding for very long to be honest so im still pretty new to everything. if you had any links to the online documentation youve metioned id appreciate it, because im always up for learning how to do everything better.

This topic is closed to new replies.

Advertisement