2

I'm trying to create a dynamic char array which will contain numbers then change these to either a X or 0,

I'm creating a tic tac toe game which creates a grid to a specific number you want, the array needs to contain all numbers for the squares and then change this number to either a X,0 depending on player,

I currently have;

const int grid_size = size * size; // determines the size of the grid height x width
char **number = new char*[grid_size]; // create the array to the size of the grid

for ( int i = 1; i <= grid_size+1; i++ ) {
    number[i] = i;
}

but with this I get a error:- error C2440: '=' : cannot convert from 'int' to 'char *' on line number[i] = i;

how would I create the array to contain the numbers - 1,grid_size, the change these numbers to either a X,0 ?

Lain
  • 2,166
  • 4
  • 23
  • 47
nats0128
  • 509
  • 5
  • 18
  • 1
    lets start with a more serious problem which is your indexing. start from 0 to gridsize - 1 or else whole hell will break loose – giorashc Apr 10 '13 at 08:13
  • i started at 1 so the first mark on the grid is a 1, or else it will be a 0 and since im using 0 dotn want my players to get confused, – nats0128 Apr 10 '13 at 08:20
  • 2
    @nats0128: The point is that declaring an array `number[grid_size]` will give you `number[0]` through `number[grid_size - 1]`, and accessing `number[grid_size]` (as you are doing inside the loop) will make your program crash (if you are lucky). Zero-based indexing is not optional in C/C++. – DevSolar Apr 10 '13 at 08:22
  • I wonder how it should affect the players, how you use the arrays under the hood? Separate UI from implementation – Arne Mertz Apr 10 '13 at 08:58

5 Answers5

2

I think you don't have to store the cell indides in your array. You just use them for printing the current grid to the user, right? What about this solution:

enum class Marker { PlayerX, PlayerO, None };

class TicTacToeGrid
{
public:
     TicTacToeGrid(size_t size) :
         grid(size* size, Marker::None), size(size)
     {}

     void Set(size_t cellId, Marker player)
     {
         if (cellId < 1 || cellId >= size * size)
             throw std::runtime_error("invalid cell");
         if (grid[cellId - 1] != Marker::None)
             throw std::runtime_error("cell is not free");

         grid[cellId - 1] = player;
     }

     Marker Get(size_t cellId) const
     {
         return grid[cellId - 1];
     }

     void Print(std::ostream& os) const
     {
         for(size_t row = 0; row < size; ++row)
         {
             for (size_t col = 0; col < size; ++col)
             {
                 size_t index = size * row + col;
                 os << CellContent(index) << "\t";
             }
             os << "\n";
         }
     }

     std::string CellContent(size_t index) const
     {
        Marker marker = grid[index];
        switch(marker)
        {
        case Marker::PlayerX:
            return "X";
        case Marker::PlayerO:
            return  "O";
        case Marker::None:
            // If it's not X or O let's show the cell index.
            return std::to_string(index + 1);
        }
     }

private:
     std::vector<Marker> grid;
     size_t size;
};


int main()
{
    TicTacToeGrid grid(3);
    grid.Print(std::cout);

    grid.Set(1, Marker::PlayerO);
    grid.Set(2, Marker::PlayerX);

    grid.Print(std::cout);
}
hansmaad
  • 18,417
  • 9
  • 53
  • 94
0
char **number = new char*[size]; // create the rows

for ( int i = 0; i < size; i++ ) {
   number[i] = new char[size]; // create the columns for the current row
   for (int j = 0; j < size; j++) {
      number[i][j] = (char)i*j; // set the cell number 
   }
}

Please note that i haven't coded in c++ in a big while so I might have some syntax problems. But this is the way to do it.

giorashc
  • 13,691
  • 3
  • 35
  • 71
  • you leak memory. and no, adding `delete`s will not help, you still leak memory (in case of exceptions) – Arne Mertz Apr 10 '13 at 09:01
  • @Arne I am not going to add delete nor attend this problem because I am not going to solve all OP problems espcially if not related to his specific problem. I expect him to know how to handle memory allocations and if he can't he should state it – giorashc Apr 10 '13 at 10:35
  • and I clearly stated about my c++ experience so no need to push it further. – giorashc Apr 10 '13 at 10:36
0

The correct way is ....

#define Row_num 3
#define Col_num 3
char **number = new char*[Row_num];

for(int i=0;i<Row_num;i++){
    number[i] = new char[Col_num];
    for(int j=0;j<Col_num;j++){
        number[i][j] = j;
    }
}

By this line

 char **number = new char*[Row_num];

you actually create an array of pointers. So you can't do this assignment ...

number[i] = i;

Since number[i] holds a pointer to an array .

palatok
  • 1
  • 1
0

First of all, if you need an array of numbers, you should use int* number = new int[grid_size], and definitely not char** (as you would if you were storing character strings).

Second, even if you want the numbers to go from 1 to grid_size, the array indexes you are storing them in should still be in range 0..grid_size-1, otherwise you will be accessing a non-existing element.

const int grid_size = size * size; // determines the size of the grid height x width
int *number = new int*[grid_size]; // create the array to the size of the grid

for ( int i = 0; i < grid_size; i++ ) {
    number[i] = i + 1;
}
riv
  • 6,846
  • 2
  • 34
  • 63
0

You have two solutions: create an array of arrays to store your characters (that's what a matrix is fundamentally), or create a single array of char which would be the linearized version of the matrix, ie. an array containing all the rows of the matrix put together in one.

The first case is trivial:

const int grid_size = size * size; // determines the size of the grid height x width
char **number = new char*[size]; // create the array to the size of the grid

for ( int i = 0; i < size; i++ ) {
    number[i] = new char[grid_size];
    for( int j = 0; j < size; j++)
         number[i][j] = i * size + j;
}

// access any char with a double bracket notation
// beware that coordinates start at `0`
number[2][1] = 'X';

The second solution is trickier, and I recommend using a helper function to translate matrix coordinates into the array index:

const int grid_size = size * size;

int idx(int x, int y){
    return y * size + x;
}

char *number = new char[grid_size];

for (int i = 0; i < grid_size; i++)
    number[i] = i;

number[idx(2,1)] = 'O';

Characters are actually numbers in disguise, but with values way above 9, so for a regular tic-tac-toe game it should not be a problem, and you should be able to have it work with size up to 8*8. Starting from 65, the numbers start representing regular alphabet characters (ie. 65 is A, 66 is B and so on, look up the ASCII code table for more details). One way to overcome the issue, if you want to store the cell number in the cell and also keep track of the state of the game, is to use 254 and 255 as the values denoting the player moves, instead of O and X, but you will still be limited to a 7*7 grid size.

For larger size, you will probably need consider another data structure to track the game state.

didierc
  • 14,572
  • 3
  • 32
  • 52