#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    26
    Rep Power
    0

    Wierd Crash In My Program


    I am making a TicTacToe program and everytime i run it i get a crash right after the computers turn.
    also when i remove the if statement right after the while(1) in main() it doesnt crash but if i remove it nobody will win and the game doesnt end.
    here is the code.
    I also get no errors or warnings i use code:blocks as my compiler if that helps.

    Code:
    #include <stdio.h>
    #include <windows.h>
    #include <time.h>
    #include <string.h>
    
    char win[20],W;
    char comp[] = "Computer";
    char you[] = "You";
    int board[3][3] = {
            0,0,0,
            0,0,0,
            0,0,0};
    
    void AI(void)
    {
    
        int A,B;
    
    
        while(1)
        {
            srand((unsigned)time(NULL));
    
            A = rand() % 3;
            B = rand() % 3;
    
    
            if(board[A][B]!=1 && board[A][B]!=2)
                {
                    board[A][B] = 2;
                    break;
                }
        }
    
    
    }
    void Board(void)
    {
        printf("\n\n");
    
        printf("\n\t\t\t\tY");
        printf("\n\t\t\t\t3 %d %d %d",board[0][0],board[0][1],board[0][2]);
        printf("\n\t\t\t\t2 %d %d %d",board[1][0],board[1][1],board[1][2]);
        printf("\n\t\t\t\t1 %d %d %d",board[2][0],board[2][1],board[2][2]);
        printf("\n\t\t\t\t  1 2 3 X");
    }
    
    void Evauluate(int X, int Y)
    {
        //1 2 3    0 1 2    3
        //2        1 x x    2
        //3        2 x x     1 2 3
    
        if(X==1 && Y==1)
        {
            board[2][0] = 1;
        }
        else if(X==1 && Y==2)
        {
            board[1][0] = 1;
        }
        else if(X==1 && Y==3)
        {
            board[0][0] = 1;
        }
        else if(X==2 && Y==1)
        {
            board[2][1] = 1;
        }
        else if(X==2 && Y==2)
        {
            board[1][1] = 1;
        }
        else if(X==2 && Y==3)
        {
            board[0][1] = 1;
        }
        else if(X==3 && Y==1)
        {
            board[2][2] = 1;
        }
        else if(X==3 && Y==2)
        {
            board[1][2] = 1;
        }
        else if(X==3 && Y==3)
        {
            board[0][2] = 1;
        }
    }
    
    int Win(void)
    {
    
    
    // you
        if(board[0][0] + board[0][1] + board[0][2] == 3)
        {
            strcpy(win,you);
            goto Won;
        }
        else if(board[1][0] + board[1][1] + board[1][2] == 3)
        {
            strcpy(win,you);
            goto Won;
        }
        else if(board[2][0] + board[2][1] + board[2][2] == 3)
        {
            strcpy(win,you);
            goto Won;
        }
        else if(board[0][0] + board[1][1] + board[2][2] == 3)
        {
            strcpy(win,you);
            goto Won;
        }
        else if(board[0][2] + board[1][1] + board[2][0] == 3)
        {
            strcpy(win,you);
            goto Won;
        }
        else if(board[0][0] + board[1][0] + board[2][0] == 3)
        {
            strcpy(win,you);
            goto Won;
        }
        else if(board[0][1] + board[2][1] + board[2][1] == 3)
        {
            strcpy(win,you);
            goto Won;
        }
        else if(board[0][2] + board[1][2] + board[2][2] == 3)
        {
            strcpy(win,you);
            goto Won;
        }
    
        // Compuetr
        else if(board[0][0] + board[0][1] + board[0][2] == 6)
        {
            strcpy(win,comp);
            goto Won;
        }
        else if(board[1][0] + board[1][1] + board[1][2] == 6)
        {
            strcpy(win,comp);
            goto Won;
        }
        else if(board[2][0] + board[2][1] + board[2][2] == 6)
        {
            strcpy(win,comp);
            goto Won;
        }
        else if(board[0][0] + board[1][1] + board[2][2] == 6)
        {
            strcpy(win,comp);
            goto Won;
        }
        else if(board[0][2] + board[1][1] + board[2][0] == 6)
        {
            strcpy(win,comp);
            goto Won;
        }
        else if(board[0][0] + board[1][0] + board[2][0] == 6)
        {
            strcpy(win,comp);
            goto Won;
        }
        else if(board[0][1] + board[2][1] + board[2][1] == 6)
        {
            strcpy(win,comp);
            goto Won;
        }
        else if(board[0][2] + board[1][2] + board[2][2] == 6)
        {
            strcpy(win,comp);
            goto Won;
        }
        else
        {
            goto no;
        }
        Won:;
        W=7;
    
        no:;
    
    }
    
    int main()
    {
        int X,Y;
        Board();
        putchar('\n');
    
    
    while(1)
    {
        if(W==7)
            {
                break;
            }
            printf("\n\n Enter Cordinates To Pick Format X,Y: ");
            scanf("%d,%d",&X,&Y);
            Evauluate(X,Y);
            system("cls");
            Board();
            Win();
    
    
    
            printf("\nComputers Turn\nComputer Is Thinking . . .");
            Sleep(1000);
            AI();
            system("cls");
            Win();
    
            Board();
    
    
    
    
    
    
    }
    fin:;
    
    printf("\n%s Won The Game");
    
    return 0;
    }
  2. #2
  3. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,379
    Rep Power
    1871
    > srand((unsigned)time(NULL));
    Do this before you enter the while loop.
    Ideally, you do this once at the beginning of main()

    Otherwise, A = rand() % 3; is going to keep giving you the SAME answer until a whole second has elapsed, and you get another seed.

    > if(board[0][0] + board[0][1] + board[0][2] == 3)
    So if you choose board[0][0] (=1) and computer chooses board[0][1] (=2), and board[0][2] is empty, you win.

    > goto Won;
    All the else if's take care of this, without messy goto's filling up the code. While you're learning to code, choosing a goto is 99.999% the wrong answer to whatever it is you're doing.

    Code:
        if(X==1 && Y==1)
        {
            board[2][0] = 1;
        }
    This would be SO much simpler if you did board[X-1][Y-1] = 1;
    The board is symmetrical, so it doesn't matter which corner you regard as being 0,0.

    Finally, get a compiler with lots of diagnostic capability.
    Code:
    $ gcc -g -Wall foo.c
    foo.c:10: warning: missing braces around initializer
    foo.c:10: warning: (near initialization for `board[0]')
    foo.c: In function `AI':
    foo.c:23: warning: implicit declaration of function `rand'
    foo.c: In function `Win':
    foo.c:187: warning: control reaches end of non-void function
    foo.c: In function `main':
    foo.c:194: warning: implicit declaration of function `srand'
    foo.c:228: warning: too few arguments for format
    foo.c:228: warning: too few arguments for format
    foo.c:226: warning: label `fin' defined but not used
    foo.c:231:2: warning: no newline at end of file
    > printf("\n%s Won The Game");
    Yes, you forgot the string parameter to print!
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  4. #3
  5. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,109
    Rep Power
    1802
    Using a debugger is a really effective method of crash analysis. You can either step the code into the event that will cause a crash and observe the variable state, or if you don't know where the crash occurs, after the event, the debugger will in most cases stop and allow you to unwind the call stack to the point in your code where it failed - sometimes the fault may be detectable precisely at the point of failure.

    Code::Blocks is an IDE not a compiler. It works with GCC (MinGW/GCC on Windows). It integrates a perfectly adequate debugger (GDB) and provides an easy to use interface to it (easier at least then the GDB command line).

    I cannot immediately see a problem and would resort to compiling and running the code in a debugger myself if I were to investigate. However a couple of other issues arise:

    You should only ever seed the random number generator once at the start of your program (most conveniently in main()). You are seeding it every time the AI() loop runs with a time value that updates only once per second - you will get the same "random" number repeatedly until the second ticks over, and the "random-ness" of that is likely to be suspect). For debugging it is often better in fact to seed the generator with a fixed value so that every time you run it it produces the same sequence, so your code does the same thing - often useful when debugging.

    Use of global variables should be avoided.

    Win() is declared to return an int but returns nothing. I wondew how you did not get a warning for that.

    Your Win() function has a lot of repetition and an unnecessary goto. Goto is always unnecessary; if you think you have a situation where it is necessary, your design is almost always flawed. It is "unstructured", as is using break or continue in a loop - something else your code has. There are a number of ways Win() could be better coded. The following is directly equivalent to yours but without repetition or goto:

    C Code:
     
    void Win(void)
    {
        // you
        if( board[0][0] + board[0][1] + board[0][2] == 3 ||
            board[1][0] + board[1][1] + board[1][2] == 3 ||
            board[2][0] + board[2][1] + board[2][2] == 3 ||
            board[0][0] + board[1][1] + board[2][2] == 3 ||
            board[0][2] + board[1][1] + board[2][0] == 3 ||
            board[0][0] + board[1][0] + board[2][0] == 3 ||
            board[0][1] + board[2][1] + board[2][1] == 3 ||
            board[0][2] + board[1][2] + board[2][2] == 3 )
        {
            strcpy(win,you);
            W = 7 ;
        }
        // Computer
        else if( board[0][0] + board[0][1] + board[0][2] == 6 ||
                 board[1][0] + board[1][1] + board[1][2] == 6 ||
                 board[2][0] + board[2][1] + board[2][2] == 6 ||
                 board[0][0] + board[1][1] + board[2][2] == 6 ||
                 board[0][2] + board[1][1] + board[2][0] == 6 ||
                 board[0][0] + board[1][0] + board[2][0] == 6 ||
                 board[0][1] + board[2][1] + board[2][1] == 6 ||
                 board[0][2] + board[1][2] + board[2][2] == 6 ||
        {
            strcpy(win,comp);
            W = 7 ;
        }
    }


    However there is a perhaps more elegant approach using iteration.

    C Code:
     
    void Win(void)
    {
        int a ;
        int b ;
        int sum = 0;
     
        // Check rows
        for( a = 0; a < 3 && sum != 3 && sum != 6 ; a++ )
        {
            for( b = 0, sum = 0; b < 3; b++ )
            {
                sum += board[a][b] ;
            }
        }
     
        // Check columns
        for( a = 0; a < 3 && sum != 3 && sum != 6 ; a++ )
        {
            for( b = 0, sum = 0; b < 3; b++ )
            {
                sum += board[b][a] ;
            }
        }
     
        // Check 1st diagonal
        for( a = 0, sum = 0; a < 3 && sum != 3 && sum != 6 ; a++ )
        {
            sum += board[a][a] ;
        }
     
        // Check 2nd diagonal
        for( a = 0, sum = 0; a < 3 && sum != 3 && sum != 6 ; a++ )
        {
            sum += board[a][a] ;
        }
     
        if( sum == 3 )
        {
            // Winner is you
            strcpy(win,you);
            W = 7 ;
        }
        else if( sum == 6 )
        {
            // Winner is computer
            strcpy(win,you);
            W = 7 ;
        }
    }


    It is possible to merge the four outer check loops into one, but that the needs multiple sum variables to be calculated and tested, and it all gets a bit hard to follow.
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2013
    Posts
    26
    Rep Power
    0
    Yeah a lot of stupid mistakes on my part
    and win was returning a value i was usinig it to try to fix the crash but took it off and forgot to take off the int
    thanks for your help

IMN logo majestic logo threadwatch logo seochat tools logo