Question

Last week I've make an assignment in which we had to code a Tic-Tac-Toe game using a 3*3 board. Now, I am trying to do by myself the same game but with a player's customizable board size.

I ask the user for the quantity of rows and columns hw wishes, I correctly create the game board and print this one using my << overloader function. Everything seems to be okay. BUt when I try to do a movement(place a mark in the board), the x and y coordinates passed by the user does not match with what we see on screen.

I do not know if the error comes from my SetPosition() or AtPosition(). This is the first time I deal with this kind of array, so I hope someone can help me. (sorry for my bad english)

There you have my driver file and my GameBoard.h and .cpp If you need more infomration, ask me.

    #include "GameBoard.h"
    #include <iostream> /*cout, cin*/
    #include <stdlib.h> /* rand, srand */
    #include <time.h>   /* time        */

    using namespace std;

    // ************Prototypes*************
    int RandomInt(int low, int high); // generate a random number
    // ***********************************


    int main(void)
    {
        // *************Variables************
        int x_size;                 // the user decide of the size of the board
        int y_size;                 // the user decide of the size of the board
        int x_player;               // the user x-coordinate
        int y_player;               // the user y-coordinate
        int ID_player = 1;          // player ID
        int x_computer;             // the computer x-coordinate
        int y_computer;             // the computer y-coordinate 
        int ID_computer = 2;        // computer ID  
        int keepplaying = 0;        // use this for game loop until we do not have the check win function
        // **********************************
        srand(time(0));

        // ask to the user which size he wants to use
        cout << "Welcome to my Tic Tae Toe Game!" << endl;
        cout << "What size do you want?" << endl;
        cout << "Insert number of rows" << endl;
        cin >> x_size;
        cout << "Insert number of columns" << endl;
        cin >> y_size;

        cout << "This is the GameBoard we are using" << endl;

        // create the GameBoard    
        Board myBoard(x_size, y_size);
        // set all the array to 0
        myBoard.ResetBoard();
        // prints the 2D array
        cout << myBoard << endl;

        cout << "You are the player 1 and you play against the computer (number 2). Good Luck!" << endl;

        do
        {

            // ask to the user the coordinates in which he wants to place the mark
            do
            {
                cout << "Player 1 turn! " << endl;
                cout << "Insert x coordinate: ";
                cin >> x_player ;
                cout << "Insert y coordinate: ";
                cin >> y_player ;
            }
            while( (x_player < 0 || x_player > x_size) || (y_player < 0 || y_player > y_size) || myBoard.AtPosition(x_player, y_player) != 0 );
            // while the cell is not available or the coordinates are not valide
            myBoard.SetPosition(x_player, y_player , ID_player); // the mark has been placed

            // print the move
            cout << myBoard << endl; 
            cout << "End of turn!" << endl;

            // The computer place a mark: the x and y coordinates are randomly generated
            cout << "Computer Turn:" << endl;
            do
            {
                x_computer = RandomInt(0,x_size);
                y_computer = RandomInt(0,y_size);
            }while(myBoard.AtPosition(x_computer, y_computer) != 0);
            myBoard.SetPosition(x_computer, y_computer, ID_computer);
            cout << myBoard << endl; 

        }while(keepplaying != 1) ;         

        //return 0;
    }

    // This function create a random number
    int RandomInt(int low, int high)
    {
      int number = rand() % (high - low + 1) + low;
      return number;
    }

This is the main.cpp, it will ask for user's data and then call the function declared and defined in my class Board

    #include <iostream> /*cout, cin, ostream*/

    class Board
    {
        public:
       /* Board()
        { 
            x = 3;
            y = 3;
            //player_ID = 1;
            //computer_ID = 2;

        }*/
        Board(int x_, int y_); // non-default constructor



        void SetPosition(int x, int y, int player);     // Place a mark
        int AtPosition(int x, int y);                   // return the ID of the cell
        void ResetBoard(void);                        // set all the array to be 0

        friend std::ostream& operator<<(std::ostream &os, const Board &rhs); // overload the << operator

        private:    
        int x;                              // x-coordinates
        int y;                              // y-coordinates
        int *board;                    // contains the board in a 2D array (3*3 gameboard)


        int player_ID;                         // player ID 
        int computer_ID;                        // computer ID

    };

There you have my header file for my class

    #include "GameBoard.h"

    // non-default constructor
    Board::Board(int x_, int y_)
    {
        x = x_;
        y = y_;    
        board = new int[x*y];
    }
    // Goes through the board array and set all the ID to 0
    void Board::ResetBoard()
    {
        for(int i = 0; i < x*y; i++)
        {
            board[i] = 0;      
        }
    }

    // returns the ID of the passed cell
    int Board::AtPosition(int x, int y)
    {
       return board[x*y];
    }

    // put a mark in the cell and return true
    void Board::SetPosition(int x, int y, int player_ID)
    {
        board[x*y +x] = player_ID;
        //value = pd[row * 4 + column];
    }

    std::ostream& operator<<(std::ostream &os, const Board &rhs)
    {
      for (int i = 0; i < rhs.x*rhs.y; i++)
      {


        if(i % rhs.y == 0)
        {
          os << std::endl;
        }
        os << rhs.board[i]; 

      }   
        return os;
    }

I hope that everything is clear and well comented

Was it helpful?

Solution

So in your Board class you have:

// returns the ID of the passed cell
int Board::AtPosition(int x, int y)
{
   return board[x*y];
}

// put a mark in the cell and return true
void Board::SetPosition(int x, int y, int player_ID)
{
    board[x*y +x] = player_ID;
    //value = pd[row * 4 + column];
}

So you're using x and y as you parameter names which are shadowing the x and y class members. You need to think about what you are trying to do. For a 3 x 3 array you have:

0 1 2
3 4 5
6 7 8

In your code it seems you intend to use x as the column number and y as the row number (but not consistently, so I can't be sure). So for x=1 and y=2 your index is 5. So how do you calculate that? You have:

board[x*y +x] = player_ID;

You need (something like):

board[this->x*y +x] = player_ID;

And also in AtPosition you need:

return board[this->x*y +x];

But I would recommend re-naming your vars to avoid shadowing. Maybe the member vars would be better called xsize/ysize or xlen/ylen.

Also in operator<< you have:

if(i % rhs.y == 0)
{
    os << std::endl;
}
os << rhs.board[i]; 

Which I think needs to be:

if(i % rhs.x == 0)
{
    os << std::endl;
}
os << rhs.board[i]; 

(Because I'm guessing rhs.x is the width, but if it's not, you have other code that's wrong.)

OTHER TIPS

First off, the functionality for this class is all messed up. If you were to create a board dynamically in memory you can access it directly. When you are calling the std::ostream function, you should simply just create a function called show. Here is some code to help explain a bit clearer.

include "GameBoard.h" #include "Player.h"

   int main() {    GameBoard* board = new GameBoard;    board->show();    Player* player = new Player(board);//passing a pointer to a pointer this is called    //dynamic passing which allows a class to manipulate another with a class    int* row = new int;    int* col = new int;    row = 1 , col = 1; //the middle spot on 3x3 board    player->setPiece(row,col);//now the player class would control the rest    delete col; delete row; delete player;//delete all but the board    board->show();//the players piece would still be there this is what dynamic pass-    //ing can do    delete board;    return 0; }

If done right the player uses a pointer to a board to control and manipulate it within it's own class. This is called data abstraction and allows functionality within classes and in the show function, use cout, don't reference to ostream. It's bad programming practice and can lead to terrible errors all over the program. Trust me i learned the hard way too lol. anyway practice this material and you will become a genius in writing almost any program. And always remember, this is OOP(Object Oriented Programming) not, PP(procedral programming) .

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top