Tic-Tac-Toe was(SDL Mouse and Hot Spots)

Started by
10 comments, last by Meta Adam 19 years, 3 months ago
Hello, I'm learning SDL and am trying to make Tic Tac Toe. I know how to check if the Mouse button goes down, but how can I check if its one of the 9 hot spots? Heres my code so far.

#include <iostream>
#include <SDL/SDL.h>
SDL_Surface *back;
SDL_Surface *x;
SDL_Surface *o;
SDL_Surface *screen;
int cell[8];

int InitImages() {
  back = SDL_LoadBMP("Back.bmp");
  x = SDL_LoadBMP("x.bmp");
  o = SDL_LoadBMP("o.bmp");
  return 0;
}
int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
void DrawIMG(SDL_Surface *img, int x, int y) {
  SDL_Rect dest;
  dest.x = x;
  dest.y = y;
  SDL_BlitSurface(img, NULL, screen, &dest);
}
void drawIMG(SDL_Surface *img, int x, int y, int w, int h, int x2, int y2) {
  SDL_Rect dest;
  dest.x = x;
  dest.y = y;
  SDL_Rect dest2;
  dest2.x = x2;
  dest2.y = y2;
  dest2.w = w;
  dest2.h = h;
  SDL_BlitSurface(img, &dest2, screen, &dest);
}
void checkcell(mousex, mousey) {
  if(mousex < 317 && mousey < 297)

void drawbg() {
  DrawIMG(back, 0, 0);
}
void drawx(int v, int z, int y, int x2, int y2) {
  if(cell[v] == 0) {
    cell[v] = 1;
    drawIMG(x, z, y, 155, 147, x2, y2);
  }
  else
    std::cout<<"Cannot put x there."<<std::endl;
}
void drawo(int v, int x, int y, int x2, int y2) {
  if(cell[v] == 0) {
    drawIMG(o, x, y, 155, 147, x2, y2);
    cell[v] = 1;
  }
  else
    std::cout<<"Cannot put o there."<<std::endl;
}

int main(int argc, char* argv[]) {
  if(SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO)<0) {
    std::cout<<"Unable to init SDL."<<std::endl;
    SDL_GetError();
  }
  InitImages();
  drawbg();
  int done=0;
  while(done == 0)
  {
    SDL_Event event;
    while ( SDL_PollEvent(&event) )
    {
      if ( event.type == SDL_QUIT )  {  done = 1;  }

      if ( event.type == SDL_KEYDOWN )
      {
        if ( event.key.keysym.sym == SDLK_ESCAPE ) { done = 1; }
      }
    }
  }
  return 0;
}




could it be something like:

if(SDL_MOUSEBUTTONDOWN == 1) {
  if(mousex < 317 && mousey < 297) {
    if(turn == 'x') {
      drawIMG(x, 320, 150, 155, 147, 317, 297);
      cell[0] = 1;
      }
    if(turn == 'y') {
      drawIMG(y, 320, 150, 155, 147, 317, 297);
      cell[0] = 1;
      }
    }
}
except i would need a way to find mouse position and set it as mouse x, and mouse y. I dunno though. Is there a way to do it so I dont have to hard code for all 9 cells? edit: Yes I know I have really bad code design, but I will fix that later. [Edited by - Meta Adam on January 13, 2005 8:45:01 PM]
Meta AdamOne of a million noob C++ programmers.
Advertisement
Are you sure you're ready for SDL? You don't seem to understand arrays yet. Assuming "int cell[8]" is what you're using to keep track of the board, you're missing an element. Arrays are declared by giving the number of elements you want, not the index of the last element you want.

int cell[8] is going to give you:
cell[0], cell[1], cell[2], cell[3], cell[4], cell[5], cell[6], cell[7] for a total of 8 elements.

You want int cell[9], so you get the 9 elements (0 - 8) that a Tic-Tac-Toe board has.

You might consider implementing Tic-Tac-Toe in a console window first. After you work through the problems that it presents, change the rendering and input code to SDL but keep the game logic. It will be a good test in the modularity of your code.
I thought I had done the array wrong, I knew it started at 0 but forgot the target number was -1 of what it says. But I changed it to cells[3][3] to help me out, on keeping track of where the cells are =)
Meta AdamOne of a million noob C++ programmers.
Hows this look so far? I made a Cell class and the made a Board class. Take a look of my code so far.
#include <iostream>#include <SDL/SDL.h>class cell {  private:    enum cellStatus {EMPTY, HASX, HASO};    bool cannotGoThere;  public:    void checkStatus(cellStatus status) {      switch (status) {        case EMPTY:          cannotGoThere = false;        case HASX:          cannotGoThere = true;        case HASO:          cannotGoThere = true;        }      }    void setStatusX(int x, int y) {      cellStatus cell[x][y] = HASX;    }    void setStatusO(int x, int y) {      cellStatus cell[x][y] = HASO;    }    void alreadyThere() {      std::cout<<"There is already a piece there."<<std::endl;    }  }class board : public cell {  private:    int cell[3][3];  public:    void placeX(int x, int y) {      void checkStatus(cell[x][y]);      if(cannotGoThere == false) {        setStatusX(x, y);      }      else        alreadyThere();    }    void placeO(int x, int y) {      void checkStatus(cell[x][y]);      if(cannotGoThere == false) {        setStatusO(x, y);      }      else        alreadyThere();    }  }

To me, that looks like probably some of the best code design i've done. But I don't know if it's good or not =)
Meta AdamOne of a million noob C++ programmers.
EDIT: you posted at the same time as me.. ill check your code out now.

you could do something like this..

struct TTTSquare{  int x;  int y;  int width;  in height;};TTTSqaure board[3][3];


then, you can set up the board like this:

for(int y = 0; y < 3; y++){   for(int x = 0; x < 3; x++)   {      board[y][x].x = x*SQUARESIZE;      board[y][x].y = y*SQUARESIZE;          board[y][x].width = SQUARESIZE;      board[y][x].height = SQUARESIZE;   }}


where SQUARESIZE is the width/height of a board square. i guess you dont need width/height as members of the TTTSquare class since they wont change, but it might be nice to keep it like that incase for some reason you want irregular shaped squares or somethin.. seems unlikely but it never hurts to leave your code open for changes.
FTA, my 2D futuristic action MMORPG
ok, theres a bunch of things wrong with your code, but its definetly a good start. im gunna comment line by line on your code, just read my comments or changes.

#include <iostream>#include <SDL/SDL.h>class cell {  private:    //very good, you seem to be using enums appropriately    enum cellStatus {EMPTY, HASX, HASO};       //hmm.. this jumps out to me as odd...perhaps you named this wrong? why would a board cell have a "cannotGoThere"? perhaps cell_taken or cell_used or cannotGoHere would be a better name?    bool cannotGoThere;  public:    //ok, this is pretty strange.. you have something thats called "checkX". usually when something is checking something, it will return a value saying the status. but your function doesnt return anything. how does it tell people the status of the cell?    void checkStatus(cellStatus status) {      switch (status) {        case EMPTY:          cannotGoThere = false;        case HASX:          cannotGoThere = true;        case HASO:          cannotGoThere = true;        }      }        void setStatusX(int x, int y) {           //here you are defining an array called cell[][].      //i just woke up, but im not even sure why this compiles       //instead it should look like cell[x][y] = HASX.      cellStatus cell[x][y] = HASX;    }    void setStatusO(int x, int y) {      cellStatus cell[x][y] = HASO;    }    //you might want to rename this function to make it more clear what it does. in the other part of your code it gets confusing    // PrintAlreadyThere() might be a better idea.    void alreadyThere() {      std::cout<<"There is already a piece there."<<std::endl;    }  }//ok. why is board inheriting from cell? this is all wrong. when using inheritence, you have to think to yourself. "Is an child a parent?". e.g., having Dog inherit from Animal. Is a dog an animal? how about in your case. is a board a cell? no, a board HAS a cell. hasA relationships are good for "composition". composition means putting a member inside of a class, instead of inheriting from that class.class board : public cell {  private:    int cell[3][3];  public:    void placeX(int x, int y) {            //what is this here now? why is void written out here? what you have here is a function declaration. you are not calling a function here. if you want to call the function, call checkStatus(cell[x][y]);      void checkStatus(cell[x][y]);      if(cannotGoThere == false) {        setStatusX(x, y);      }      else        alreadyThere();    }    void placeO(int x, int y) {      void checkStatus(cell[x][y]);      if(cannotGoThere == false) {        setStatusO(x, y);      }      else        alreadyThere();    }  }


now, here is your code after i re-wrote it
#include <iostream>#include <SDL/SDL.h>class cell {  public:    enum cellStatus {EMPTY, HASX, HASO};         //a cell starts off as EMPTY    cell(): status(EMPTY) {}    cellStatus status;};class board {  private:    cell board[3][3];  public:    cellStatus checkStatus(int x, int y) {         return board[x][y].status;        }    void setStatusX(int x, int y) {      board[x][y].status = HASX;    }    void setStatusO(int x, int y) {      board[x][y].status = HASO;    }    void PrintalreadyThere() {      std::cout<<"There is already a piece there."<<std::endl;    }    void placeX(int x, int y) {      if(checkStatus(cell[x][y]) != EMPTY)          setStatusX(x,y);      else         PrintAlreadyTaken();    }    void placeO(int x, int y) {      if(checkStatus(x,y) != EMPTY)        setStatusO(x, y);            else        PrintAlreadyThere();    }  }
FTA, my 2D futuristic action MMORPG
Here's the rewrite of your rewritten code =) Although I'm still getting errors about my enum's being undeclared, but I think I can clear it up.
#include <iostream>class cell {  public:    enum cellStatus {HASX, HASO, EMPTY};    cell(): status(EMPTY) {};    cellStatus status;  };class board {  private:    cell cells[3][3];  public:    int checkStatus(int x, int y) {      return cells[x][y].status;    }    void printCannotPlace() {      std::cout<<"Cannot place there."<<std::endl;    }    void setStatusX(int x, int y) {      cells[x][y].status = HASX;      }    void setStatusO(int x, int y) {      cells[x][y].status = HASO;      }    void placeX(int x, int y) {      if(cells[x][y].status == EMPTY)        setStatusX(x, y);      else        printCannotPlace();      }    void placeO(int x, int y) {      if(cells[x][y].status == EMPTY)        setStatusO(x, y);      else        printCannotPlace();      }  };int main() {}
Meta AdamOne of a million noob C++ programmers.
Take your enums out of the cell class and put them at the top or in their own header file (best option). Just because they're public doesn't mean they're global - they're still members of the cell class and can't be accessed without an instance of cell

Drew Sikora
Executive Producer
GameDev.net

you should still be able to access the enums, regardless if they are inside the class or not. in fact, i prefer to put them inside of the class - this way, it gives the enum's a better meaning. in a large project, you might have enums which are very similar in name, and the namespace (or class) they are in is the only way to differentiate them. plus, intellisence will remind you what enums you have by just typeing "classname::". (yes, this works with globals, but any convenience of intellisence is lost by having to wade through the global namespace).

anyway, you should be able to access your enums from outside of the cell class simply by doing cell::EMPTY, cell::HASX, etc.
FTA, my 2D futuristic action MMORPG
Quote:Original post by Meta Adam
Hows this look so far? I made a Cell class and the made a Board class. Take a look of my code so far.
*** Source Snippet Removed ***
To me, that looks like probably some of the best code design i've done. But I don't know if it's good or not =)

This is what I used for mine:

typedef struct _BLOCK{  int Hovering;  char Occupation;  int Top;  int Left;} BLOCK;

I used a 1D array and calculated the Left and Top values so that they can be drawn easily ... Also, when you check the mouse positions you can just check whether its Bigger than the Left and Top and smaller than the (Left + Width) and (Top + Hright).
__________Michael Dawson"IRC is just multiplayer notepad." - Reverend

This topic is closed to new replies.

Advertisement