2

I am trying to make a tic tac toe game in C++. I am trying to use a 2d char array to construct the board, but when my code below goes to compile, I get an error error: cannot convert '<brace-enclosed initializer list>' to 'char' in assignment

Below is the code:

#include <iostream>
#include <string>
#include <cstdlib>

using namespace std;

// Player Class
class Player
{
    public:
    explicit Player(string name){
        this->name = name;
    }

    string getName(){
        return name;
    }

    string setName(string newname){
        name = newname;
    }

    int generateRowMovement(){
        int row = rand() % 2; // Random number between 0 and 2
        return row;
    }

    int generateColMovement(){
        int col = rand() % 2; // Random number between 0 and 2
        return col;
    }

    int placeMove(){
        int rowMove, colMove;
        rowMove = rand() % 2;
        colMove = rand() % 2;
        return rowMove, colMove;

    }

    private:
    string name;

};

//Board Class
class Board
{
    public:
    explicit Board(){
    this->state[3][3] = {
                        {'.', '.', '.'},
                        {'.', '.', '.'},
                        {'.', '.', '.'}}
    } // end board

    void printBoard(char state[3][3]){
        for (int i =0; i < 3; i ++){
            for (int j =0; j < 3; j++){
                cout << state[i][j] << " ";
            }
            cout << endl;
        }
    } //end printboard

    void printBoard(){
        for (int i =0; i < 3; i ++){
            for (int j =0; j < 3; j++){
                cout << this->state[i][j] << " ";
            } //end inner j for
            cout << endl;
        } // end outer i for        
    } //end printboard

    private:
    char state[3][3];

};

int main(){
    // Player Tony("Tony");
    // cout << Tony.getName();

    Player Tony("Tony");
    Board game();

    cout << Tony.getName() << endl;
    Tony.setName("Bob");
    cout << Tony.getName() << endl;
    int currRow, currCol;
    currRow = Tony.generateRowMovement();
    currCol = Tony.generateColMovement();
    cout << currRow << currCol << endl;



    return 0;

} //end main

If I add the following block to main (and adjust some other things):

char grid[3][3] = { {'.', '.', '.'},
                    {'.', '.', '.'},
                    {'.', '.', '.'}};

for (int i =0; i < 3; i ++){
    for (int j =0; j < 3; j++){
        cout << grid[i][j] << " ";
    } //end inner j for
    cout << endl;
} // end outer i for 

I get the expected result of:

. . .
. . .
. . .

Why can I not make the default construction of this object a [3][3] char array like above?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
artemis
  • 6,857
  • 11
  • 46
  • 99
  • `Your Board constructor needs to use loops to fill the state member`. Can you provide example? If you can't tell, I am pretty new to C++. I don't know how to do so. – artemis Sep 13 '19 at 03:36
  • Don't use `rand` in C++. It is officially known as a low quality RNG. Use `std::uniform_int_distribution` instead. Also, please try to avoid `using namespace std;` because it is considered bad practice and will cause serious problems. See [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/q/1452721) – L. F. Sep 13 '19 at 04:52
  • You have a second issue in your code: I don't think your `Player::placeMove` function does what you think it does. It looks like you want to return a `row, col` pair, but that is not what happens there. See here for more info on the comma operator: https://stackoverflow.com/questions/52550/what-does-the-comma-operator-do or https://en.cppreference.com/w/cpp/language/operator_other#Built-in_comma_operator (both say the same, just in different styles). – Frodyne Sep 13 '19 at 07:59
  • If you want to return a row,col pair, then change to function like this: `pair placeMove() { ... return make_pair(rowMove, colMove); }`, and then use it like so: `auto b = Tony.placeMove(); cout << b.first << ", " << b.second << endl;`. I think that will give you what you are after. – Frodyne Sep 13 '19 at 08:07
  • I was wondering that. How could I then use that pair to place a marker, say 'X', on the `char[3][3]` array? – artemis Sep 13 '19 at 14:30

3 Answers3

2

Array brace initialization works only when declaring an array.

If you are using C++1x try adding the initialization statement {...} to the member declaration:

private:
char state[3][3] = {...};

Alternatively you can fill the array using std::fill or std::fill_n:

std::fill  (&state[0][0], &state[3][3],                      '.');
std::fill_n(&state[0][0], sizeof(state)/sizeof(state[0][0]), '.');
Kostas
  • 4,061
  • 1
  • 14
  • 32
  • In this way, I could never edit the value though, right, since it is private? – artemis Sep 13 '19 at 03:38
  • @JerryM. It is already private in your code. Private means it cannot be accessed outside the class, but it **can** be accessed by class methods (as you're doing) – Kostas Sep 13 '19 at 03:40
1

this->state[3][3] = {...} is not a valid assignment. You can't assign arrays that way. And brace initialization only works in a declaration, not in an assignment. Your Board constructor needs to use loops to fill the state member:

explicit Board(){
    for (int i =0; i < 3; i ++){
        for (int j =0; j < 3; j++){
            state[i][j] = '.';
        }
    }
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

Why can I not make the default construction of this object a [3][3] char array like above?

Yes, you can.

explicit Board() : state({
                        {'.', '.', '.'},
                        {'.', '.', '.'},
                        {'.', '.', '.'}}) {
} // end board

this->state[3][3] = is variable assignment statement, you cannot use brace enclosed list. But you can use it in constructor.

binhgreat
  • 982
  • 8
  • 13