Теперь пришло время нарисовать первое подобие ёлки.
Постановка задачи
Должно получиться следующее:
_
| X <-------- звезда
| *
| ***
| ***
10 *****
| ***** <------ ёлка
| *******
| *******
| *********
|_ *********
|----9----|
рис.1
Всё очень просто: нужно взять за основу алгоритм отрисовки треугольника и удвоить каждую строку: 1, 1, 3, 3, 5, 5...
Высота дерева задаётся пользователем.
Дабы повысить соответствие оригиналу, я хочу поместить на верхушку ёлки "звезду". Ну, вроде тех массивных стеклянных/пластмассовых штуковин, которые часто надевают на верхушку ёлки для усиления праздничного эффекта. За звезду сойдёт английская буква "X" (см. рис.1)
Реализация
Как и в задаче отрисовки треугольника, мне потребуются два цикла - один для перехода на новую строку, другой - для отрисовки каждого ряда звёздочек. Вот первый цикл:
for(i = 0; i < height; i++) {
// ...
}
С ним не будет особых проблем. А вот над вложенным циклом нужно подумать. Каким образом реализовать удвоение каждой строки? Посмотрим, как будет расти количество звёздочек в строке, в зависимости от номера строки. Как видно из куска кода выше, переменная i изменяется в цикле от 0 до height - 1 (о чём говорит знак "меньше").
i | кол. звёздочек в строке
--|------------------------
0 | 1 X
1 | 1 *
2 | 3 ***
3 | 3 ***
4 | 5 *****
5 | 5 *****
6 | 7 *******
7 | 7 *******
8 | 9 *********
9 | 9 *********
...
рис.2
Из рисунка выше видно, что количество звёздочек увеличивается на 2 на каждой чётной строке. Это даёт подсказку, как можно реализовать алгоритм.
Здесь я хочу сделать небольшое отступление, и посмотреть внимательно на работу алгоритма отрисовки треугольника. Всё, что мне нужно - это знать половину ширины треугольника, а она равна высоте.
for(i = 1; i <= h; i++)
for(j = 1; j <= (h + i); j++) {
if(j <= (h - i + 1))
putchar(' ');
else
putchar('*');
putchar('\n');
}
Начальное значение счётчиков i, j равно 1, чтобы обеспечить отступ в один дополнительный символ перед каждой строкой.
Нарисуем 3 строку треугольника (i = 3). Пусть высота h равна 5.
h + i = 8;
h - i + 1 = 3;
|<------------- 8 ------------->|
_______________________________
| | | | * | * | * | * | * |
-------------------------------
|<----- j > 3 ----->|
рис.3
Я думаю, из рисунка 3 можно понять работу этого алгоритма.
В алгоритме отрисовки ёлки половину её ширины нужно вычислять отдельно - ведь теперь эта величина не равна высоте, как в случае с отрисовкой треугольника. Однако, не всё так уж и плохо - есть простая формула, о которой я уже говорил в предыдущем посте.
hw = h / 2 - 1 (1)
Создам новую переменную, и присвою ей результат вычисления половины ширины елки, согласно формуле 1.
Теперь вернёмся к проблеме удвоения каждой строки. Поскольку, как уже было сказано выше, количество звёздочек увеличивается на 2 на чётной строке, попробуем сделать вот что.
Я просто разделю i на 2 во всех проверках условий во вложенном цикле. Вот так:
// ...
int hw;
// ...
hw = height / 2 - 1;
for(i = 0; i < height; i++)
/* Печатаю номер строки в обратном порядке (снизу вверх) */
printf("%02d\t", height-i);
for(j = 0; j <= (hw + i / 2); j++) { // <-- здесь
if(j < (hw - i / 2)) // <-- и здесь
putchar(' ');
else
if(i == 0) // или можно написать: if(!i)
/* Рисую большую звезду на верхушке ёлки */
putchar('X');
else
putchar('*');
putchar('\n');
}
// ...
Если строка нечётная, то hw будет увеличиваться в проверке условия завершения цикла for() и уменьшаться в условии if() - на остаток от деления, т.е. на 1. В результате, количество звёздочек в нечётной строке увеличиться на 2. Если же номер строки - чётный, то никаких изменений не происходит, просто копируется предыдущая строка.
Мне кажется, это потрясающе просто и понятно.
Your blog is wonderful. Thank you very much for sharing such a blog with us.
ОтветитьУдалитьAlso, visit to know more about the swimming poos and fountains
Swimming Pool Builders
Swimming Pool Manufacturers
Swimming Pool Designer in Delhi
Floating fountain Manufacturer in Delhi
Programmable Fountain manufacturer
Musical Fountain Manufacturer in Delhi