Вот и я перед новым годом (который, кстати, уже наступил - если что) придумал себе проблему, и упорно решал её на протяжении длительного времени.
С чего всё началось
А началось всё со следующей задачи.
По условию задачи пользователь вводит число строк, а программа должна нарисовать равнобедренный треугольник с помощью звёздочек - "*". Треугольник должен выглядеть так:
*
***
*****
Для примера, положим, что я ввёл высоту, равную 5 строкам.
_
| *
| ***
5 *****
| *******
|_ *********
|----9----|
Тогда, как видно на примере выше, ширина основания треугольника равна 9 звёздочкам. Если я возьму другую высоту - например, 10 строк - то получу треугольник шириной 19 звёздочек. Отсюда выводим формулу:
w = h / 2 - 1 (1)
где w - ширина, h - высота.
Рисую равнобедренный треугольник
Чтобы нарисовать ровный треугольник, мне нужно помещать определённое количество пробелов перед каждой строкой, в зависимости от номера строки.
-Что есть- -Что должно получиться-
1 * 1 *
2 *** 2 ***
3 ***** => 3 *****
4 ******* 4 *******
5 ********* 5 *********
\ /
номер строки
Чтобы это осуществить, надо знать номер центрального "столбца".
строки
1 *
2 ***
3 *****
4 *******
5 *********
123456789 <-- столбцы
^
центральный
столбец
Очевидно, в треугольнике высотой 5 строк, центральным будет 5-й столбец. И тут оказывается, что для нахождения центрального столбца нам нужно знать только высоту h треугольника, введённую пользователем - ведь, если верить формуле 1, то номер центрального столбца всегда будет совпадать с высотой. Это позволяет упростить программу.
Вот, кстати, код на Си:
#include <stdio.h>
int main() {
int height;
int i, j;
printf("Please enter height:\n> ");
scanf("%d", &height);
for(i = 1; i <= height; i++) {
for(j = 1; j <= (height + i); j++) {
if(j <= (height - i + 1))
putchar(' '); // Печатаем пробел
else
putchar('*'); // Печатаем звёздочку
}
putchar('\n'); // Переходим на новую строку
}
return 0;
}
Этот код, несмотря на его простоту, нуждается в дополнительных комментариях для понимания.
Первый цикл работает, пока i меньше или равно половины ширины треугольника. А поскольку, как уже было сказано выше, высота треугольника совпадает с номером центрального столбца, т.е. его центра - то я могу использовать значение введённой пользователем высоты height. Что я и делаю.
Второй цикл работает, пока j меньше или равно height плюс значение i (т.е. номер текущей строки).
Далее я проверяю, если j меньше или равно height минус i плюс 1. Единица здесь задаёт смещение всего треугольника от левой границы экрана. Если условие выполняется, то я печатаю пробел, иначе - звёздочку.
Эта программа решает поставленную задачу - рисует треугольник из звёздочек высотой N строк. Но...
Что не так с этим алгоритмом?..
То, что рисует эта программа, совсем не похоже на новогоднюю ёлку. А значит, эти красивые деревья будут продолжать вырубать для того, чтобы они простояли несколько дней в какой-нибудь городской квартире, пока не засохнут. Так скоро в лесу одни пеньки останутся. А пеньки, - как говорил известный персонаж известной повести, - они только для старушек хороши: на них сидеть можно.
Как бы нарисовать что-то, похожее на ёлку - да ещё так, чтобы эта ёлка высотой N, будучи вписанной в квадрат размером NxN, в основании была так же равной N?
Я подошёл к решению этой проблемы со всей серьёзностью, и нарисовал следующее:
fig. 1 отображает алгоритм отрисовки звёздочек, который я уже описывал выше. Получается равнобедренный треугольник.
Алгоритм отрисовки треугольника я не случайно назвал "алгоритмом номер 0" - следующие два алгоритма отрисовки ёлки реализуются на основе идей, реализованных в программе, решающей задачу с треугольником.
fig. 2 показывает, как можно нарисовать нечто похожее на ёлку - путём удвоения каждой строки. Но ширина основания по-прежнему меньше высоты.
fig. 3 показывает алгоритм отрисовки ёлки. Это как раз то, что нужно. Как видно из рисунка, ширина ёлки при таком способе заполнения строк равна высоте. Причём, здесь можно заметить интересную особенность данного алгоритма - она показана на рисунке справа от fig. 3.
Пока это всё. Предлагаю читателям подумать над реализацией второго и третьего алгоритма отрисовки ёлки.
Реализацию второго алгоритма я рассмотрю в следующем посте.