0

I've initialised the following array to store moves in a tic-tac-toe game (there can be up to 100 moves (10x10 grid). Each subarray needs to store the row and column of the move, as well as the symbol being placed there.

char moves[100][3];

I then want to insert the three values into each subarray. I use the variable moveCount for the index into which i want to store the subarray of move data.

moves[moveCount] = {row, col, symbol};

however this is throwing the error "expression must be a modifiable lvalue". How do i go about inserting the subarray of move data into the overall array?

1

4 Answers 4

4

There are two errors in this statement

moves[moveCount] = {row, col, symbol};

The first one is that the expression moves[moveCount] is an array and arrays do not have the assignment operator.

The second one is the list in braces is not an expression.

You need to write

moves[moveCount][0] = row; 
moves[moveCount][1] = col;
moves[moveCount][2] = symbol;

Instead of defining the two dimensional array consider a definition of a one-dimensioanl array of objects of a structure type that will contain three data members row, col and symbol.

Sign up to request clarification or add additional context in comments.

Comments

2

In C you cannot assign values to an array but only to separate array members.

But I doubt that an array is the proper data type for you. You want to store 3 values with different meaning. That would call for a struct instead of an array:

typedef struct {
char row;
char col;
char symbol;
} move_t;

move_t moves[100];

Then you can use a compound literal to assign new values to each element:

moves[movecount]=(move_t){row, col, symbol};

Comments

0

I'm not sure how to do that on one line but this worked for me:

    char moves[10][3];

    moves[0][0] = 'a';
    moves[0][1] = 'b'; 
    moves[0][2] = 'c';

So if is it acceptable for you to assign the values one by one, that would be an option.

What I also found here is that you can create an additional array and initialise it with your values, then copy it to there you need it.

char moves[10][3];
char values[3] = {'1', '2', '3'};
memcpy(moves[0], values, sizeof(values));

Comments

0

Vlad from Moscow is right, you cannot assign an array that way. Its solution is the right way to proceed, but you may consider a more compact way to represent your grid.

You need only 1 bit to represent one of the 2 states 'O' or 'X' of the game and 4 bits to represent the value for row or column. Thus, 4 + 4 + 1 = 9 bits should be enough and you can store them together within a 16-bit variable (uint16_t).

Consider a special case when the value is 0, then no move happened on that position.

Use macros to get and set the right values:

#define FIELD_SIZE ((1 << 4) - 1)
#define GET_ROW(x) (x & FIELD_SIZE)
#define GET_COL(x) ((x >> 4) & FIELD_SIZE)
#define IS_EMPTY(x) (x == 0)
#define GET_SYMBOL(x) (!(x >> 8))

Bits schema:

+---UNUSED---+-SYMBOL-+--COL--+--ROW--+
    16-9         8       7-4     3-0

GET_SYMBOL return 1 or 0.

However, I prefer Gerhardh's solution. It's clear and easier to manage. You may still save some bits:

typedef struct {
    char row:4;
    char col:4;
    char symbol;
} move_t;

2 Comments

You should not use plain char for type in struct bitfields. If compiler uses signed chars and signed bitfield ranges, the range won't be enough for 10 rows or columns. In general, I don't think struct bitfields are worth the trouble to save few bytes here.
You're right, you can replace char with uint8_t. Usefulness of savings bytes may depend on the context.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.