I'm trying to fill an array with some selected characters from string. 2 columns have to stay empty, but this is how it's working for me. Every symbol should be equal to number of rows. Like ball sort game.. Some advice? Thanks.
void generator(const int rows, const int columns, char field[rows][columns]){
// seed
srand(time(NULL));
int random_index;
// choosing empty columns (they'll be by side)
int clear_column[2];
// choosing random number in range of columns
clear_column[0] = rand() % (columns 1);
// adding 1 index to already choosen number
clear_column[1] = clear_column[0] 1;
// if choosen number is equal to number of columns => second empty column will be on the left side
if ( clear_column[0] == columns)
{
clear_column[1] = clear_column[0]-1;
}
// variable to store all symbols
char store_symbol[10] = "^@#&* -/$";
// variable to store used symbols
int store_index[10] = {0,0,0,0,0,0,0,0,0};
// ** i = columns; k = rows
// loops all columns
for (int i = 0; i < columns; i )
{
// loops all rows
for (int k = 0; k < rows; k )
{
// adding empty columns
if ( i == clear_column[0] || i == clear_column[1])
{
field[k][i] = ' ';
}
else{
int got_symbol = 0;
while (got_symbol == 0)
{
random_index = rand() % rows;
if ( store_index[random_index] <= rows)
{
field[i][k] = store_symbol[random_index];
store_index[random_index] = 1;
got_symbol = 1;
break;
}
}
}
}
}
This is how it should look.
CodePudding user response:
To fix the potential Undefined Behaviour in this function, when rows
does not equal columns
, the indices here
field[i][k] = store_symbol[random_index];
need to be flipped
field[k][i] = store_symbol[random_index];
The following allows rows
plus one of each character in the array:
if (store_index[random_index] <= rows) {
Change <=
to <
to limit the number of each character in the array to a maximum of rows
.
The following
int clear_column[2];
clear_column[0] = rand() % (columns 1);
clear_column[1] = clear_column[0] 1;
if (clear_column[0] == columns) {
clear_column[1] = clear_column[0]-1;
}
introduces an off-by-one error. If clear_column[0]
is equal to columns
, then the only column to be cleared will be the last one, via clear_column[1]
(clear_column[1] = clear_column[0] - 1;
).
i
will never reach columns
in the loop.
There are a few solutions to this:
Ensure columns > 1
, find the first column within the valid range minus, and take the next column over.
int clear_column[2] = { rand() % (columns - 1) };
clear_column[1] = clear_column[0] 1;
Or, find the first column to clear within the valid range, and adjust the second in either direction:
int clear_column[2] = { rand() % columns };
clear_column[1] = clear_column[0] (clear_column[0] == columns - 1 ? -1 : 1);
Aside: This distributes empty columns more frequently to the last two columns (clear_column[0]
being columns - 1
or columns - 2
results in the same pattern.
Or, you could wrap the second column to clear around to the start of the array:
clear_column[0] = rand() % columns;
clear_column[1] = (clear_column[0] 1) % columns;
Or, completely randomize your cleared columns.
int clear_column[2] = { rand() % columns };
while ((clear_column[1] = rand() % columns) == clear_column[0]);
These last two do produce different patterns, though.
There is a problem with the requirement
Every symbol should be equal to number of rows
when the number of elements minus the number of blank spaces (rows times two) is not equal to the square of rows, since you allow rows
different characters up to rows
times each.
Instead you should allow columns - 2
different characters up to rows
times each.
Here is an example of the aforementioned changes applied to your function:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SYM "^@#&* -/$?"
#define MAX_SYM 10
#define def(c, a, i, d) (c > i ? atoi(a[i]) : d)
void generator(const int rows, const int columns, char field[rows][columns])
{
int clear_column[2] = { rand() % columns };
clear_column[1] = (clear_column[0] 1) % columns;
char store_symbol[MAX_SYM] = SYM;
int store_index[MAX_SYM] = { 0 };
for (int i = 0; i < columns; i ) {
for (int k = 0; k < rows; k ) {
if (i == clear_column[0] || i == clear_column[1]) {
field[k][i] = ' ';
continue;
}
while (1) {
int random_index = rand() % (columns - 2);
if (store_index[random_index] < rows) {
field[k][i] = store_symbol[random_index];
store_index[random_index] = 1;
break;
}
}
}
}
}
int main(int argc, char **argv)
{
int r = def(argc, argv, 1, 4);
int c = def(argc, argv, 2, 6);
if (r < 1 || c < 1 || r > MAX_SYM || c > MAX_SYM) {
fprintf(stderr, "Invalid dimensions %dx%d\n", r, c);
return EXIT_FAILURE;
}
char map[r][c];
srand((unsigned) time(NULL));
generator(r, c, map);
for (int i = 0; i < r; i ) {
printf("|");
for (int j = 0; j < c; j ) {
printf(" %c |", map[i][j]);
}
putchar('\n');
}
}