Thread: Stumped on an infinite loop

  1. #1
    Registered User
    Join Date
    Jun 2010
    Posts
    11

    Stumped on an infinite loop

    Ok guys, be nice. First time posting
    I'm a programming amateur. Only learned up to arrays so, nothing advanced yet please.

    For a programming exercise, were asked to make a tic tac toe program. Here's the way I wrote it.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    int checkDiag(int board[3][3])
    {
    	if(board[1][1] == 0)
    		return 0;
    	if(board[1][1] == board[0][0] && board[1][1] == board[2][2])
    		return 1;
    	else if(board[1][1] == board[0][2] && board[1][1] == board[2][0])
    		return 1;
    	return 0;
    }
    int checkNondiag(int board[3][3])
    {
    	int i, j, three = 1, check = 0;
    	for(i=0;i<3;i++)
    		if(board[i][i] == 0)
    			check++;
    	if(check == 3)
    		return 0;
    	for(i=0;i<3;i++)
    	{
    		three = 1;
    		for(j=1;j<3;j++)
    		{
    			if(board[i][0] == board[i][j])
    				three++;
    		}
    		if(three == 3)
    			return 1;
    	}
    	three = 1;
    	for(i=0;i<3;i++)
    	{
    		three = 1;
    		for(j=1;j<3;j++)
    		{
    			if(board[0][i] == board[i][j])
    				three++;
    		}
    		if(three == 3)
    			return 1;
    	}
    	return 0;	
    }
    void gameboard(int board[3][3])
    {
    	int i, j;
    	printf(" - - - \n|1|2|3|\n - - - \n|4|5|6|\n - - - \n|7|8|9|\n - - - \n\n");
    	printf(" - - - \n");
    	for(i=0;i<3;i++)
    	{
    		printf("|");
    		for(j=0;j<3;j++)
    		{
    			switch(board[i][j])
    			{
    				case 1: printf("X|");
    						break;
    				case 2: printf("O|");
    						break;
    				default: printf(" |");
    			}
    		}
    		printf("\n - - - \n");
    	}
    }
    int main(void)
    {
    	int board[3][3] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
    	int turn = 0, move = 0, win = 0, p1 = 0, p2 = 0;
    	int i, j;
    	do
    	{
    		do
    		{
    			if(checkDiag(board) == 1 || checkNondiag(board) == 1)
    				switch(turn)
    				{
    					case 0: p2++;
    							break;
    					case 1: p1++;
    							break;
    				}
    			system("cls");
    			printf("TIC TAC TOE IN C\n\n");
    			gameboard(board);
    			if(checkDiag(board) == 1 || checkNondiag(board) == 1)
    				switch(turn)
    				{
    					case 0: p2++;
    						      break;
    					case 1: p1++;
    					             break;
    				}
    			printf("\nPlayer 1(X): %d\nPlayer 2(O): %d\n\n", p1, p2);
    			if(checkDiag(board) == 1 || checkNondiag(board) == 1)
    				switch(turn)
    				{
    					case 0: printf("Player 2 won!\n");
    							win = 1;
    							for(i=0;i<3;i++)
    								for(j=0;j<3;j++)
    									board[i][j] = 0;
    							break;
    					case 1: printf("Player 1 won!\n");
    							win = 1;
    							for(i=0;i<3;i++)
    								for(j=0;j<3;j++)
    									board[i][j] = 0;
    							break;
    				}
    			printf("Player %d's turn!\n", turn + 1);
    			printf("What space would you like to use? ");
    			while(move < 1 || move > 9)
    			{
    				scanf("%d", &move);
    				if( move < 1 || move > 9)
    					printf("Invalid coordinates. Please enter another: ");
    			}
    			switch(move)
    			{
    					case 1: board[0][0] = turn + 1;
    							break;
    					case 2: board[0][1] = turn + 1;
    							break;
    					case 3: board[0][2] = turn + 1;
    							break;
    					case 4: board[1][0] = turn + 1;
    							break;
    					case 5: board[1][1] = turn + 1;
    							break;
    					case 6: board[1][2] = turn + 1;
    							break;
    					case 7: board[2][0] = turn + 1;
    							break;
    					case 8: board[2][1] = turn + 1;
    							break;
    					case 9: board[2][2] = turn + 1;
    							break;
    			}
    			switch(turn)
    			{
    				case 0: turn = 1;
    						break;
    				case 1: turn = 0;
    						break;
    			}
    		}while(win == 0);
    	}while(p1 < 5 && p2 < 5);
    }
    Bear with me on the amateur-ish and inefficient coding.
    May anyone tell me what's making it loop like that? and a solution?
    And feel free to make suggestions to shorten my code. nothing to complicated, and only in C please. All the stuff I've used there is pretty much all that I've learned so far.

  2. #2
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Why do you have to while-do loops? You can make one as
    Code:
    do {
        ...
    } while (win == 0 && p1 < 5 && p2 < 5);
    So if win = 1 it will exit. If p1 >=5 or p2>=5 it will exit.

    Also, win doesn't seem to be necessary variable. You win, you empty the board, you start again. Isn't that true?
    Then you break from the first do-while loop and continue on the outer do-while. Then win stays 1 for ever. You should skip win if you want this behavior.

    So just keep the outer loop.

    I know I am not answering the real question

    Try adding at the end of the do-while
    Code:
    printf("\n %d %d\n", p1, p2);
    to check those two values and see why they don't get incremented. Use printfs in general to get an output and check the flow of your program. It is better to use a debugger of course, but I am guessing you don't have one.

  3. #3
    Registered User
    Join Date
    Jun 2010
    Posts
    11
    I forgot to state that the game only ends when one person has won 5 games Sorry.

    Which do-while did you mean? Tried adding the one you said right after the inner do-while and now, it really was an infinite loop.

    Concerning the debugger, I'm using Pelles C and I have the debugger thingies enabled(i think).
    I never learned how to use it. We weren't taught how to use it(yet, hopefully) in class.

    edit:
    saw what you said about the win variable staying at 1, added a win = 0; right after the inner loop and it still doing that continuous thingy until it ends.
    Last edited by nirvana619; 06-30-2010 at 02:26 PM.

  4. #4
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    OK, leave the program as you posted it and replace
    Code:
    printf("Player 2 won!\n");
    printf("Player 1 won!\n");
    with
    Code:
    printf("Player 2 games won!\nCurrent Score %d - %d\n", p1, p2);
    printf("Player 1 games won!\nCurrent Score %d - %d\n", p1, p2);
    respectively and tell us the output. Do p1 and p2 increase as they should?

  5. #5
    Registered User
    Join Date
    Jun 2010
    Posts
    11
    So I removed system("cls"); for a clearer look. The first output added to 2 to both p1 and p2 alternately until p1 won.

    I found out that I had a duplicate code that added twice to the score so i removed that. Still the same behavior, adding 1 alternately to p1 and p2 until p1 won.

    The question is, why does it not ask the 2nd player for a move? I saw that the move variable never resetted itself... You know what? I'll just post the code.

    Code:
    int main(void)
    {
    	int board[3][3] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
    	int turn = 0, move = 0, win = 0, p1 = 0, p2 = 0;
    	int i, j;
    	do
    	{
    		do
    		{
    			system("cls");
    			printf("TIC TAC TOE IN C\n\n");
    			gameboard(board);
                            /* There was an extra if code here with a duplicate p1 and p2++, removed it*/
    			move = 0; /*added this so it stops that stupid loop.*/
    			if(checkDiag(board) == 1 || checkNondiag(board) == 1)
    				switch(turn)
    				{
    					case 0: p2++;
    						      break;
    					case 1: p1++;
    					             break;
    				}
    			printf("\nPlayer 1(X): %d\nPlayer 2(O): %d\n\n", p1, p2);
    			if(checkDiag(board) == 1 || checkNondiag(board) == 1)
    				switch(turn)
    				{
    					case 0: printf("Player 2 games won!\nCurrent Score %d - %d\n", p1, p2);;
    							win = 1;
    							for(i=0;i<3;i++)
    								for(j=0;j<3;j++)
    									board[i][j] = 0;
    							break;
    					case 1: printf("Player 1 games won!\nCurrent Score %d - %d\n", p1, p2);;
    							win = 1;
    							for(i=0;i<3;i++)
    								for(j=0;j<3;j++)
    									board[i][j] = 0;
    							break;
    				}
    			printf("Player %d's turn!\n", turn + 1);
    			printf("What space would you like to use? ");
    			while(move < 1 || move > 9)
    			{
    				scanf("%d", &move);
    				if( move < 1 || move > 9)
    					printf("Invalid coordinates. Please enter another: ");
    			}
    			switch(move)
    			{
    					case 1: board[0][0] = turn + 1;
    							break;
    					case 2: board[0][1] = turn + 1;
    							break;
    					case 3: board[0][2] = turn + 1;
    							break;
    					case 4: board[1][0] = turn + 1;
    							break;
    					case 5: board[1][1] = turn + 1;
    							break;
    					case 6: board[1][2] = turn + 1;
    							break;
    					case 7: board[2][0] = turn + 1;
    							break;
    					case 8: board[2][1] = turn + 1;
    							break;
    					case 9: board[2][2] = turn + 1;
    							break;
    			}
    			switch(turn)
    			{
    				case 0: turn = 1;
    						break;
    				case 1: turn = 0;
    						break;
    			}
    		}while(win == 0);
    		win = 0;
    	}while(p1 < 5 && p2 < 5);
    
    }
    Now the game's screwed up Now that it's asking for turns, I played continously. At the first few moves, the board cleared. Then after a few more moves, player 1 won. i entered 1, 2, 3 , 4, 5 ,6 alternately to both players, so no one should've won. I guess the function i used to check who's won is also screwed up.

  6. #6
    Registered User
    Join Date
    Apr 2007
    Posts
    51
    I don't see where you set win back to zero after a game.

    Ninja'd!

  7. #7
    Registered User
    Join Date
    Apr 2007
    Posts
    51
    Correct me if I am wrong, but you check for a winner
    Code:
    if(checkDiag(board) == 1 || checkNondiag(board) == 1)
    then have one of them take a turn.
    Code:
    while(move < 1 || move > 9)
    			{
    				scanf("%d", &move);
    				if( move < 1 || move > 9)
    					printf("Invalid coordinates. Please enter another: ");
    			}
    			switch(move)
    Wouldn't you want to do that the other way around?

    Plus, what heppens in
    Code:
    switch(turn)
    			{
    				case 0: turn = 1;
    						break;
    				case 1: turn = 0;
    						break;
    			}
    if turn ==2?
    Last edited by markcole; 06-30-2010 at 03:04 PM.

  8. #8
    Registered User
    Join Date
    Jun 2010
    Posts
    11
    I don't see where you set win back to zero after a game.

    Ninja'd!
    It's right here:

    Code:
    switch(turn)
    			{
    				case 0: turn = 1;
    						break;
    				case 1: turn = 0;
    						break;
    			}
    		}while(win == 0);
    		win = 0; <------------------------------|Right Here|
    	}while(p1 < 5 && p2 < 5);
    Wouldn't you want to do that the other way around?
    Concerning the arrangement of the code, it's logical that the game board updates itself after every move.

    So, let's assume that my program works and we're at the 5th turn(minimum amount of moves for someone to win).

    After the player takes his/her turn, the first switch records the move into the game board then the second switch switches the players' turns.

    The loop restarts, game board shows the 5th move, then it checks to see if anyone has won. If anyone won, it shows Player %d won! then ends the inner loop immediately.

    Then the board array gets all its values back to 0 and start the game again.

    If that's faulty logic, please help me fix it.

    edit:
    if turn ==2?
    turn is a pseudo-boolean variable. only switches from 0 and 1. Notice that there is no other code that changes turn's value aside from that switch code

  9. #9
    Registered User
    Join Date
    Apr 2007
    Posts
    51
    Quote Originally Posted by nirvana619 View Post

    Concerning the arrangement of the code, it's logical that the game board updates itself after every move.

    So, let's assume that my program works and we're at the 5th turn(minimum amount of moves for someone to win).

    After the player takes his/her turn, the first switch records the move into the game board then the second switch switches the players' turns.

    The loop restarts, game board shows the 5th move, then it checks to see if anyone has won. If anyone won, it shows Player %d won! then ends the inner loop immediately.

    Then the board array gets all its values back to 0 and start the game again.

    If that's faulty logic, please help me fix it.

    edit:


    turn is a pseudo-boolean variable. only switches from 0 and 1. Notice that there is no other code that changes turn's value aside from that switch code
    I ran it and player 1 won on the first move every time by selecting position 1, so I think there is an error on how you determine the winner.

    As for the logic, it is fine, but if I win 5 rounds, the game should end. The way it is written, it starts another game even after I win 5 rounds and then ends. It isn't "wrong" per se, but I would do it a bit different.

    For the "turn" variable, I just read it wrong and thought you were incrementing it, but you are not.

  10. #10
    Registered User
    Join Date
    Jun 2010
    Posts
    11
    The way it is written, it starts another game even after I win 5 rounds and then ends. It isn't "wrong" per se, but I would do it a bit different.
    Yes you're right. :| A friend helped me and now the game's up and running except for that error you have specified. After someone reaches 5 wins, it still asks the other player for a move, then ends the game.

    May anyone help me with that?
    Credits to Ken Russell for the revision of my Non diag functions as well as the fixing the part it went wrong when checking the winner.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    int checkDiag(int board[3][3])
    {
    	if(board[1][1] == board[0][0] && board[1][1] == board[2][2])
    		return 1;
    	else if(board[1][1] == board[0][2] && board[1][1] == board[2][0])
    		return 1;
    	return 0;
    }
    int checkNondiag(int board[3][3])
    {	
    	int k;	
    	for (k=0; k<3; k++)
        {
            if (board[k][1]==board[k][0] && board[k][1]==board[k][2])
            return 1;
        }
        for (k=0; k<3; k++)
        {
            if (board[1][k]==board[0][k] && board[1][k]==board[2][k])
    	    return 1;
        }
    }
    void gameboard(int board[3][3], int p1, int p2)
    {
    	int i, j;
        printf("TIC TAC TOE IN C\n\n");
    	printf("\nPlayer 1(X): %d\nPlayer 2(O): %d\n\n", p1, p2);
    	printf(" - - - \n|1|2|3|\n - - - \n|4|5|6|\n - - - \n|7|8|9|\n - - - \n\n");
    	printf(" - - - \n");
    	for(i=0;i<3;i++)
    	{
    		printf("|");
    		for(j=0;j<3;j++)
    		{
    			switch(board[i][j])
    			{
    				case 1: printf("X|");
    						break;
    				case 2: printf("O|");
    						break;
    				default: printf(" |");
    			}
    		}
    		printf("\n - - - \n");
    	}
    }
    int main(void)
    {
    	int board[3][3] = {10, 20, 30, 40, 50, 60, 70, 80, 90};
    	int turn = 0, move = 0, win = 0, p1 = 0, p2 = 0;
    	int i, j;
    	do
    	{
    		do
    		{
    			system("cls");
    			gameboard(board, p1, p2);
    			move = 0;
    			if(checkDiag(board) == 1 || checkNondiag(board) == 1)
    				switch(turn)
    				{
    					case 0: p2++;
    						      break;
    					case 1: p1++;
    					             break;
    				}
    			if(checkDiag(board) == 1 || checkNondiag(board) == 1)
    			{	system("cls");
    				win = 1;
    				gameboard(board,p1,p2);
                  		switch(turn)
    				{
    					case 0: printf("Player 2 won this round!\n", p1, p2);
    							system("Pause");
    							break;
    					case 1: printf("Player 1 won this round!\n", p1, p2);
    							system("Pause");
    							break;
    				}
    				system("cls");
    					for(i=0;i<3;i++)
    						for(j=0;j<3;j++)
          						board[i][j] = (i*10)+(j*20); 
    					gameboard(board,p1,p2);
    			}
    			printf("Player %d's turn!\n", turn + 1);
    			printf("What space would you like to use? ");
    			while(move < 1 || move > 9)
    			{
    				scanf("%d", &move);
    				if( move < 1 || move > 9)
    					printf("Invalid coordinates. Please enter another: ");
    			}
    			switch(move)
    			{
    					case 1: board[0][0] = turn + 1;
    							break;
    					case 2: board[0][1] = turn + 1;
    							break;
    					case 3: board[0][2] = turn + 1;
    							break;
    					case 4: board[1][0] = turn + 1;
    							break;
    					case 5: board[1][1] = turn + 1;
    							break;
    					case 6: board[1][2] = turn + 1;
    							break;
    					case 7: board[2][0] = turn + 1;
    							break;
    					case 8: board[2][1] = turn + 1;
    							break;
    					case 9: board[2][2] = turn + 1;
    							break;
    			}
    			switch(turn)
    			{
    				case 0: turn = 1;
    						break;
    				case 1: turn = 0;
    						break;
    			}
    		}while(win == 0);
    		win = 0;
    	}while(p1 < 5 && p2 < 5);
        if(p1==5)
          printf("\nPlayer 1 has won the game!\nThank you for playing!\n");
        else
          printf("\nPlayer 2 has won the game!\nThank you for playing!\n");
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Why does this code produce infinite loop?
    By matchkop in forum C Programming
    Replies: 15
    Last Post: 05-25-2010, 09:52 AM
  2. Using while produces an infinite loop...
    By UCF43 in forum C Programming
    Replies: 4
    Last Post: 04-01-2010, 04:47 PM
  3. Replies: 2
    Last Post: 06-14-2009, 11:24 PM
  4. Cosine fucntion and infinite loop.
    By youareafever in forum C Programming
    Replies: 2
    Last Post: 11-07-2008, 04:45 AM
  5. Switch statement = infinite loop
    By Lucid003 in forum C++ Programming
    Replies: 10
    Last Post: 10-10-2005, 12:46 AM