help with simple first game

Started by
4 comments, last by Koobazaur 16 years, 3 months ago
I am creating my first game using SDL and I can get the X and O to display on a Tic-Tac-Toe board but I can't get them to be displayed based on whose turn it is. Its a player vs player game. I am using a bool value set to true if it's player ones turn it equals true if not its false and hence player two's turn. But it just randomly switches between the two pieces and I cannot figure out why but here's the code for that

if(player1 == true)
		{
			for(int i = 0; i < 9; ++i)
			{
				if((x > board_tiles.x) && (x < board_tiles.w) && (y > board_tiles.y) && (y < board_tiles.h))
				{
					apply_surface(board_tiles.x,board_tiles.y,pieceX,screen);
					player1 = false;
				}
			}

		}
		else if(player1 == false)
		{
			for(int i = 0; i < 9; ++i)
			{
				if((x > board_tiles.x) && (x < board_tiles.w) && (y > board_tiles.y) && (y < board_tiles.h))
				{
					apply_surface(board_tiles.x,board_tiles.y,pieceO,screen);
					player1 = true;
				}
			}
		}


I am using the for loop to decide in what square the user clicked the mouse so I search through them all and see if the user has clicked in them and x and y are the mouse offsets.
Advertisement
I figured out what I was doing wrong and which it my program kept acting the way it did. It was beacuse of the mouse offsets. The values were staying the same through main() and when it re ran through the game loop it just changed the piece. But now I have a whole different problem. The players turn are not connistent. They are always different. It will go X,O,X,O,O,X,X or differently. It's just random. Here's my code if someone can take a look at it please. Thank you.

// headers#include "SDL/SDL.h"#include "SDL/SDL_image.h"#include <string>// constants for screenconst int SCREEN_WIDTH = 640;const int SCREEN_HEIGHT = 480;const int SCREEN_BPP = 32;// the event structureSDL_Event event;// the tic-tac-toe board squaresSDL_Rect board_tiles[9];// the surfaceSDL_Surface *screen = NULL;SDL_Surface *background = NULL;SDL_Surface *pieceX = NULL;SDL_Surface *pieceO = NULL;// load the images into the surfacesSDL_Surface *load_image(std::string filename){	SDL_Surface *loadedImage = NULL;	SDL_Surface *optimizedImage = NULL;	loadedImage = IMG_Load(filename.c_str());	if(loadedImage != NULL)	{		optimizedImage = SDL_DisplayFormat(loadedImage);		SDL_FreeSurface(loadedImage);		if(optimizedImage != NULL)		{			SDL_SetColorKey(optimizedImage,SDL_SRCCOLORKEY,SDL_MapRGB(optimizedImage->format,0,0xFF,0xFF));		}	}	return optimizedImage;}void apply_surface(int x, int y, SDL_Surface *source,SDL_Surface *destination,SDL_Rect *clip = NULL){	SDL_Rect offset;	offset.x = x;	offset.y = y;	SDL_BlitSurface(source,clip,destination,&offset);}bool init(){	if(SDL_Init(SDL_INIT_EVERYTHING) == -1)		return false;	screen = SDL_SetVideoMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,SDL_SWSURFACE);	if(screen == NULL)		return false;	SDL_WM_SetCaption("Tic-Tac-Toe 1.0",NULL);	return true;}bool load_files(){	background = load_image("background.png");	pieceX = load_image("pieceX.png");	pieceO = load_image("pieceO.png");	if(background == NULL)		return false;	if(pieceX == NULL)		return false;	if(pieceO == NULL)		return false;	return true;}void clean_up(){	SDL_FreeSurface(background);	SDL_FreeSurface(pieceX);	SDL_FreeSurface(pieceO);	SDL_Quit();}// initalizes all the square piece of the Tic-Tac-Toe boardvoid init_tiles(){	// top left	board_tiles[0].x = 80;	board_tiles[0].y = 115;	board_tiles[0].w = 165;	board_tiles[0].h = 185;	// top middle	board_tiles[1].x = 180;	board_tiles[1].y = 115;	board_tiles[1].w = 345;	board_tiles[1].h = 185;	// top right	board_tiles[2].x = 350;	board_tiles[2].y = 115;	board_tiles[2].w = 440;	board_tiles[2].h = 185;	// middle left	board_tiles[3].x = 75;	board_tiles[3].y = 190;	board_tiles[3].w = 170;	board_tiles[3].h = 280;	// middle middle	board_tiles[4].x = 175;	board_tiles[4].y = 190;	board_tiles[4].w = 345;	board_tiles[4].h = 280;	// middle right	board_tiles[5].x = 350;	board_tiles[5].y = 190;	board_tiles[5].w = 440;	board_tiles[5].h = 280;	// bottom left	board_tiles[6].x = 75;	board_tiles[6].y = 285;	board_tiles[6].w = 165;	board_tiles[6].h = 340;	// bottom middle	board_tiles[7].x = 175;	board_tiles[7].y = 285;	board_tiles[7].w = 345;	board_tiles[7].h = 340;		// bottom right	board_tiles[8].x = 350;	board_tiles[8].y = 285;	board_tiles[8].w = 445;	board_tiles[8].h = 340;}				int main(int argc, char *args[]){	// the mouse button offsets	int x = 0, y = 0;	bool quit = false;	bool player1 = true;	// initalize SDL	if(init() == false)		return 1;	// initalize and load all the files for us	if(load_files() == false)		return 1;	// load the Tic-Tac-Toe board	init_tiles();	apply_surface(0,0,background,screen);	while(quit == false)	{		while(SDL_PollEvent(&event))				{			if(event.type == SDL_MOUSEBUTTONDOWN)			{				if(event.button.button == SDL_BUTTON_LEFT)				{					x = event.button.x;					y = event.button.y;				}			}			else if(event.type == SDL_QUIT)			{				quit = true;			}		}				for(int i = 0; i < 9; ++i)		{			if(player1 == true)			{				if((x > board_tiles.x) && (x < board_tiles.w) && (y > board_tiles.y) && (y < board_tiles.h))					{												apply_surface(board_tiles.x,board_tiles.y,pieceX,screen);					}			}						else if(player1 == false)			{				if((x > board_tiles.x) && (x < board_tiles.w) && (y > board_tiles.y) && (y < board_tiles.h))					{												apply_surface(board_tiles.x,board_tiles.y,pieceO,screen);					}			}		}		if(player1 == true)			player1 = false;		else if(player1 == false)			player1 = true;		x = 0;		y = 0;				if(SDL_Flip(screen) == -1)			return 1;					}	clean_up();	return 0;}	
It goes through the ( quit == false ) loop unhindered, changing player everytime it reaches the end.

It needs to change players only when the player has placed a piece.

As it is now there's 50% chance you are player 1 and 50% chance you are player 2 every time you click the mouse, hence the randomness.

I think that's it.
Chris is right, but aside from that I noticed the code to put each player's piece is exactly the same except for what piece is being put down. What you could have done instead is to have an array of 2 elements, one containing a pointer to pieceX and the other containing a pointer to pieceO (and of course, you would no longer declare pieceX and pieceO as loose variables). Rather than using a boolean to determine who's turn it is, you would use a number that corresponds to the index of the array that contains that player's piece. As you make bigger and bigger projects, learning to avoid repetition will be one of the most useful skills you'll develop as a programmer.

You might go even further and make a class for each player. This class would have the player's name, a pointer to their current piece (what used to be pieceO or pieceX), and maybe even a number for how many games they've won. Instead of having an array with pointers to pieceX or pieceO, you would have pointers to Player objects. This way, you could put a text label on your game saying "It's your turn, Billy Bo Bob!".


Thank you for all the information its all helping alot. Im gonna try to get the game working first them implemnting the classes after that and some more functionality. But I tried to figure out if the player won by trying to use the code in Dawson's book but I'm not sure what Im doing wrong. Im using an array of Surfaces and setting them all to NULL at first. Then when a player places a piece if with set the position in the array of surfaces to pieceX or pieceO and then I i'm trying to search through the board and see if the player has three in a row to see if they won and if they did then display a message. But its not displaying a message and not sure why. I know I'm having alot of problems but I'm also learning. Ive made some simple text based games but thats why I didnt want to try anything to difficult at first. Thanks
Your basic program flow (if I understood everything correctly) looks something like this:

Loop{If Mouse Clicked -> Get Mouse positionApply tile at mouse positionChange player}


As others have pointed out, your biggest flaw is that all your functions are called every loop iteration. That is, the player changes regardless if he has clicked (i.e. finished his turn). Likewise, you do the tile-placement checks every for loop, even if a player did not place a tile, which is wasteful.

What you should do is re-organize your code so that there is a clear division between each player's turns, and that tile placement and turn changes are done only when the player actually makes a move. This can be done through a simple "state" system using a switch statement.

Here's some pseudo code to give you an idea of what I'm talking about:

variable STATE = player turn;while(quit != true)	{	do standard stuff here that needs to be done every loop like:		- draw your tiles to screen		- check for non-state specific input (ex: Escape key -> set quit = true)		switch(STATE)		//============================================================		case player turn:			{			//============================================================			//	Player input check			//============================================================						if(there is new input)				{				 switch(input type)					{					 case left mouse click: 						{							if(empty tile) 								{								set tile to player 1's tile								set STATE to turn done								} 							else								{								 do nothing, or display error ("This tile is already taken!") or something								}											}															}				}			 break state switch statement;			}					//============================================================		case turn done:			{			 if(any one player won)				set STATE to someone won;			 else				{				change "current" player to the other player (player1 = !player1)				STATE = player turn;				}						 break state switch statement;			}					//============================================================		case some one won:			{			 dispaly victory screen or something like that;							 break state switch statement;			}	}


You can then wrap each state code into it's own function to make your game loop look nicer and easier to understand.

Also, a hint - you can use the negation operator to "invert" bools. Instead of your if else if, just do player1 = !player1;

edit: here's a read on game states: http://gamedevgeek.com/tutorials/managing-game-states-in-c/

[Edited by - Koobazaur on January 2, 2008 1:58:42 AM]
Comrade, Listen! The Glorious Commonwealth's first Airship has been compromised! Who is the saboteur? Who can be saved? Uncover what the passengers are hiding and write the grisly conclusion of its final hours in an open-ended, player-driven adventure. Dziekujemy! -- Karaski: What Goes Up...

This topic is closed to new replies.

Advertisement