Devcpp 1
Devcpp 1
Devcpp 1
Глава I.
Введение в программирование
1. Простейшие программы......................................................................................... 3
Зачем нужно программирование? ........................................................................... 3
Два этапа создания программ................................................................................... 3
Простейшая программа на Си ................................................................................. 4
Вывод текста на экран ............................................................................................... 4
Как запустить программу? ....................................................................................... 5
Остановим мгновение ................................................................................................ 5
2. Переменные ............................................................................................................... 7
Типы данных и переменные ..................................................................................... 7
Вычисление суммы двух чисел (ввод и вывод)..................................................... 7
Арифметические выражения .................................................................................... 9
Форматы для вывода данных ................................................................................ 11
3. Выбор вариантов ................................................................................................... 14
Зачем нужны ветвления? ........................................................................................ 14
Условный оператор if — else............................................................................... 14
Сложные условия ...................................................................................................... 16
Переключатель switch (множественный выбор) ............................................. 17
4. Циклы ....................................................................................................................... 19
Зачем нужны циклы? ............................................................................................... 19
Цикл с известным числом шагов (for) ................................................................ 19
Цикл с условием (while) ........................................................................................ 20
Цикл с постусловием (do — while) .................................................................... 22
Досрочный выход из цикла..................................................................................... 23
Вычисление сумм последовательностей............................................................... 24
5. Методы отладки программ ................................................................................. 27
Отладочные средства Dev-C++ ............................................................................... 27
6. Работа в графическом режиме ........................................................................... 31
Простейшая графическая программа ................................................................... 31
Как начать рисовать? .............................................................................................. 31
Пример программы .................................................................................................. 34
7. Процедуры ............................................................................................................... 35
Пример задачи с процедурой .................................................................................. 35
8. Функции ................................................................................................................... 38
Отличие функций от процедур ............................................................................... 38
Логические функции ................................................................................................ 39
Функции, возвращающие два значения ............................................................... 40
9. Структура программ ............................................................................................ 42
Составные части программы ................................................................................. 42
Глобальные и локальные переменные ................................................................. 42
Оформление текста программы............................................................................. 43
10. Анимация............................................................................................................. 46
Что такое анимация?................................................................................................ 46
Движение объекта ..................................................................................................... 46
http://kpolyakov.spb.ru
2
I. Введение в программирование © К. Поляков, 1995-2009
Управление клавишами-стрелками ..................................................................... 48
11. Случайные и псевдослучайные числа .............................................................. 51
Что такое случайные числа? .................................................................................. 51
Распределение случайных чисел ........................................................................... 51
Функции для работы со случайными числами .................................................. 52
Случайные числа в заданном интервале ............................................................. 52
Снег на экране........................................................................................................... 53
http://kpolyakov.narod.ru
3
Программирование на языке Си. © К. Поляков, 1995-2012
1. Простейшие программы
Исходный файл:
first.cpp
транслятор
компоновщик
Исполняемый файл:
first.exe
Почему же не сделать все за один шаг? Для простейших программ это действительно было бы
проще, но для сложных проектов двухступенчатый процесс имеет явные преимущества:
http://kpolyakov.spb.ru
4
I. Введение в программирование © К. Поляков, 1995-2009
Исходный файл программы на языке Си имеет расширение *.с или *.cpp (расширение
*.cpp говорит о том, что в программе могут быть использованы возможности языка Си++).
Это обычный текстовый файл, в который записывают текст программы в любом текстовом ре-
дакторе, например, в Блокноте.
Транслятор переводит исходный файл (вернее, записанную в нём программу) в машин-
ные коды и строит так называемый объектный файл с тем же именем и расширением *.o. Хо-
тя в нем уже записан машинный код, объектный файл еще нельзя запускать на компьютере,
потому что в нем не хватает стандартных функций (например, для ввода и вывода данных).
Компоновщик подключает стандартные функции, хранящиеся в библиотеках (они имеют
расширение *.a). В результате получается один файл с расширением *.exe, который и пред-
ставляет собой готовую программу.
Простейшая программа на Си
Такая программа состоит всего из 8 символов. Вот она:
main()
{
}
Основная программа всегда называется именем main (будьте внимательны – Си различает
большие и маленькие буквы, а все стандартные операторы Си записываются маленькими бук-
вами). Пустые скобки означают, что main не имеет аргументов. Фигурные скобки обозначают
начало и конец основной программы – поскольку внутри них ничего нет, наша программа ни-
чего не делает, она просто соответствует правилам языка Си, ее можно скомпилировать и полу-
чить exe-файл.
Что новенького?
• Чтобы использовать стандартные функции, необходимо сказать транслятору, что есть
функция с таким именем и перечислить тип ее аргументов – тогда он сможет определить,
верно ли мы ее используем. Это значит, что надо включить в программу описание этой
функции. Описания стандартных функций Си находятся в так называемых заголовочных
файлах с расширением *.h (в каталоге C:\Dev-Cpp\include).
1
Препроцессор – это специальная программа, которая обрабатывает текст вашей программы раньше транслятора.
Все команды препроцессора начиняются знаком #.
http://kpolyakov.narod.ru
5
Программирование на языке Си. © К. Поляков, 1995-2012
скобок не должно быть пробелов. Для подключения еще каждого нового заголовочного
файла надо использовать новую команду #include.
Остановим мгновение
Если запускать рассмотренную выше программу, то обнаружится, что программа сразу
заканчивает работу и возвращается обратно в оболочку, не дав нам посмотреть результат ее
работы на экране. Бороться с этим можно так – давайте скажем компьютеру, что в конце рабо-
ты надо дождаться нажатия любой клавиши.
#include <stdio.h> подключение заголовочного
#include <conio.h> файла conio.h
main()
{
printf("Привет"); // вывод на экран
getch(); /*ждать нажатия клавиши*/
}
Что новенького?
• Задержка до нажатия любой клавиши выполняется функцией getch().
• Описание этой функции находится в заголовочном файле conio.h.
http://kpolyakov.spb.ru
6
I. Введение в программирование © К. Поляков, 1995-2009
• Знаки // обозначают начало комментария — все правее них до конца строки не обраба-
тывается транслятором и служит нам для пояснения программы.
• Комментарий также можно ограничивать парами символов /* (начало комментария) и */
(конец комментария). В этом случае комментарий может быть многострочный, то есть со-
стоять из нескольких строк.
http://kpolyakov.narod.ru
7
Программирование на языке Си. © К. Поляков, 1995-2012
2. Переменные
http://kpolyakov.spb.ru
8
I. Введение в программирование © К. Поляков, 1995-2009
#include <stdio.h>
#include <conio.h>
main()
{
int a, b, c; // объявление переменных
printf ( "Введите два целых числа \n" ); // подсказка для ввода
scanf ( "%d%d", &a, &b ); // ввод данных
c = a + b; // вычисления (оператор присваивания)
printf ( "Результат: %d + %d = %d \n",
a, b, c ); // вывод результата
getch();
}
Что новенького?
• Программа чаще всего содержит 4 части:
o объявление переменных;
o ввод исходных данных;
o обработка данных (вычисления);
o вывод результата.
• Перед вводом данных необходимо вывести на экран подсказку (иначе компьютер будет
ждать ввода данных, а пользователь не будет знать, что от него хочет машина).
• Символы \n в функции printf обозначают переход в начало новой строки.
• Для ввода данных используют функцию scanf.
формат ввода адреса переменных
http://kpolyakov.narod.ru
9
Программирование на языке Си. © К. Поляков, 1995-2012
o слева от знака равенства ставится имя переменной, в которую надо записать результат
c = a + b; // сумму a и b записать в c
• Для вывода чисел и значений переменных на экран используют функцию printf
эти символы вывести здесь вывести целые
без изменений числа данные для вывода
Арифметические выражения
Из чего состоят арифметические выражения?
Арифметические выражения, стоящие в правой части оператора присваивания, могут содер-
жать
• целые и вещественные числа (в вещественных числах целая и дробная часть разделяются
точкой, а не запятой, как это принято в математике)
• знаки арифметических действий
+ — сложение, вычитание
* / умножение, деление
% остаток от деления
• вызовы стандартных функций
abs(i) модуль целого числа i
fabs(x) модуль вещественного числа x
sqrt(x) квадратный корень из вещественного числа x
pow(x,y) вычисляет x в степени y
• круглые скобки для изменения порядка действий
http://kpolyakov.spb.ru
10
I. Введение в программирование © К. Поляков, 1995-2009
Особенности арифметических операций
При использовании деления надо помнить, что
int i, n;
float x;
i = 7;
x = i / 4; // x=1, делится целое на целое
x = i / 4.; // x=1.75, делится целое на дробное
x =(float) i / 4; // x=1.75, делится дробное на целое
n = 7. / 4.; // n=1, результат записывается в
// целую переменную
Наибольшие сложности из всех действий вызывает взятие остатка. Если надо вычислить оста-
ток от деления переменной a на переменную b и результат записать в переменную ostatok,
то оператор присваивания выглядит так:
ostatok = a % b;
Если считать это уравнением, то оно бессмысленно с точки зрения математики. Однако с точки
зрения информатики этот оператор служит для увеличения значения переменной i на единицу.
http://kpolyakov.narod.ru
11
Программирование на языке Си. © К. Поляков, 1995-2012
Буквально это означает: взять старое значение переменной i, прибавить к нему единицу и за-
писать результат в ту же переменную i.
Инкремент и декремент
В языке Си определены специальные операторы быстрого увеличения на единицу (ин-
кремента)
i ++; // или...
++ i;
что равносильно оператору присваивания
i = i + 1;
и быстрого уменьшения на единицу (декремента)
i— —; // или...
— — i;
что равносильно оператору присваивания
i = i — 1;
Между первой и второй формами этих операторов есть некоторая разница, но только тогда, ко-
гда они входят в состав более сложных операторов или условий.
http://kpolyakov.spb.ru
12
I. Введение в программирование © К. Поляков, 1995-2009
printf("[%6d]", 1234); [ 1234] 6 позиций, выравнивание вправо.
printf("[%-6d]", 1234); [1234 ] 6 позиций, выравнивание влево.
Число не помещается в заданные 2
printf("[%2d]", 1234); [1234] позиции, поэтому область вывода
расширяется.
Для вывода символов используются такие же приемы форматирования, но формат %d заменяет-
ся на %c.
Вещественные числа
Для вывода (и для ввода) вещественных чисел могут использоваться три формата: %f,
%e и %g. В таблице показаны примеры использования формата %f.
http://kpolyakov.narod.ru
13
Программирование на языке Си. © К. Поляков, 1995-2012
Число не помещается в за-
данные 6 позиций (2 цифры
printf("[%6.2e]", 123.45); [1.23e+02] в дробной части мантиссы),
поэтому область вывода
расширяется.
Формат %g применяется для того, чтобы удалить лишние нули в конце дробной части
числа и автоматически выбрать формат (в стандартном виде или с фиксированной точкой). Для
очень больших или очень маленьких чисел выбирается формат с плавающей точкой (в стан-
дартном виде). В этом формате можно задать общее число позиций на число и количество зна-
чащих цифр.
Пример вывода Результат Комментарий
printf("[%g]", 12345); [12345]
Минимально возможное
printf("[%g]", 123.45); [123.45] поле, не более 6 значащих
printf("[%g]", 0.000012345); [1.2345e-05] цифр.
http://kpolyakov.spb.ru
14
I. Введение в программирование © К. Поляков, 1995-2009
3. Выбор вариантов
Зачем нужны ветвления?
В простейших программах все команды выполняются одна за другой последовательно.
Так реализуются линейные алгоритмы. Однако часто надо выбрать тот или иной вариант дейст-
вий в зависимости от некоторых условий: если условие верно, поступать одним способом, а
если неверно — другим. Для этого используют разветвляющиеся алгоритмы, которые в язы-
ках программирования представлены в виде условных операторов. В языке Си существует два
вида условных операторов:
• оператор if — else для выбора из двух вариантов
• оператор множественного выбора switch для выбора из нескольких вариантов
http://kpolyakov.narod.ru
15
Программирование на языке Си. © К. Поляков, 1995-2012
Что новенького?
• Условный оператор имеет следующий вид:
if ( условие ) // заголовок с условием
{
... // блок «если» — операторы, которые выполняются,
// если условие в заголовке истинно
}
else
{
... // блок «иначе» — операторы, которые выполняются,
// если условие в скобках ложно
}
• Эта запись представляет собой единый оператор, поэтому между скобкой, завершающей
блок «если» и словом else не могут находиться никакие операторы.
• После слова else никогда НЕ ставится условие — блок «иначе» выполняется тогда, ко-
гда основное условие, указанное в скобках после if, ложно.
• Если в блоке «если» или в блоке «иначе» только один оператор, то фигурные скобки мож-
но не ставить.
• В условии можно использовать знаки логических отношений
> < больше, меньше
>= <= больше или равно, меньше или равно
== равно
!= не равно
• В языке Си любое число, не равное нулю, обозначает истинное условие, а ноль — ложное
условие.
• Если в блоке «иначе» не надо ничего делать (например: «если в продаже есть мороженое,
купи мороженое», а если нет ...), то весь блок «иначе» можно опустить и использовать со-
кращенную форму условного оператора:
if ( условие )
{
... // что делать, если условие истинно
}
Например, решение предыдущей задачи могло бы выглядеть так:
#include <stdio.h>
#include <conio.h>
main()
{
float A, B, Max;
printf("Введите A и B : ");
scanf ( "%f%f", &A, &B );
Max = A;
if ( B > A )
Max = B;
printf ( "Наибольшее %f", Max );
getch();
}
http://kpolyakov.spb.ru
16
I. Введение в программирование © К. Поляков, 1995-2009
• В блоки «если» и «иначе» могут входить любые другие операторы, в том числе и другие
вложенные условные операторы; при этом оператор else относится к ближайшему пре-
дыдущему if:
if ( A > 10 )
if ( A > 100 )
printf ( "У вас очень много денег." );
else
printf ( "У вас достаточно денег." );
else
printf ( "У вас маловато денег." );
• Чтобы легче разобраться в программе, все блоки «если» и «иначе» (вместе с ограничи-
вающими их скобками) сдвигаются вправо на 2-3 символа (запись «лесенкой»).
Сложные условия
Простейшие условия состоят из одного отношения (больше, меньше и т.д.). Иногда надо
написать условие, в котором объединяются два или более простейших отношений. Например,
фирма отбирает сотрудников в возрасте от 25 до 40 лет (вклчительно). Тогда простейшая про-
грамма могла бы выглядеть так:
#include <stdio.h>
#include <conio.h>
main()
{
int age;
printf ( "\nВведите ваш возраст: " );
scanf ( "%d", &age );
if ( 25 <= age && age <= 40 ) // сложное условие
printf ( "Вы нам подходите." );
else
printf ( "Извините, Вы нам не подходите." );
getch();
}
Что новенького?
• Сложное условие состоит из двух или нескольких простых отношений, которые объеди-
няются с помощью знаков логических операций:
o операция И — требуется одновременное выполнение двух условий
условие_1 && условие_2
Эту операцию можно описать следующей таблицей (она называется таблицей истин-
ности)
условие_1 условие_2 условие_1 && условие_2
ложно (0) ложно (0) ложно(0)
ложно (0) истинно (1) ложно(0)
истинно (1) ложно (0) ложно(0)
истинно (1) истинно (1) истинно (1)
http://kpolyakov.narod.ru
17
Программирование на языке Си. © К. Поляков, 1995-2012
o операция ИЛИ — требуется выполнение хотя бы одного из двух условий (или обоих
сразу)
условие_1 || условие_2
http://kpolyakov.narod.ru
19
Программирование на языке Си. © К. Поляков, 1995-2012
4. Циклы
Что новенького?
• Цикл for используется тогда, когда количество повторений цикла заранее известно или
может быть вычислено.
• Цикл for состоит из заголовка и тела цикла.
• В заголовке после слова for в круглых скобках записываются через точку с запятой три
выражения:
o начальные значения: операторы присваивания, которые выполняются один раз перед
выполнением цикла;
o условие, при котором выполняется следующий шаг цикла; если условие неверно,
работа цикла заканчивается; если оно неверно в самом начале, цикл не выполняется ни
одного раза (говорят, что это цикл с предусловием, то есть условие проверяется перед
выполнением цикла);
http://kpolyakov.spb.ru
20
I. Введение в программирование © К. Поляков, 1995-2009
o действия в конце каждого шага цикла (в большинстве случаев это операторы при-
сваивания).
• В каждой части заголовка может быть несколько операторов, разделенных запятыми.
Примеры заголовков:
for ( i = 0; i < 10; i ++ ) { ... }
for ( i = 0, x = 1.; i < 10; i += 2, x *= 0.1 ){ ... }
• Тело цикла заключается в фигурные скобки; если в теле цикла стоит всего один оператор,
скобки можно не ставить.
• В тело цикла могут входить любые другие операторы, в том числе и другие циклы (такой
прием называется «вложенные циклы»).
• Для того, чтобы легче разобраться в программе, все тело цикла и ограничивающие его
скобки сдвигаются вправо на 2-3 символа (запись «лесенкой»).
http://kpolyakov.narod.ru
21
Программирование на языке Си. © К. Поляков, 1995-2012
(пили бревно, пока оно не будет распилено; иди вперед, пока не дойдешь до двери). Слово «по-
ка» на английском языке записывается как while, и так же называется еще один вид цикла.
Задача. Ввести целое число и определить, сколько в нем цифр.
Для решения этой задачи обычно применяется такой алгоритм. Число делится на 10 и от-
брасывается остаток, и так до тех пор, пока результат деления не равен нулю. С помощью спе-
циальной переменной (она называется счетчиком) считаем, сколько раз выполнялось деление –
столько цифр и было в числе. Понятно, что нельзя заранее определить, сколько раз надо разде-
лить число, поэтому надо использовать цикл с условием.
#include <stdio.h>
#include <conio.h>
main()
{
int N; // число, с которым работаем
int count=0; // переменная-счетчик
printf ( "\nВведите число N: " ); // подсказка
scanf ( "%d", &N ); // ввод N с клавиатуры
while ( N > 0 ) // заголовок цикла «пока N > 0»
{ // начало цикла (открывающая скобка)
N /= 10; // отсекаем последнюю цифру
тело цикла
count ++; // увеличиваем счетчик цифр
} // конец цикла (закрывающая скобка)
printf ( "В этом числе %d цифр\n", count );
getch();
}
Что новенького?
• Цикл while используется тогда, когда количество повторений цикла заранее неизвестно
и не может быть вычислено.
• Цикл while состоит из заголовка и тела цикла.
• В заголовке после слова while в круглых скобках записывается условие, при котором
цикл продолжает выполняться. Когда это условие нарушается (становится ложно), цикл
заканчивается.
• В условии можно использовать знаки логических отношений и операций
> < больше, меньше
>= <= больше или равно, меньше или равно
== равно
!= не равно
• Если условие неверно в самом начале, то цикл не выполняется ни разу (это цикл с преду-
словием).
• Если условие никогда не становится ложным (неверным), то цикл никогда не заканчива-
ется; в таком случае говорят, что программа «зациклилась» — это серьезная логическая
ошибка.
• В языке Си любое число, не равное нулю, обозначает истинное условие, а ноль — ложное
условие:
Что новенького?
• Цикл do—while используется тогда, когда количество повторений цикла заранее неиз-
вестно и не может быть вычислено.
http://kpolyakov.narod.ru
23
Программирование на языке Си. © К. Поляков, 1995-2012
• Цикл состоит из заголовка do, тела цикла и завершающего условия.
• Условие записывается в круглых скобках после слова while, цикл продолжает выпол-
няться, пока условие верно; когда условие становится неверно, цикл заканчивается.
• Условие проверяется только в конце очередного шага цикла (это цикл с постусловием),
таким образом, цикл всегда выполняется хотя бы один раз.
• Если условие никогда не становится ложным (неверным), то цикл никогда не заканчива-
ется; в таком случае говорят, что программа «зациклилась» — это серьезная логическая
ошибка.
• Тело цикла заключается в фигурные скобки; если в теле цикла стоит всего один оператор,
скобки можно не ставить.
• В тело цикла могут входить любые другие операторы, в том числе и другие циклы (такой
прием называется «вложенные циклы»).
• Для того, чтобы легче разобраться в программе, все тело цикла и ограничивающие его
скобки сдвигаются вправо на 2-3 символа (запись «лесенкой»).
Что новенького?
• Если только внутри цикла можно определить, надо ли делать вычисления в теле цикла и надо
ли продолжать цикл (например, при вводе исходных данных), часто используют бесконеч-
ный цикл, внутри которого стоит оператор выхода break:
while ( 1 ) {
...
if ( надо выйти ) break;
...
}
• С помощью оператора break можно досрочно выходить из любых циклов: for, while,
do—while.
• Чтобы досрочно завершить текущий шаг цикла и сразу перейти к следующему шагу, исполь-
зуют оператор continue.
http://kpolyakov.spb.ru
26
I. Введение в программирование © К. Поляков, 1995-2009
Цикл закончится тогда, когда переменная a (она обозначает модуль очередного элемента по-
следовательности) станет меньше 0,001. Чтобы программа вошла в цикл на первом шаге, в эту
переменную надо записать любое значение, большее, чем 0,001.
Очевидно, что если переменная a не будет уменьшаться, то условие в заголовке цикла
всегда будет истинно и программа «зациклится».
http://kpolyakov.narod.ru
27
Программирование на языке Си. © К. Поляков, 1995-2012
Трассировка
Трассировка – это вывод сигнальных сообщений в определенных точках программы во
время ее работы. Что же это дает?
Во-первых, получив такое сообщение на экран, мы знаем, что программа вышла в эту точ-
ку (не завершила работу аварийно раньше и не зациклилась). Во-вторых, в этих сообщениях
можно выводить не только текст, но и значения переменных – это позволяет проверять, пра-
вильно ли считает программа. Если, например, во 2-ой контрольной точке все значения пере-
менных были верные, а в 3-ой уже нет, то ошибку нужно искать между этими точками.
В этой программе в трех точках (1, 2 и 3) стоят операторы трассировки:
main()
{
int i, X;
printf("Введите целое число:\n");
scanf("%d", &X);
printf("Введено X=%d\n", X); // точка 1
for(i=1; i<10; i++)
{
printf("В цикле: i=%d, X=%d\n", i, X); // точка 2
...
}
printf("После цикла: X=%d\n", X); // точка 3
...
}
В точке 1 мы увидим на экране число, которое находится в переменной X после ввода зна-
чения с клавиатуры – так можно проверить правильность ввода.
http://kpolyakov.spb.ru
28
I. Введение в программирование © К. Поляков, 1995-2009
В точке 2 мы выводим на экран значения переменных на каждом шаге цикла. Это позво-
ляет сверить их с ручным расчетом и выяснить, верно ли выполняются вычисления в цикле.
В точке 3 значение переменной X после завершения цикла выводится на экран.
Заметим, что трассировку можно применять практически всегда, для этого не нужна про-
грамма-отладчик.
Пошаговое выполнение
Обычно программа выполняет-
ся безостановочно от начала до кон-
ца. Лучший способ отладки — это
выполнить программу по строчкам,
останавливаясь после выполнения
Щелкнуть здесь
каждой команды и проверяя значения (или Ctrl+F5)
переменных в памяти. Для этой цели точка останова
служат специальные программы —
отладчики.
С оболочкой Dev-C++ постав-
ляется отладчики GDB. Сначала
нужно установить точки останова,
то есть отметить строки, где нужно
остановить программу. Для этого
достаточно щелкнуть мышкой слева
от нужной строчки программы на
черном фоне. Повторный щелчок снимает точку останова в этом месте. Кроме того, с помощью
комбинации клавиш Ctrl+F5 можно устанавливать и снимать точку останова в том месте, где
стоит курсор.
Когда в программе есть хотя бы одна точка останова, можно запустить ее в отладочном
режиме, нажав кнопку F8. Отладчик должен остановить программу на первой встретившейся
http://kpolyakov.narod.ru
29
Программирование на языке Си. © К. Поляков, 1995-2012
точке останова. После этого можно выполнять программу в пошаговом режиме (по одной
строчке), нажимая клавишу F7.
Однако в этом режиме отладчик не позволяет входить внутрь вызываемых процедур (по
шагам выполняется только основная программа). Для входа в процедуру или функцию исполь-
зуют комбинацию Shift+F7.
При нажатии клавиш Ctrl+F7 отладчик запускает программу до следующей точки остано-
ва. Завершить отладку можно с помощью комбинации клавиш Ctrl+Shift+F2.
http://kpolyakov.spb.ru
30
I. Введение в программирование © К. Поляков, 1995-2009
причину ошибки, легко ее исправить. Для этого достаточно заменить условие в цикле на
i < N.
http://kpolyakov.narod.ru
31
Программирование на языке Си. © К. Поляков, 1995-2012
рисование мясо
выключение графического режима
хлеб
Что новенького?
• Для использования графических функций надо подключить заголовочный файл
graphics.h.
• Функция initwindow открывает дополнительное окно, в котором можно рисовать. В
скобках нужно указать ширину и высоту этого окна в пикселях.
• Окно с графикой закрывается с помощью функции closegraph.
http://kpolyakov.spb.ru
32
I. Введение в программирование © К. Поляков, 1995-2009
Цвет
Для 16 стандартных цветов заданы числовое и символьное обозначения:
0 BLACK черный 8 DARKGRAY темно-серый
1 BLUE синий 9 LIGHTBLUE светло-синий
2 GREEN зеленый 10 LIGHTGREEN светло-зеленый
3 CYAN морской волны 11 LIGHTCYAN светлый морской волны
4 RED красный 12 LIGHTRED светло-красный
5 MAGENTA фиолетовый 13 LIGHTMAGENTA светло-фиолетовый
6 BROWN коричневый 14 YELLOW желтый
7 LIGHTGRAY светло-серый 15 WHITE белый
Кроме того, можно использовать полную палитру цветов (режим True Color, истинный цвет). В
этом случае цвет строится из трех составляющих: красной (R) , зеленой (G) и синей (B). Каждая
из этих составляющих – целое число от 0 до 255 (256 вариантов), таким образом, всего получа-
ется 2563 = 16 777 216 цветов. Цвета строятся с помощью функции COLOR, у нее в скобках пе-
речисляются через запятую значения составляющих R , G и B (именно в таком порядке). Вот,
например, некоторые цвета:
COLOR(0,0,0) черный
COLOR(255, 0, 0) красный
COLOR(0, 255, 0) зеленый
COLOR(0, 0, 255) синий
COLOR(255, 255, 255) белый
COLOR(100, 100, 100) серый
COLOR(255, 0, 255) фиолетовый
COLOR(255, 255, 0) желтый
Функция setcolor устанавливает цвет линий:
setcolor ( 10 ); // установить светло-зеленый цвет
Все линии (а также прямоугольники, окружности), нарисованные после этой команды, будут
светло-зеленого цвета. Эта же функция может установить цвет из полной палитры:
setcolor ( COLOR(255,0,255) ); // установить фиолетовый цвет
Когда открывается окно для графики, по умолчанию (то есть без дополнительных действий)
устанавливается белый цвет.
Линии
Отрезок можно нарисовать с помощью команды line:
line ( x1, y1, x2, y2 ); // отрезок (x1,y1)-(x2,y2)
Есть и другой способ: сначала перевести курсор (указатель текущего положения) в точку
(x1,y1) командой moveto, а затем нарисовать отрезок в точку (x2,y2) командой lineto:
http://kpolyakov.narod.ru
33
Программирование на языке Си. © К. Поляков, 1995-2012
moveto ( x1, y1 ); // курсор в точку (x1,y1)
lineto ( x2, y2 ); // отрезок в точку (x2,y2)
После выполнения команды lineto курсор смещается в новую точку (x1, y1) (x2, y2)
(x2,y2). Особенно удобно использовать эти команды при рисовании
ломаных линий:
(x5, y5) (x3, y3)
setcolor(12); // красный цвет
moveto (x1, y1); // курсор в первую точку
lineto (x2, y2); // отрезок во вторую точку (x4, y4)
lineto (x3, y3); // и т.д.
lineto (x4, y4);
lineto (x5, y5);
Прямоугольники
Для рисования прямоугольника нужно задать координаты двух проти-
(x1, y1)
воположных углов (обычно выбирают левый верхний и правый ниж-
ний углы). Цвет контура устанавливается с помощью функции
setcolor, а сам прямоугольник рисуется командой rectangle: (x2, y2)
setcolor ( 9 ); (x1, y1)
rectangle (x1, y1, x2, y2);
Закрашенный прямоугольник рисует команда bar. Цвет и стиль залив- (x2, y2)
ки нужно заранее установить, вызвав функцию setfillstyle:
setfillstyle ( 1, 12 ); // стиль 1, цвет 12
bar (x1, y1, x2, y2);
Первое число в команде setfillstyle задает стиль заливки:
0 – отключить заливку
1 – сплошная заливка
3,4,5,6 – наклонные линии
7,8 – сетка
9,10,11 – точечные узоры
а второе – цвет.
Окружность
Чтобы нарисовать окружность, используют функцию circle:
setcolor ( COLOR(0,255,0) ); // зеленый цвет
circle ( x, y, R );
При вызове функции circle в скобках указывают координаты центра и радиус окружности в
пикселях. Это могут быть числа, имена переменных или арифметические выражения, напри-
мер:
circle ( 200, y0+20, R );
http://kpolyakov.spb.ru
34
I. Введение в программирование © К. Поляков, 1995-2009
Для заливки нужно знать координаты (x,y) одной (любой!) точки внутри этой области. Кроме
того, нужно, чтобы граница области была одного цвета, без разрывов. Цвет границы указывает-
ся последним в списке данных, которые передаются функции floodfill.
Надписи
(x, y)
Функция outtextxy позволяет выводить текст в любом месте окна. Ей
нужно задать координаты (x,y) левого верхнего угла текста. Цвет текста Вася
устанавливается с помощью функции setcolor:
setcolor ( 9 );
outtextxy ( x, y, "Вася" );
http://kpolyakov.narod.ru
35
Программирование на языке Си. © К. Поляков, 1995-2012
7. Процедуры
http://kpolyakov.spb.ru
36
I. Введение в программирование © К. Поляков, 1995-2009
Слово void означает, что эта команда выполняет какие-то действия (например, что-то рисует),
а не вычисляет какое-то значение2. В скобках через запятую перечисляются параметры проце-
дуры.
Параметры – это дополнительные данные для работы процедуры.
Можно сделать процедуру без параметров, но она будет всегда выполнять совершенно одина-
ковые действия. Например, всегда будет рисовать синий треугольник в одном и том же месте.
Параметры дают возможность менять результат работы процедуры – перемещать фигуру (из-
меняя параметры x и y) и задавать разные цвета заливки (меняя па-
раметр c). 60
Вспомните, что мы включили в параметры все, что изменяет-
ся. Эти данные заранее неизвестны, поэтому они обозначаются име- (100,100)
нами (переменными) и называются формальными параметрами. В
заголовке процедуры для каждого параметра указывается его тип,
как при объявлении переменных. 100
Как же использовать такую процедуру? Предположим, что левый нижний угол синего
треугольника нужно разместить в точке (100,100). Учитывая, что длина основания тре-
угольника и его высота равны соответственно 100 и 60, находим координаты соответствующих
углов двух других треугольников: (200,100) для зеленого и (200,160) для красного. Решение
нашей задачи выглядит так:
#include <conio.h>
#include <graphics.h>
void Tr ( int x, int y, int c )
{
moveto ( x, y ); // курсор в левый нижний угол
lineto ( x, y-60 ); // рисуем контур
lineto ( x+100, y );
lineto ( x, y );
setfillstyle ( 1, c ); // устанавливаем цвет заливки
floodfill ( x+20, y-20, 15); // заливка до белой границы
}
main()
{
initwindow (400, 300);
Tr (100, 100, COLOR(0,0,255));
Tr (200, 100, COLOR(0,255,0));
Tr (200, 160, COLOR(255,0,0));
getch();
closegraph();
}
Посмотрим на программу внимательно. Процедура (расшифровка, описание новой команды)
расположена выше основной программы. Она оформлена в виде отдельного блока, не внутри
основной программы, а рядом с ней. Строчка
Tr (100, 100, COLOR(0,0,255));
это вызов процедуры. В скобках указаны фактические значения всех параметров (фактические
параметры). При таком вызове первое значение (100) подставляется в процедуру вместо пер-
вого параметра – x, второе значение – вместо второго параметра и т.д. Важно, что к моменту
2
Позднее мы изучим подпрограммы, которые возвращают значение-результат – они называются функциями.
http://kpolyakov.narod.ru
37
Программирование на языке Си. © К. Поляков, 1995-2012
обработки этой строчки транслятор уже знает процедуру Tr, поскольку она была объявлена
выше.
Чтобы нарисовать оставшиеся два треугольника, нам не нужно заново два раза писать все
команды, вошедшие в процедуру, а достаточно вызвать процедуру еще два раз, с другими па-
раметрами:
Tr (200, 100, COLOR(0,255,0));
Tr (200, 160, COLOR(255,0,0));
Что новенького?
• Процедура оформляется так же, как основная программа: заголовок и тело процедуры в фи-
гурных скобках.
• Перед именем процедуры ставится слово void. Это означает, что она предназначена не
для вычислений, а для выполнения некоторых действий.
• После имени в скобках через запятую перечисляются параметры процедуры — те величи-
ны, от которых зависит ее работа. Параметры иногда называют аргументами процедуры.
• Для каждого параметра отдельно указывается его тип (int, float, char).
• Имена параметров можно выбирать любые, допустимые в языке Си.
• Параметры, перечисленные в заголовке процедуры, называются формальными — это зна-
чит, что они доступны только внутри процедуры при ее вызове.
• Желательно выбирать осмысленные имена параметров процедуры — это позволяет легче
разобраться в программе потом, когда уже все забыто.
• При вызове процедуры надо указать ее имя и в скобках фактические параметры, которые
подставляются в процедуре вместо формальных параметров.
• Фактические параметры — это числа или любые арифметические выражения (в этом случае
сначала рассчитывается их значение).
• Первый фактический параметр подставляется в процедуре вместо первого формального па-
раметра, и т.д.
• Процедура должна быть объявлена до основной программы; чтобы к моменту вызова проце-
дуры транслятор знал, что есть такая процедура, а также сколько она имеет параметров и ка-
ких. Это позволяет находить ошибки на этапе трансляции, например такие:
http://kpolyakov.spb.ru
38
I. Введение в программирование © К. Поляков, 1995-2009
8. Функции
Что новенького?
• Функция оформляется так же, как процедура: заголовок и тело функции в фигурных скобках.
• Перед именем функции ставится тип результата (int, float, char, и т.д.) — это озна-
чает, что она возвращает значение указанного типа.
http://kpolyakov.narod.ru
39
Программирование на языке Си. © К. Поляков, 1995-2012
• После имени в скобках через запятую перечисляются параметры функции — те величины,
от которых зависит ее работа.
• Для каждого параметра отдельно указывается его тип (int, float, char).
• Имена параметров можно выбирать любые, допустимые в языке Си.
• Параметры, перечисленные в заголовке функции, называются формальными — это значит,
что они доступны только внутри функции при ее вызове.
• Желательно выбирать осмысленные имена параметров — это позволяет легче разобраться в
программе потом.
• При вызове функции надо указать ее имя и в скобках фактические параметры, которые ис-
пользуются внутри функции вместо формальных параметров.
• Фактические параметры — это числа или любые арифметические выражения (в этом случае
сначала рассчитывается их значение).
• Первый фактический параметр используется внутри функции вместо первого формального
параметра, и т.д.
• Для того, чтобы определить значение функции, используется оператор return, после кото-
рого через пробел записывается возвращаемое значение – число или арифметическое выра-
жение. Примеры:
return 34;
return s;
return a + 4*b - 5;
При выполнении оператора return работа функции заканчивается.
• В функции можно использовать несколько операторов return.
• Если функции расположены ниже основной программы, их необходимо объявить до основ-
ной программы. Для объявления функции надо написать ее заголовок с точкой с запятой в
конце.
• При объявлении функции после заголовка ставится точка с запятой, а в том месте, где запи-
сано тело функции — не ставится.
Логические функции
Очень часто надо составить функцию, которая просто решает какой-то вопрос и отвечает
на вопрос «Да» или «Нет». Такие функции называются логическими. Вспомним, что в Си ноль
означает ложное условие, а единица – истинное.
Логическая функция – это функция, возвращающая 1 (если ответ «Да») или 0 (если ответ
«Нет»).
Логические функции используются, главным образом, в двух случаях:
• если надо проанализировать ситуацию и ответить на вопрос, от которого зависят дальнейшие
действия программы;
• если надо выполнить какие-то сложные операции и определить, была ли при этом какая-то
ошибка.
http://kpolyakov.spb.ru
40
I. Введение в программирование © К. Поляков, 1995-2009
Простое число или нет?
Задача. Ввести число N и определить, простое оно или нет. Использовать функцию, которая
отвечает на этот вопрос.
Теперь расположим тело функции ниже основной программы. Чтобы транслятор знал об
этой функции во время обработки основной программы, надо объявить её заранее.
#include <stdio.h>
#include <conio.h>
int Prime ( int N ); // объявление функции
main()
{
int N;
printf ( "\nВведите целое число ");
scanf ( "%d", &N );
if ( Prime(N) ) // вызов функции
printf ( "Число %d - простое\n", N );
else printf ( "Число %d - составное\n", N );
getch();
}
int Prime ( int N ) // описание функции
{
for ( int i = 2; i*i <= N; i ++ )
if ( N % i == 0 ) return 0; // нашли делитель – составное!
return 1; // не нашли ни одного делителя – простое!
}
Что новенького?
• Если надо, чтобы функция вернула два и более результатов, поступают следующим образом:
o один результат передается как обычно с помощью оператора return
o остальные возвращаемые значения передаются через изменяемые параметры
• Обычные параметры не могут изменяться подпрограммой, потому что она работает с копия-
ми параметров (например, если менять значения a и b в функции MinMax, соответствующие
им переменные N и M в основной программе не изменятся).
• Любая процедура и функция может возвращать значения через изменяемые параметры.
• Изменяемые параметры (или параметры, передаваемые по ссылке) объявляются в заголовке
подпрограммы специальным образом: перед их именем ставится знак & — в данном случае
он означает ссылку, то есть подпрограмма может менять значение параметра (в данном слу-
чае функция меняет значение переменной max в основной программе).
• При вызове таких функций и процедур вместо каждого фактического изменяемого параметра
надо подставлять только имя переменной (не число и не арифметическое выражение — в
этих случаях транслятор выдает предупреждение и формирует в памяти временную пере-
менную).
http://kpolyakov.spb.ru
42
I. Введение в программирование © К. Поляков, 1995-2009
9. Структура программ
Составные части программы
В составе программы можно выделить несколько частей:
• Подключение заголовочных файлов — это строки, которые начинаются с #include
• Объявление констант (постоянных величин):
const N = 20;
• Глобальные переменные — это переменные, объявленные вне основной программы и под-
программ. К таким переменным могут обращаться все процедуры и функции данной про-
граммы (их не надо еще раз объявлять в этих процедурах).
• Объявление функций и процедур — обычно ставятся выше основной программы. По тре-
бованиям языка Си в тот момент, когда транслятор находит вызов подпрограммы, она
должна быть объявлена и известны типы всех ее параметров.
• Основная программа может располагаться как до всех подпрограмм, так и после них. Не
рекомендуется вставлять ее между подпрограммами, так как при этом ее сложнее найти.
глобальная локальная
http://kpolyakov.spb.ru
44
I. Введение в программирование © К. Поляков, 1995-2009
Оформление процедур и функций
При оформлении функций и процедур рекомендуется придерживаться следующих правил:
• Одинаковые операции в разных частях программы оформляются в виде подпрограмм.
• Имена функций и процедур должны быть информативными, то есть нести информацию о
том, что делает эта подпрограмма. К сожалению, транслятор не понимает русские имена,
поэтому приходится писать по-английски. Если вам сложно писать имена на английском
языке, можно писать русские слова английскими буквами. Например, процедуру, рисую-
щую квадрат, можно объявить так:
void Square ( int x, int y, int a );
или так
void Kvadrat ( int x, int y, int a );
• Перед заголовком подпрограммы надо вставлять несколько строк с комментарием (здесь
можно писать по-русски). В комментарий записывается самая важная информация: что
означают параметры подпрограммы, что она делает, какое значение она возвращает (если
это функция), её особенности.
• Не рекомендуется делать подпрограммы длиной более 25-30 строк, так как при этом они
становятся сложными и запутанными. Если подпрограмма получается длинной, ее надо
разбить на более мелкие процедуры и функции.
• Чтобы отделить одну часть подпрограммы от другой, используют пустые строки. Круп-
ный смысловой блок функции можно выделять строкой знаков минус в комментариях.
Приведем пример оформления на примере функции, которая рисует на экране закрашенный
ромб с заданными параметрами, если весь ромб умещается на экран (при этом результат функ-
ции равен 1), или возвращает признак ошибки (число 0).
//**********************************************
// ROMB — рисование ромба в заданной позиции
заголовок
// (x,y) — координаты центра ромба
// a, b — ширина и высота ромба
// color, colorFill — цвета границы и заливки
// Возвращает 1, если операция выполнена, и 0 если
// ромб выходит за пределы экрана
//**********************************************
обработка
int Romb ( int x, int y, int a, int b, int color,
ошибок
int colorFill )
{
if ( (x < a) || (x > 640-a) || (y < b) || (y > 480-b) )
return 0;
//------------------------------------ крупный блок
setcolor ( color );
line ( x-a, y, x, y-b ); line ( x-a, y, x, y+b );
line ( x+a, y, x, y-b ); line ( x+a, y, x, y+b );
return 1;
}
http://kpolyakov.narod.ru
45
Программирование на языке Си. © К. Поляков, 1995-2012
Отступы
Отступы используются для выделения структурных блоков программы (подпрограмм,
циклов, условных операторов). Отступы позволяют легко искать лишние и недостающие скоб-
ки, понимать логику работы программы и находить в ней ошибки. При расстановке отступов
рекомендуется соблюдать следующие правила:
• Величина отступа равна 2-4 символа.
• Дополнительным отступом выделяются
o тело циклов for, while, do-while
o тело условного оператора if и блока else
o тело оператора множественного выбора switch
Вот пример записи программы с отступами (запись «лесенкой»):
main()
{
int a = 1, b = 4, i;
for (i=1; i<2; i++)
{
if ( a > b )
{
b = a + i;
}
else
{
a = b + i;
}
}
printf ( "%d %d\n", a, b );
}
http://kpolyakov.spb.ru
46
I. Введение в программирование © К. Поляков, 1995-2009
10. Анимация
Движение объекта
Составим программу, которая передвигает по экрану какой-то объект (в
нашем случае – квадрат) от левой границы экрана к правой. Программа закан-
чивает работу, когда объект вышел за границы экрана или была нажата клави-
ша Esc.
Предварительный анализ
Рассмотрим объект, который движется по экрану. Пусть это будет
(x, y) квадрат со стороной 20 пикселей. При движении координаты всех его точек
будут меняться. Чтобы строить квадрат в любом месте экрана, мы выберем
его левый верхний угол в качестве базовой (опорной) точки и обозначим ее
(x+20, y+20) координаты за (x,y). Координаты противоположного угла будут равны
(x+20,y+20).
Теперь надо придумать способ изобразить движение так, чтобы рисунок не мигал, и про-
грамма работала одинаково на всех компьютерах независимо от быстродействия. Для этого
применяют такой алгоритм:
1) рисуем фигуру на экране;
2) делаем небольшую задержку (обычно 10-20 мс);
3) стираем фигуру;
4) меняем ее координаты;
5) переходим к шагу 1.
Эти действия повторяются до тех пор, пока не будет получена команда «закончить дви-
жение» (в нашем случае – нажата клавиша Esc или объект вышел за правую границу экрана).
Пусть движение прямоугольника происходит на синем фоне. Тогда самый быстрый и про-
стой способ стереть его – это нарисовать его же, но синим цветом. Поэтому удобно написать
процедуру, параметрами которой являются координаты x и y, а также цвет color. Когда мы
используем синий цвет, фигура стирается с экрана.
void Draw( int x, int y, int color )
{
setfillstyle ( 1, color ); // сплошная заливка, цвет color
bar ( x, y, x+20, y+20 ); // залитый прямоугольник
}
Программа
Программа «в сборе» выглядит так:
#include <conio.h>
#include <graphics.h>
void Draw ( int x, int y, int color )
{
setfillstyle ( 1, color ); // сплошная заливка, цвет color
bar ( x, y, x+20, y+20 ); // залитый прямоугольник
}
main()
{
int x, y; // координаты квадрата
initwindow (400, 400); // открыть окно для графики
setfillstyle(1, COLOR(0,0,255)); // сплошная заливка, синий цвет
bar (0, 0, 399, 399); // залить фон
x = 0; y = 240; // начальные координаты квадрата
/* анимация */
closegraph(); // закрыть окно для графики
}
http://kpolyakov.spb.ru
48
I. Введение в программирование © К. Поляков, 1995-2009
Осталось лишь дописать основной блок, который обозначен в программе комментарием
/* анимация */
В нем нужно организовать цикл анимации, который заканчивается тогда, когда квадрат коснул-
ся границ окна или нажата клавиша Esc.
while ( x + 20 < 400 ) // пока не коснулся границы окна
{
if ( kbhit() ) // если нажата клавиша...
if ( getch() == 27 ) break; // если Esc, выход из цикла
Draw ( x, y, COLOR(255,255,0) ); // рисуем желтый квадрат
delay ( 20 ); // смотрим на него (задержка)
Draw ( x, y, COLOR(0,0,255) ); // стираем
x ++; // перемещаем
}
Цикл while выполняется до тех пор, пока фигура находится в пределах экрана. Нажатие
на клавишу Esc обрабатывается внутри цикла. Сначала мы определяем, нажата ли какая-нибудь
клавиша (с помощью функции kbhit), затем определяем ее код (функция getch) и, если он
равен коду клавиши Esc, выходим из цикла с помощью оператора break.
В основной части цикла рисуем фигуру с помощью процедуры, затем делаем задержку на
20 мс, вызывая функцию delay с параметром 20, и затем стираем фигуру. После этого изменя-
ем координату x и возвращаемся к началу цикла.
Что новенького?
• Чтобы определить нажата ли какая-нибудь клавиша, используется функция kbhit. Она
возвращает 0, если никакая клавиша не нажата, и ненулевое значение, если была нажата
какая-то клавиша.
• Если клавиша уже была нажата, ее код можно получить (без дополнительного ожидания)
с помощью функции getch.
• Чтобы сделать задержку на заданное время, используется процедура delay. Параметром
этой процедуры является величина задержки в миллисекундах. Если уменьшать задержку,
фигура будет двигаться быстрее.
Управление клавишами-стрелками
Предварительный анализ
Принцип работы программы очень простой: получив код клавиши, надо сдвинуть объект в со-
ответствующую сторону. Если обозначить изменения координат фигуры x и y за 1 шаг цикла
через dx и dy, для движения в четырех направлениях получаем:
движение влево dx < 0, dy = 0
движение вправо dx > 0, dy = 0
движение вверх dx = 0, dy < 0
движение вниз dx = 0, dy > 0
Это значит, что надо сделать выбор одного из четырех вариантов в зависимости от кода нажа-
той клавиши. Для этого можно использовать несколько условных операторов if, но существу-
ет специальный оператор switch, который позволяет легко организовать выбор из нескольких
вариантов.
http://kpolyakov.narod.ru
49
Программирование на языке Си. © К. Поляков, 1995-2012
if switch
1 2 1 2 3 4
Еще одна проблема связана с тем, что клавиши управления курсором (стрелки) – не совсем
обычные клавиши. Они относятся к группе функциональных клавиш, у которых нет кодов в
таблице символов. Когда нажата одна из специальных клавиш, система реагирует на нее как на
2 нажатия, причем для первого код символа всегда равен нулю, а для второго мы получим спе-
циальный код (так называемый скан-код, номер клавиши на клавиатуре). Мы будем использо-
вать упрощенный подход, когда анализируется только этот второй код:
влево 75 вверх 72
вправо 77 вниз 80
У такого приема есть единственный недостаток: объект будет также реагировать на нажатие
клавиш с кодами 75, 77, 72 и 80 в таблице символов, то есть на заглавные латинские буквы K,
M, H и P.
Простейший случай
Составим программу, при выполнении которой фигура будет двигаться только тогда, ко-
гда мы нажмем на клавишу-стрелку. В цикле мы сначала рисуем фигуру, ждем нажатия на кла-
вишу и принимаем ее код с помощью функции getch. После этого стираем фигуру в том же
месте (пока не изменились координаты) и, в зависимости от этого кода, меняем координаты
фигуры нужным образом.
Здесь используется бесконечный цикл while(1). Выйти из него можно только одним
способом – через оператор break (досрочный выход из цикла).
while ( 1 ) // бесконечный цикл
{
Draw ( x, y, COLOR(255,255,0) ); // рисуем квадрат
code = getch(); // ждем нажатия клавиши
if ( code == 27 ) break; // если Esc, то выход
Draw ( x, y, COLOR(0,0,255) ); // стираем квадрат
switch ( code ) { // выбор направления
case 75: x --; break; // влево
case 77: x ++; break; // вправо
case 72: y --; break; // вверх
case 80: y ++; // вниз
}
}
В операторе switch значения координат меняются на единицу, хотя можно использовать лю-
бой шаг. В конце обработки каждого варианта надо ставить оператор break, чтобы не выпол-
нялись строки, стоящие ниже. Обратите внимание, что целую переменную code нужно объя-
вить в начале основной программы.
Непрерывное движение
Теперь рассмотрим более сложный случай, когда объект продолжает движение в выбран-
ном направлении даже тогда, когда ни одни клавиша не нажата, а при нажатии клавиши-
стрелки меняет направление. Здесь надо использовать переменные dx и dy, которые задают
направление движения. Сначала мы определяем, нажата ли клавиша, а затем определяем ее код,
http://kpolyakov.spb.ru
50
I. Введение в программирование © К. Поляков, 1995-2009
записываем его в переменную code, и обрабатываем это нажатие с помощью оператора
switch.
dx = 1; dy = 0; // сначала двигается вправо
while ( 1 ) // бесконечный цикл
{
if ( kbhit() ) { // если нажата клавиша
code = getch(); // получить ее код
if ( code == 27 ) break; // если Esc, то выход
switch ( code ) { // изменить направление движения
case 75: dx = -1; dy = 0; break;
case 77: dx = 1; dy = 0; break;
case 72: dx = 0; dy = -1; break;
case 80: dx = 0; dy = 1;
}
}
Draw ( x, y, COLOR(255,255,0) ); // рисуем квадрат
delay ( 10 ); // ждем
Draw ( x, y, COLOR(0,0,255) ); // стираем
x += dx; // двигаем квадрат
y += dy;
}
http://kpolyakov.narod.ru
51
Программирование на языке Си. © К. Поляков, 1995-2012
равномерное неравномерное
распределение распределение
Большинство стандартных датчиков псевдослучайных чисел (то есть формул, по которым они
вычисляются) дают равномерное распределение в некотором интервале.
Поскольку случайные числа в компьютере вычисляются по формуле, то для того, чтобы
повторить в точности какую-нибудь случайную последовательность достаточно просто взять то
же самое начальное значение.
http://kpolyakov.spb.ru
52
I. Введение в программирование © К. Поляков, 1995-2009
Снег на экране
Приведенная ниже программа генерирует случайное значение x в интервале [0,399],
случайное значение y в интервале [0,299] и проверяет цвет точки с координатами (x,y).
Если эта точка черная, то ее цвет устанавливается случайный, а если нет — черный. Случайный
цвет строится с помощью стандартной функции COLOR из красной (R), зеленой (G) и синей (B)
составляющих, которые выбираются случайно в интервале [0,255].
#include <graphics.h>
#include <conio.h>
#include <stdlib.h>
int random (int N) { return rand() % N; } // функция
main()
{
int x, y, R, G, B;
initwindow (500, 500);
while ( ! kbhit () ) { // пока не нажата клавиша
x = random(400); // случайные координаты
y = random(300);
R = random(256); // случайный цвет (R,G,B)
G = random(256);
B = random(256);
if ( getpixel(x,y) != 0 ) // если точка не черного цвета
putpixel ( x, y, 0 ); // делаем ее черной
else // иначе...
putpixel ( x, y, COLOR(R,G,B) ); // случайный цвет
}
getch();
closegraph();
}
Что новенького?
• для определения того, была ли нажата какая-нибудь клавиша, используется функция
kbhit, которая возвращает 0, если клавиша не была нажата, и ненулевое значение, если
нажата любая клавиша. Для того, чтобы определить код этой клавиши, надо вызвать
функцию getch. Таким образом, цикл «пока не нажата клавиша» может выглядеть так:
http://kpolyakov.spb.ru