When I started writing the answer, I noticed that the author's array “what I expect to receive” does not coincide with the picture. Specificity in this matter is not enough. Therefore, I will give two different versions of such fields.
1. General code
The code common to both versions:
#include <stdio.h> #include <math.h> #define MAP_WIDTH 30 #define MAP_HEIGHT 30 void print_map(int* map, int w, int h) { for (int y = 0; y < MAP_HEIGHT; ++y) { for (int x = 0; x < MAP_WIDTH; ++x) { // Вместо нулей печатаем пробелы, чтобы не сломать глаза :) (map[x + y*MAP_WIDTH] == 0) ? printf(" ") : printf("%2i ", map[x + y*MAP_WIDTH]); } putchar('\n'); } } <...> int main() { int map[MAP_HEIGHT][MAP_WIDTH] = {{0}};
2. Reducing the weight of the point depending on the distance to the center
The weight of each point should decrease with distance from the center. But how? To be honest, I still could not find the rule for the weights to decrease as in the picture. Therefore, I will provide the code for the linear reduction of the scales .
// map - матрица целых чисел, w, h -- его высота и ширина соответственно. // x и y -- координаты центра поля. // start_value -- очевидно, начальное значение. // attenuation_constant -- коэффициент затухания. void set_potential(int* map, int w, int h, int x, int y, int start_value, int attenuation_constant) { // Вычисляем максимальное удаление от центра по вертикали/горизонтали. int verical_and_horizontal_steps_nm = start_value / attenuation_constant; int box[2][2] = { {x - verical_and_horizontal_steps_nm + 2, y - verical_and_horizontal_steps_nm + 2}, {x + verical_and_horizontal_steps_nm - 1, y + verical_and_horizontal_steps_nm - 1} }; for (int dot_y = box[0][1]; dot_y < box[1][1]; ++dot_y) { for (int dot_x = box[0][0]; dot_x < box[1][0]; ++dot_x) { // Считаем расстояние до точки по формуле d = sqrt((x0-x1)^2 + (y0-y1)^2). int distance = sqrt((x-dot_x)*(x-dot_x) + (y-dot_y)*(y-dot_y)); // Значение текущей точки меняется линейно. int dot_value = start_value - distance * attenuation_constant; // Если точка не лежит на вертикали или горизонтали от центральной мы считаем // значение по-другому, т. к. диагональ квадрата всегда больше его стороны. // Т. к. длина стороны у нас -- 1, то длина диагонали будет sqrt(2). if (dot_y != y && dot_x != x) dot_value = start_value - round(sqrt(2) * distance * attenuation_constant); // Чтобы не было отрицательных коэффициентов по углам добавляем условие. map[dot_x + dot_y*MAP_WIDTH] = dot_value > 0 ? dot_value : 0; } } }
Here is the output for set_potential((int*)map, MAP_WIDTH, MAP_HEIGHT, 15, 15, 10, 2) :
2 2 4 2 2 2 4 4 6 4 4 2 2 4 7 8 7 4 2 4 6 8 10 8 6 4 2 4 7 8 7 4 2 2 4 4 6 4 4 2 2 2 4 2 2
Not very similar to the picture, but the weights depend directly on the distance to the center.
3. I do not even know what to call an option. See for yourself ...
If we take a better look at the lower left (and in general, any) quarter of the picture or the array of the “expectations” of the author, we note that
- All numbers on the same diagonal are equal;
- Each number on the next diagonal (with a divergence from the center) is exactly one step (I called it the attenuation coefficient ) more than any number on the previous diagonal;
- The length of each diagonal is greater than the previous one by one.
Difficult to explain in words, see for yourself (attenuation factor = 2):

1. 10 (- 2 = 8) 2. 8 8 (- 2 = 6) 3. 6 6 6 (- 2 = 4) 4. 4 4 4 4 (- 2 = 2) 5. 2 2 2 2 2
Four such quarters (correctly turned) will give the desired picture (which, by the way, is a diamond, which is what the author needs (see the comments to the question)).
The drawing algorithm is very simple, I think everything will be clear from the code:
void set_potential2(int* map, int w, int h, int x, int y, int start_value, int attenuation_constant) { // Заполняем центр. map[x + y*MAP_WIDTH] = start_value; // Вычисляем максимальное удаление от центра по вертикали/горизонтали. int verical_and_horizontal_steps_nm = start_value / attenuation_constant; // Здесь i -- расстояние от центра до текущей точки. for (int i = 1; i < verical_and_horizontal_steps_nm; ++i) { int dot_value = start_value - attenuation_constant * i; // Заполняем левый нижний угол: // // dot_y = y+i -- переходим в точку максимального отдаления по вертикали от центра. // dot_x = x -- координата x точки равна координате центра. // do_y >= y; --dot_y -- пока находимся выше центра, поднимаемся вверх. // --dot_x -- смещаемся влево. // // Т. е. мы как-бы по ступенькам поднимаемся вверх-влево, вверх-влево, вверх-влево... // Для остальных углов меняем только направления в заголовке цикла. for (int dot_y = y+i, dot_x = x; dot_y >= y; --dot_y, --dot_x) // Тоже самое, что map[dot_x][dot_y] map[dot_x + dot_y*MAP_WIDTH] = dot_value; // Правый нижний угол for (int dot_y = y+i, dot_x = x; dot_y >= y; --dot_y, ++dot_x) map[dot_x + dot_y*MAP_WIDTH] = dot_value; // Левый верхний угол for (int dot_y = yi, dot_x = x; dot_y <= y; ++dot_y, --dot_x) map[dot_x + dot_y*MAP_WIDTH] = dot_value; // Правый верхний угол for (int dot_y = yi, dot_x = x; dot_y <= y; ++dot_y, ++dot_x) map[dot_x + dot_y*MAP_WIDTH] = dot_value; } }
This is what the algorithm produces when set_potential2((int*)map, MAP_WIDTH, MAP_HEIGHT, 9, 9, 10, 2) :
2 2 4 2 2 4 6 4 2 2 4 6 8 6 4 2 2 4 6 8 10 8 6 4 2 2 4 6 8 6 4 2 2 4 6 4 2 2 4 2 2
The author led a cropped array:
{ 2, 4, 6, 4, 2, 4, 6, 8, 6, 4, 6, 8, 10, 8, 6, 4, 6, 8, 6, 4, 2, 4, 6, 4, 2 }
We cut our result:
2 4 6 4 2 4 6 8 6 4 6 8 10 8 6 4 6 8 6 4 2 4 6 4 2
The similarity is obvious. I think this is exactly what the author needed. In my opinion, beauty :)
PS The code is not very, of course, but it will go to illustrate the idea.
PSS To be honest, I don’t know how to correctly translate the “damping factor”: “attenuation constant” or “damping constant”. If anyone correct, will appreciate.