Я пытаюсь заполнить массив некоторыми выбранными символами из строки. 2 столбца должны оставаться пустыми, но у меня это работает так. Каждый символ должен быть равен количеству строк. Как игра с сортировкой мячей.. Небольшой совет? Спасибо.
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;
}
}
}
}
}
Вот как это должно выглядеть.
Чтобы исправить потенциальное Undefined Behavior в этой функции, когда rows не равно columns, индексы здесь
field[i][k] = store_symbol[random_index];
Нужно перевернуть
field[k][i] = store_symbol[random_index];
Следующее позволяет rows плюс один из каждого символа в массиве:
if (store_index[random_index] <= rows) {
Измените <= на <, чтобы ограничить количество каждого символа в массиве до максимума rows.
Следующий
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;
}
Вводит ошибку off-by-one. Если clear_column[0] равно columns, то очищается только последний столбец через clear_column[1] (clear_column[1] = clear_column[0] - 1;).
I никогда не достигнет columns в цикле.
Есть несколько решений для этого:
Убедитесь, что columns > 1 найдите первый столбец в допустимом диапазоне минус один и возьмите следующий столбец.
int clear_column[2] = { rand() % (columns - 1) };
clear_column[1] = clear_column[0] + 1;
Или найдите первый столбец для очистки в пределах допустимого диапазона и отрегулируйте второй в любом направлении:
int clear_column[2] = { rand() % columns };
clear_column[1] = clear_column[0] + (clear_column[0] == columns - 1 ? -1 : 1);
В стороне: это чаще распределяет пустые столбцы по двум последним столбцам (clear_column[0], будучи columns - 1 или columns - 2, приводит к тому же шаблону.
Или вы можете обернуть второй столбец, чтобы очистить его до начала массива:
clear_column[0] = rand() % columns;
clear_column[1] = (clear_column[0] + 1) % columns;
Или полностью рандомизируйте очищенные столбцы.
int clear_column[2] = { rand() % columns };
while ((clear_column[1] = rand() % columns) == clear_column[0]);
Однако эти последние два создают разные шаблоны.
Возникла проблема с требованием
Каждый символ должен быть равен количеству строк
Когда количество элементов за вычетом количества пробелов (строк, умноженных на два) не равно квадрату строк, поскольку вы допускаете rows разных символов до rows раз каждый.
Вместо этого вы должны разрешить columns - 2 разных символов до rows раз каждый (или наоборот).
Вот пример вышеупомянутых изменений, примененных к вашей функции:
#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');
}
}
В сторону: вызов srand внутри функции-генератора вызывает недоумение. Может быть безобидно, но проверьте srand() — зачем вызывать его только один раз?