Server Help

Non-Subspace Related Coding - I got bored and made a Tic-Tac-Toe game in SDL.

Animate Dreams - Mon Jan 25, 2010 11:15 pm
Post subject: I got bored and made a Tic-Tac-Toe game in SDL.
I wanted to learn SDL, and this is the first actual application I've made. I could use some advice on better ways to do things, if you guys have the time.

Code: Show/Hide
/* Tic-Tac-Toe
** By Kevin J. Russell
** 2010.01.19 January 19th, 2010
**
** This is my first game.
** It's Tic-Tac-Toe in C++/SDL.
*/


/* Includes */
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"


/* Screen Attributes */
const int SCREEN_WIDTH = 600;
const int SCREEN_HEIGHT = 600;
const int SCREEN_BPP = 32;

enum Mark
{ markOpen, markX, markO };


/* Function Prototypes */
void ApplySurface(int x, int y, SDL_Surface *source, SDL_Surface *destination);
void MarkSquare(int square, Mark mark);
void Logic();

/* Surfaces */
SDL_Surface *screen = NULL;
SDL_Surface *background = NULL;
SDL_Surface *x = NULL;
SDL_Surface *o = NULL;
SDL_Surface *win = NULL;


SDL_Event event;

Mark board[10];
Mark mark = markO;
bool quit = false;


int main(int argc, char *args[])
{
    for (int i = 0; i < 10; i++)
        board[i] = markOpen;
   
    SDL_Init(SDL_INIT_EVERYTHING);
    screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT,
        SCREEN_BPP, SDL_SWSURFACE);
    SDL_WM_SetCaption("Tic-Tac-Toe", NULL);
   
    background = SDL_DisplayFormat(IMG_Load("background.png"));
    x = SDL_DisplayFormat(IMG_Load("x.png"));
    o = SDL_DisplayFormat(IMG_Load("o.png"));
   
    ApplySurface(0, 0, background, screen);
    SDL_Flip(screen);
   
    while (quit == false)
    {
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_MOUSEBUTTONDOWN)
            {
                // Sneaky algorithm to convert mouse pos to square number
                MarkSquare((event.button.x/200)
                    + (event.button.y/200)*3 +1, mark);
               
                Logic();
            }
            if (event.type == SDL_QUIT)
                quit = true;
        }
    }
    SDL_FreeSurface(win);
    SDL_FreeSurface(background);
    SDL_FreeSurface(x);
    SDL_FreeSurface(o);
    SDL_Quit();
   
    return 0;
}


void ApplySurface(int x, int y, SDL_Surface *source, SDL_Surface *destination)
{
    SDL_Rect offset;

    offset.x = x;
    offset.y = y;

    SDL_BlitSurface(source, NULL, destination, &offset);
}


void MarkSquare(int square, Mark mark)
{
    board[square] = mark;

    // Get placement co-ords based on square number.
    int xpos = (((square-1)%3) *200) +10;
    int ypos = (((square-1)/3) *200) +10;
   
    if (mark == markX)
        ApplySurface(xpos, ypos, x, screen);
    else if (mark == markO)
        ApplySurface(xpos, ypos, o, screen);
}


void Logic()
{
    if (mark == markX)
        mark = markO;
    else if (mark == markO)
        mark = markX;
   
    // Victory Check
    if (board[1] == board[2] && board[1] == board[3] && board[1] != markOpen)
    {
        if (board[1] == markX)
            win = SDL_DisplayFormat(IMG_Load("xwin.png"));
        else
            win = SDL_DisplayFormat(IMG_Load("owin.png"));
        ApplySurface(0, 201, win, screen);
    }
    else if (board[4] == board[5] && board[4] == board[6] && board[4] != markOpen)
    {
        if (board[4] == markX)
            win = SDL_DisplayFormat(IMG_Load("xwin.png"));
        else
            win = SDL_DisplayFormat(IMG_Load("owin.png"));
        ApplySurface(0, 201, win, screen);
    }
    else if (board[7] == board[8] && board[7] == board[9] && board[7] != markOpen)
    {
        if (board[7] == markX)
            win = SDL_DisplayFormat(IMG_Load("xwin.png"));
        else
            win = SDL_DisplayFormat(IMG_Load("owin.png"));
        ApplySurface(0, 201, win, screen);
    }
    else if (board[1] == board[4] && board[1] == board[7] && board[1] != markOpen)
    {
        if (board[1] == markX)
            win = SDL_DisplayFormat(IMG_Load("xwin.png"));
        else
            win = SDL_DisplayFormat(IMG_Load("owin.png"));
        ApplySurface(0, 201, win, screen);
    }
    else if (board[2] == board[5] && board[2] == board[8] && board[2] != markOpen)
    {
        if (board[2] == markX)
            win = SDL_DisplayFormat(IMG_Load("xwin.png"));
        else
            win = SDL_DisplayFormat(IMG_Load("owin.png"));
        ApplySurface(0, 201, win, screen);
    }
    else if (board[3] == board[6] && board[3] == board[9] && board[3] != markOpen)
    {
        if (board[3] == markX)
            win = SDL_DisplayFormat(IMG_Load("xwin.png"));
        else
            win = SDL_DisplayFormat(IMG_Load("owin.png"));
        ApplySurface(0, 201, win, screen);
    }
    else if (board[1] == board[5] && board[1] == board[9] && board[1] != markOpen)
    {
        if (board[1] == markX)
            win = SDL_DisplayFormat(IMG_Load("xwin.png"));
        else
            win = SDL_DisplayFormat(IMG_Load("owin.png"));
        ApplySurface(0, 201, win, screen);
    }
    else if (board[3] == board[5] && board[3] == board[7] && board[3] != markOpen)
    {
        if (board[3] == markX)
            win = SDL_DisplayFormat(IMG_Load("xwin.png"));
        else
            win = SDL_DisplayFormat(IMG_Load("owin.png"));
        ApplySurface(0, 201, win, screen);
    }
    SDL_Flip(screen);
}


You should have seen what I had before. I had programmed in the co-ordinates for each square manually, so my game loop looked like this:
Code: Show/Hide
if (event.type == SDL_MOUSEBUTTONDOWN)
            {
                if (event.button.x <= 200 && event.button.y <= 200)
                    MarkSquare(1, mark);
                if (event.button.x > 200 && event.button.x <= 400 && event.button.y <= 200)
                    MarkSquare(2, mark);
                if (event.button.x > 400 && event.button.y <= 200)
                    MarkSquare(3, mark);
                if (event.button.x <= 200 && event.button.y > 200 && event.button.y <= 400)
                    MarkSquare(4, mark);
                if (event.button.x > 200 && event.button.x <= 400 && event.button.y > 200 && event.button.y <= 400)
                    MarkSquare(5, mark);
                if (event.button.x > 400 && event.button.y > 200 && event.button.y <= 400)
                    MarkSquare(6, mark);
                if (event.button.x <= 200 && event.button.y > 400)
                    MarkSquare(7, mark);
                if (event.button.x > 200 && event.button.x <= 400 && event.button.y > 400)
                    MarkSquare(8, mark);
                if (event.button.x > 400 && event.button.y > 400)
                    MarkSquare(9, mark);
               
                Logic();
            }


I still have something very similar for the win condition. I check each possible win state. I realize I should probably just check the column and the row of the square just posted, but I'm not sure how to do that. Should I use a multi-dimensional array instead? Then, I think I could just take the square that was just played, board[x][y], and I could check in a loop like board[x][i], and board[i][y]. Something like that.

Source and executable attached. You'll need SDL installed to compile, though.
Samapico - Mon Jan 25, 2010 11:27 pm
Post subject:
A loop in a 2D array would definitely save you some work.
You're also wasting board[0] tongue.gif

A loop to scroll through a 2D array, without needing too many weird control structures, could look like this:

Code: Show/Hide

//check rows
for (int j = 0; j < 3; j++) //for each row
if (board[0][j] != markOpen && board[0][j] == board[1][j] && board[0][j] == board[2][j])
  win(board[0][j]);

//where win is a function that takes a Mark argument
//do the same for columns

You could have another for in there, but you'd have to make tricky stuff to compare each cell. Like store the first value, compare each one, and break out the for loop at some point... If you could have a 4x4 or larger board, it would be worth it, but not here, imo.
Animate Dreams - Fri Jan 29, 2010 5:21 pm
Post subject:
Code: Show/Hide
/* Tic-Tac-Toe
** By Kevin J. Russell
** 2010.01.19 January 19th, 2010
**
** This is my first game.
** It's Tic-Tac-Toe in C++/SDL.
*/


/* Includes */
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"


/* Screen Attributes */
const int SCREEN_WIDTH = 600;
const int SCREEN_HEIGHT = 600;
const int SCREEN_BPP = 32;

enum Mark
{ markOpen, markX, markO };


/* Function Prototypes */
void ApplySurface(int x, int y, SDL_Surface *source, SDL_Surface *destination);
void MarkSquare(int squarex, int squarey, Mark mark);
void Logic();

/* Surfaces */
SDL_Surface *screen = NULL;
SDL_Surface *background = NULL;
SDL_Surface *x = NULL;
SDL_Surface *o = NULL;
SDL_Surface *win = NULL;


SDL_Event event;

//Mark board[10];
Mark board[3][3];
Mark mark = markO;
bool quit = false;


int main(int argc, char *args[])
{
    /*for (int i = 0; i < 10; i++)
        board[i] = markOpen;*/
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            board[i][j] = markOpen;
   
    SDL_Init(SDL_INIT_EVERYTHING);
    screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT,
        SCREEN_BPP, SDL_SWSURFACE);
    SDL_WM_SetCaption("Tic-Tac-Toe", NULL);
   
    background = SDL_DisplayFormat(IMG_Load("background.png"));
    x = SDL_DisplayFormat(IMG_Load("x.png"));
    o = SDL_DisplayFormat(IMG_Load("o.png"));
   
    ApplySurface(0, 0, background, screen);
    SDL_Flip(screen);
   
    while (quit == false)
    {
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_MOUSEBUTTONDOWN)
            {
                // Sneaky algorithm to convert mouse pos to square co-ord
                MarkSquare(event.button.x/200, event.button.y/200, mark);
               
                Logic();
            }
            if (event.type == SDL_QUIT)
                quit = true;
        }
    }
    SDL_FreeSurface(win);
    SDL_FreeSurface(background);
    SDL_FreeSurface(x);
    SDL_FreeSurface(o);
    SDL_Quit();
   
    return 0;
}


void ApplySurface(int x, int y, SDL_Surface *source, SDL_Surface *destination)
{
    SDL_Rect offset;

    offset.x = x;
    offset.y = y;

    SDL_BlitSurface(source, NULL, destination, &offset);
}


void MarkSquare(int squarex, int squarey, Mark mark)
{
    board[squarex][squarey] = mark;

    // Get placement co-ords based on square number   
    if (mark == markX)
        ApplySurface(200 * squarex + 10, 200 * squarey + 10, x, screen);
    else if (mark == markO)
        ApplySurface(200 * squarex + 10, 200 * squarey + 10, o, screen);
}


void Logic()
{
    // Set the win surface to the previous player's mark, in case of victory.
    // Then flip the mark for the next turn.
    if (mark == markX)
    {
        win = SDL_DisplayFormat(IMG_Load("xwin.png"));
        mark = markO;
    }
    else
    {
        win = SDL_DisplayFormat(IMG_Load("owin.png"));
        mark = markX;
    }
   
    // Victory Check
    for (int i = 0; i < 3; i++)
    {
        if (board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] != markOpen)
            ApplySurface(0, 201, win, screen);
        if (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] != markOpen)
            ApplySurface(0, 201, win, screen);
    }
    if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] != markOpen)
        ApplySurface(0, 201, win, screen);
    if (board[0][2] == board[1][1] && board[0][2] == board[2][0] && board[0][2] != markOpen)
        ApplySurface(0, 201, win, screen);
   
    SDL_Flip(screen);
}


Got it set up with a multidimensional array, now. I think it's basically done until I want to come back and add either game states(so I can actually stop the game) or AI.
Also, lol. Never seen a topic moved OUT of trash talk.
rootbear75 - Tue Feb 02, 2010 4:01 am
Post subject:
Feature request: Button along top or bottom that you can use to make a new game.

just make it start the program over....

like at the top have a
Code: Show/Hide

Label start;

then at the bottom
have a
Code: Show/Hide

goTo(start);


or something along that line.
Samapico - Tue Feb 02, 2010 5:21 pm
Post subject:
Don't listen to rootbear, he wants to make you program like it's 1985 again.

You can make your main loop back at the beginning in a much cleaner way tongue.gif
You might only need to dump the initialization stuff in a function, and call that function when you hit restart.
Animate Dreams - Thu Feb 04, 2010 12:46 am
Post subject:
Samapico wrote:
Don't listen to rootbear, he wants to make you program like it's 1985 again.

You can make your main loop back at the beginning in a much cleaner way tongue.gif
You might only need to dump the initialization stuff in a function, and call that function when you hit restart.


Ah, there is so little initialization, I think it just clutters things to move it into a function. I understand the need in larger projects, and in one way I am trying to teach myself some of the things I'd need for a larger project, but bad decisions are still bad decisions.

I plan on using this as an intro into game states, actually:
http://lazyfoo.net/articles/article06/index.php

That's the same place I've been using to learn SDL, although I'm only on Tutorial 9. Schoolwork has just started to get rough as well... so I might not get back to the tutorials until school is out.
To be honest, I'm not opposed to using goto for game states.
Samapico - Thu Feb 04, 2010 8:34 am
Post subject:
Animate Dreams wrote:
Ah, there is so little initialization, I think it just clutters things to move it into a function.
Your main is cluttered sa_tongue.gif

And what I was saying is, if you want to be able to restart the game, you'll probably need to repeat the initialization somewhere in the code, so you'll want it in a function.
Animate Dreams - Sat Feb 06, 2010 2:13 am
Post subject:
Actually, I can do it in three lines. Something like
for (int i = 0; i < 9; i++)
board[i] = markOpen;
ApplySurface(background, screen, null, null);
SDL_Flip(screen);

okay four.
Samapico - Sat Feb 06, 2010 2:58 pm
Post subject:
... still, you don't want to repeat these 4 lines if you want to do the operation more than once in your code. Making a function for these 4 lines would be far from cluttering

It's not rare to see functions with even only 1 line of code
All times are -5 GMT
View topic
Powered by phpBB 2.0 .0.11 © 2001 phpBB Group