Thread: while loop

  1. #1
    Registered User
    Join Date
    Nov 2007
    Posts
    164

    while loop

    Code:
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    // global constants
    const char X = 'X';
    const char O = 'O';
    const char EMPTY = ' ';
    const char TIE = 'T';
    const char NO_ONE = 'N';
    
    // game function's prototypes
    void displayBoard(const vector<char>& board); // function that displays the game board
    char choosePiece(); // function to let the user choose their pieces
    char winner(const vector<char>& board); // determines the game winner
    char firstMove(const char& player1, const char& player2); // function that determines who makes the first move
    int playerOneMove(const vector<char>& board); // returns the move of player1
    int playerTwoMove(const vector<char>& board); // returns the move of player2
    bool moveLegal(const vector<char>& board); // determines whether a move is legal
    
    int main()
    {
    	// vector that holds the game board
    	vector<char> board(9, EMPTY); // there are only 9 positions in a tic-tac-toe board so a vector with 9 elements is fine
    	//and initialized all elements with the EMPTY char
    
    	// show the instructions
    	// this is how the board would look like
    	cout << "\n\n" << 0 << " | " << 1 << " | " << 2 << endl;
    	cout << "---------" << endl;
    	cout << 3 << " | " << 4 << " | " << 5 << endl;
    	cout << "---------" << endl;
    	cout << 6 << " | " << 7 << " | " << 8 << endl;
    
    	cout << "\n\nThe above is the game board" << endl;
    	cout << "To put your piece in the center of the game board, enter number 4."
    	 	 << "\nTo put your piece elsewhere in the board, then enter its corresponding position"
    	 	 << "\nnumber as illustrated in the diagram above" << endl;
    
    
    
    	char player1, player2;
    	player1 = choosePiece();
    
    	// player1 has chosen its piece now chose the opposite piece of player1 for player2
    	if (player1 == 'X')
    	{
    		player2 = 'O';
    	}
    	else {
    		player2 = 'X';
    	}
    
    	cout << "\n\nPlayer 1's piece is " << player1 << endl;
    	cout << "Player 2's piece is " << player2 << endl;
    
    	char turn; // variable to store whose turn it is
    
    	turn = firstMove(player1, player2); // who goes first, returns either X or O
    
    	cout << "Good luck to both of the players!" << endl;
    	board[0] = X;
    
    	// while nobody has one the game and its not a tie
    	while (winner(board) == NO_ONE)
    	{
    		int move;
    
    		if (turn == player1)
    		{
    			move = playerOneMove(board);
    		}
    	}
    }
    
    void displayBoard(const vector<char>& board)
    {
    	cout << "\n\n" << board[0] << " | " << board[1] << " | " << board[2] << endl;
    	cout << "---------" << endl;
    	cout << board[3] << " | " << board[4] << " | " << board[5] << endl;
    	cout << "---------" << endl;
    	cout << board[6] << " | " << board[7] << " | " << board[8] << endl;
    
    }
    
    char choosePiece()
    {
    	cout << "\n\nPiece 1 = X" << endl;
    	cout << "Piece 2 = O" << endl;
    
    	char piece;
    
    	cout << "Enter a number to choose your piece [1-2]: " << endl;
    	cin >> piece;
    
    	if (piece == '1')
    	{
    		return X;
    	}
    	else {
    		return O;
    	}
    }
    
    char winner(const vector<char>& board)
    {
    	// multi-dimensional array that holds all possible winning rows
    	int WINNING_ROWS[8][3] = { {0, 1, 2},
    							   {3, 4, 5},
    							   {6, 7, 8},
    							   {0, 3, 6},
    							   {1, 4, 7},
    							   {2, 5, 8},
    							   {0, 4, 8},
    							   {2, 4, 6} };
    
    	const int TOTAL_ROWS = 8; // there are only 8 possible winning rows
    
    	// check to see if any winning row has three values that are the same and not empty
    	// then we have a winner and return the value of that row ( either X or O )
    	for (int i = 0; i < TOTAL_ROWS; i++)
    	{
    		if (board[WINNING_ROWS[i][0]] != EMPTY &&
    			board[WINNING_ROWS[i][0]] == board[WINNING_ROWS[i][1]] &&
    			board[WINNING_ROWS[i][1]] == board[WINNING_ROWS[i][2]])
    			{
    				return board[WINNING_ROWS[i][0]];
    			}
    	}
    
    	// since no body has won, check for a tie, that is there are no empty squares left
    	const int NUM_OF_POSITIONS = 9; // number of square in the game board
    	int emptyPositions = 0;
    
    	for (int i = 0; i < NUM_OF_POSITIONS; i++)
    	{
    		if (board[i] == EMPTY)
    		{
    			emptyPositions++;
    		}
    	}
    
    	// if there are no empty positions left in the board then the game is a tie
    	if (emptyPositions == 0)
    	{
    		return TIE;
    	}
    	else {
    		return NO_ONE; // it's neither a tie nor any player has won the game yet, the game is still remaining
    	}
    }
    
    char firstMove(const char& player1, const char& player2)
    {
    	char move;
    
    	cout << "\n\nWho will make the first move? " << player1 << " or " << player2 << " ?" << endl;
    	cout << "Enter "<< player1 << " or " << player2 << " : ";
    	cin >> move;
    
    
    
    	return toupper(move);
    }
    
    int playerOneMove(const vector<char>& board)
    {
    	int move;
    	do
    	{
    		cout << "Where will you move?" << " (0-" << board.size() - 1 << "): ";
    		cin >> move;
    	} while ((!(move >= 0 && move <= 8)) && (board[move] != EMPTY));
    	
    	cout << board[0];
    	cout << "\nExiting playerOneMove function" << endl;	
    }
    I don't know whats wrong with my do...while loop, its the one at the last function

    What I want is that it only exits if the move is between 0-8 and and that the board[move] is EMPTY, well when creating the the vector board I initialized all of its element to EMPTY but after then I initialized the board[0] to X now when at the do...while loop at my last function I enter 0 it exits the loop ? Why ? It shouldn't, because board[0] is equal to X not EMPTY the first condition in the do...while loop is working correctly but not the second one.

    What am I doing wrong ?

    EDIT: Sorry for the wrong thread name it should be Do...While loop problem
    Last edited by manzoor; 08-12-2008 at 06:11 AM.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    What I want is that it only exits if the move is between 0-8 and and that the board[move] is EMPTY
    So, if (move >= 0 && move <= 8) and board[move] == EMPTY you want to exit the loop. Therefore take the negation of that expression, and you get !((move >= 0 && move <= 8) && board[move] == EMPTY). This is equivalent to !(move >= 0 && move <= 8) || board[move] != EMPTY (note the || instead of &&).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    your condition is equivalent to
    Code:
    (move < 0 || move > 8) && (board[move] != EMPTY)
    so when move == 0 - first part is false - and second part is not checked

    note also that for the move == -1 first condition will be true - and you will get outof bounds access when checking the second part
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  4. #4
    Registered User
    Join Date
    Nov 2007
    Posts
    164
    Ok thanks laserlight and vart

    @laserlight:your solution works perfectly everything is as I expected, but i dont understand why the || instead of &&, I want both of the conditions to be true not only one

    Code:
    while ((!(move >= 0 && move <= 8)) && (board[move] != EMPTY))
    Doesn't my condition says this:
    That While move is not greater than or equal to 0 and move is not less than or equal to 8 and board[move] (in my case board[0]) is not equal to EMPTY continue looping.

    When move is 0, then it is greater than 0 and is equal to 0 ( this means the first condition becomes false) and board[move] is is not equal to EMPTY, that is the second condition is still true, it should continue looping but it doesn't and it exits
    Last edited by manzoor; 08-12-2008 at 06:43 AM.

  5. #5
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    if you have problems reading complex conditions - make it simple
    Code:
    for(;;)
    {
        cout << "Where will you move?" << " (0-" << board.size() - 1 << "): ";
        cin >> move;
        if(move < 0 || mov >= board.size() )
        {
            cout << "wrong input - try again" << endl;
        }
        else if (board[move] != EMPTY)
        {
           cout << "place taken - choose another" << endl;
        }
        else
        {
            break;
        }
    }
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by vart View Post
    if you have problems reading complex conditions - make it simple
    Code:
    for(;;)
    {
        cout << "Where will you move?" << " (0-" << board.size() - 1 << "): ";
        cin >> move;
        if(move < 0 || mov >= board.size() )
        {
            cout << "wrong input - try again" << endl;
        }
        else if (board[move] != EMPTY)
        {
           cout << "place taken - choose another" << endl;
        }
        else
        {
            break;
        }
    }
    Not only is this easier to write, but it is also easier for others to understand, which helps EVERYONE. I hate it when you find a really complicated condition in a loop. It is much better if the code is clearer. And the error messages are now clearly indicating what is wrong with the move too.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Registered User
    Join Date
    Nov 2007
    Posts
    164
    But they said that:
    Some programmers feel that break and continue violate structured programming. The effects of these statements can be achieved by structured programming techniques. Most programmers consider the use of break in switch statements acceptable.
    I may have problem reading complex conditions, in fact I have problem. But I request you to explain me the problem with my condition, as I didn't got the point. So in future I may avoid things like this
    Last edited by manzoor; 08-12-2008 at 07:29 AM.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I do agree that break and continue can lead to spaghetti-code too. You could, instead of using break, use a "done = 1;", [initializing with "done = 0" before the loop], and use "while(!done)" or some similar construct.

    You just have to break it down:
    Code:
    while ((!(move >= 0 && move <= 8)) && (board[move] != EMPTY))
    Becomes:
    Code:
    !(move >= 0 && move <= 8)
    So that is true if move is less than 0 or greater than 8.

    Code:
    board[move] != EMPTY
    True if board[move] is not EMPTY

    For the whole condition to be true, both conditions need to be true. In this case, that's undefined, since if move is out of range, board[move] is undefined (and should not be tested). You need to continue if the move is out of range OR the board position isn't empty.


    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Nov 2007
    Posts
    164
    Well one more thing to ask

    Look at my last function it is supposed to return an int but it doesn't even though I'm able to compile it fine why ?

  10. #10
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by manzoor View Post
    Well one more thing to ask

    Look at my last function it is supposed to return an int but it doesn't even though I'm able to compile it fine why ?
    Because you haven't got enough warnings enabled?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  11. #11
    Registered User
    Join Date
    Nov 2007
    Posts
    164
    Yup, Code::Blocks didn't detected it, but Visual Studio did

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Yup, Code::Blocks didn't detected it, but Visual Studio did
    In Code::Blocks, go to Project -> Build Options and check "Enable all compiler warnings". You may also wish to check "Enable warnings demanded by strict ISO C and ISO C++".
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. nested loop, simple but i'm missing it
    By big_brother in forum C Programming
    Replies: 19
    Last Post: 10-23-2006, 10:21 PM
  2. While loop misbehaving (or misunderstanding)
    By mattAU in forum C Programming
    Replies: 2
    Last Post: 08-28-2006, 02:14 AM
  3. loop in a linked linked lists
    By kris.c in forum C Programming
    Replies: 6
    Last Post: 08-26-2006, 12:38 PM
  4. while loop help
    By bliznags in forum C Programming
    Replies: 5
    Last Post: 03-20-2005, 12:30 AM
  5. loop issues
    By kristy in forum C Programming
    Replies: 3
    Last Post: 03-05-2005, 09:14 AM