2.20M
Категория: ПрограммированиеПрограммирование

Программирование на языке высокого уровня. Лекция 5. Подпрограммы и функции

1.

Богатов Р.Н.
Программирование
на языке высокого уровня
C++ ► Лекция 5 ► Подпрограммы и функции
Кафедра АСОИУ ОмГТУ, 2020

2.

const
int N=10;
void
main()
{int a[N];
const int N=10; int a[N];
void massiv_sluchaino(int A, int B);
void//
massiv();
1. Случайное заполнение
voidsrand(time(0));
massiv_sort();
voidfor(int
massiv_perevorot();
i=0; i<N; i++)
Подпрограммы
Предварительное объявление
(forward
... declaration)
const int N=10;
int a[N];
a[i] = rand() % 100;
void main()
{
// вывод
...
for(int i=0; i<N; i++)
}
printf("%d ", a[i]);
printf("\n\n");
void massiv_sluchaino(int
A, int B)
{
//
2. Сортировка
for(int
i=0; i<N; i++)
for(int
i=0;
i++)% (B-A);
a[i] = Ai<N-1;
+ rand()
for(int j=i+1; j<N; j++)
}
void massiv() if (a[i]>a[j]) swap(&a[i], &a[j]);
{
//
вывод i=0; i<N; i++)
for(int
for(int i=0; i<N; i++)
printf("%d ", a[i]);
printf("%d ", a[i]);
printf("\n\n");
printf("\n\n");
_getch();
}
...
}
3. Переворот
void//
massiv_sort()
{
for(int i=0; i<N/2; i++)
for(int
i=0; i<N-1;
i++)
swap(&a[i],
&a[N-1-i]);
for(int j=i+1; j<N; j++)
// вывод
if (a[i]>a[j]) swap(&a[i], &a[j]);
for(int i=0; i<N; i++)
printf("%d ", a[i]);
void massiv_perevorot()
printf("\n\n");
{
void main()
{
massiv_sluchaino(0, 100);
massiv();
massiv_sort();
massiv();
massiv_perevorot();
massiv();
Определение
(definition)
}
}
}
for(int i=0; i<N/2; i++)
_getch();
swap(&a[i], &a[N-1-i]);
Замечания:
1. Предварительное объявление не обязательно. Вместо этого
можно все определения перенести наверх (до функции main).
2. Массив пришлось объявить глобально (вне main). Почему?

3.

...
...
...
int min(int x, int y)
intmin(int
min(int x,int
inty)y)
int
{ min(int x,
int
x, int y)
{{
return x<y? x: y;
{
returnx<y?
x<y? x:y;y;
return
} return x<y? x:
x: y;
}}
}
1>------ Построение начато: -----double min(double 1>
x, double
y)
main.cpp
double
min(double
x,
double
y)
void
{ main()
void
main()
1> .\main.cpp(29): error C2666: min: для 2 перегрузок есть
{{
return x<y? x:подобные
y;
преобразования
{
return x<y? x: y;
...
1> .\main.cpp(12): может быть "double min(double,double)"
} ...
} // найти минимальное
из 4 чисел
1> .\main.cpp(7):
или
"int min(int,int)"
// найти минимальное
из 4 чисел
int main()
a, b, c, d; 1> при попытке сопоставить список аргументов "(int, double)"
void
double a, b, c, d;
==========
Построение: успешно: 0, с ошибками: 1 ==========
void
main()
4 числа: ");
{ printf("Введите
printf("Введите 4 вещественных числа: ");
{ scanf("%d%d%d%d", &a, &b, &c, &d);
int a;
scanf("%lg%lg%lg%lg",
&a, &b, &c, &d);
// найти минимальное из 4 чисел
printf("Введите целое число: ");
double a, b, c, d; из них: %d", min(a, min(b, min(c, d))) );
printf("Минимальное
scanf("%d", &a); из них: %lg", min(a, min(b, min(c, d))) );
printf("Минимальное
printf("Введите 4 вещественных числа: ");
_getch();
double b;
_getch();
scanf("%lg%lg%lg%lg", &a, &b, &c, &d);
}
printf("Введите дробное число: ");
}
scanf("%lg", &b);
printf("Минимальное из них: %lg", min(a, min(b, min(c, d))) );
_getch();
printf("Минимальное из них: %lg", min(
min(a,
(double)a,
b) );
b) );
}
_getch();
}
Перегрузка функций

4.

Вычисляем НОД и НОК
// прямой перебор делителей
int НОД = 1;
for (int i = 2; i <= min(A, B); i++)
if (A % i == 0 && B % i == 0)
НОД = i;
// обратный поиск наибольшего делителя
int НОД = 0;
for (int i = min(A, B); НОД == 0; i--)
if (A % i == 0 && B % i == 0)
НОД = i;
// прямой перебор общих кратных
int НОК = 0;
for (int i = max(A, B); НОК == 0; i++)
if (i % A == 0 && i % B == 0)
НОК = i;
int НОД(int A, int B)
{
for (int i = min(A, B); ; i--)
if (A % i == 0 && B % i == 0)
return i;
}
int НОК(int A, int B)
{
for (int i = max(A, B); ; i++)
if (i % A == 0 && i % B == 0)
return i;
}

5.

Вычисляем НОД по алгоритму Евклида
void
main() A, int B);
int НОД(int
{int НОК(int A, int B);
int a, b;
voidprintf("Введите
main()
два целых числа: ");
{ scanf("%d%d", &a, &b);
int a, b;
printf("Введите
два целых числа: ");
while
(b)
{scanf("%d%d", &a, &b);
printf("НОД(%d, %d) =\n", a, b );
printf("НОД(%d,
%d) = %d\n", a, b, НОД(a, b) );
int t = b;
printf("НОК(%d, %d) = %d\n", a, b, НОК(a, b) );
b = a % b;
}
a = t;
int НОД(int A, int B)
int }НОД(int A, int B)
{
{
if (B == 0) return A;
while (B)
printf("= %d\n", a );
else return НОД(B, A % B);
{
}
}
int t = B;
B = A % B;
int НОК(int A, int B)
A = t;
{
}
return abs(A*B)/НОД(A, B);
http://ru.wikipedia.org/wiki/Алгоритм_Евклида
return A;
}
}

6.

...
double y(double x);
void metod_del_popolam(double a, double b, double eps, int N);
Решение
нелинейного
уравнения
void main()
{
setlocale(LC_ALL, "Russian");
void
metod_del_popolam(double
double
b, double
eps, int N)
printf("Поиск
корней функции a,
y(x)
= cos(x)
- x^3.\n");
{
printf("\nПоиск
double
x1=0, x2=1; корня методом деления пополам:\n");
double c = 0, интервал
fc = 0; поиска [x1; x2]: ");
printf("Введите
double fa = y(a);
scanf("%lg%lg",
&x1, &x2);
double
fb
=
y(b);
...
// +здесь ещё должна быть проверка на наличие корней if (fa*fb>=0)
int i = 1;
metod_del_popolam(x1,
x2, eps, N);
for
(;
i
<
N;
i++)
//metod_iteraziy((x1+x2)/2, eps, N);
{
//metod_Newtona((x1+x2)/2,
eps, N);
c
=
(a
+
b)
/
2;
//metod_hord(x1, x2, eps, N);
fc = y(c);
_getch();
// +вывод протокола итерации (если нужно)
}
if (b - x)
c < eps) break;
double y(double
if (fa * fc < 0)
{
b = -c,pow(x,
fb = fc;
return cos(x)
3);
else
}
a = c, fa = fc;
void }metod_del_popolam(double a, double b, double eps, int N)
{
...// +вывод результата
}}

7.

Пора
писать
нормальную
игрушку!

8.

int main()
const int N = 19, M = 34;
{ int xt = 1, yt = 1, dxt = 1, dyt = 0; // координаты и направление движение танка
int a[N][M];
bool
tank_shot
= false;
srand(time(0));
//
показана
логика
только
одного
бота
(в игремассив
— массив
такихлетящих
ботов)в разные стороны)
const
int brick
177;
//
код
символа
для
стенсделать
// здесь
здесь
логика= только
одного
снаряда

можно
снарядов,
int
score
=
0,
hp
=
7;
field_init();
//
создать
в
массиве
поле
с
бордюром
int
xb
= 0;
...
...
int
xs==0,
0,yb
ys,
dxs, dys; // координаты и направление полёта снаряда
...
add_walls();
//
добавить на поле случайные стены
...
...
void
aid_respawn()
void
field_init()
bullets_init();
// занулить массивы для снарядов
void
tank_move()
int{ sign(int
a) // sign(x) — знак аргумента x: +1, -1 или 0.
{ { void
new_bullet()
bots_init(); // занулить массивы координат ботов
{
int x,
for
(int
i +=y;
1; //
i <поместить
N-1;
i++)
{ aid_respawn();
поля +аптечку
if
(a[yt
dyt][xt
+ adxt]
'случайном
': ||
+ dyt][xt
dxt] == '+')
return
a
<
0
?
-1
:
>
0 ==
?в +1
0; a[yt месте
do
{
for
(int
j
=
1;
j
<
M-1;
j++)
if
(a[yt
+
dyt][xt
+
dxt]
!=
brick)
{
}
xa[i][j]
= xt
1 +
++dyt][xt
rand()
2);
' ';ys%+=(M
xs
=
yt- +
dyt,
dxs = dxt, dys = dyt;
for(intifframe=0;
;=dxt,
frame++)
(a[yt
dxt]
==
'+')
y
=
1
+
rand()
%
(N
2);
void
bot_move()
}{
hp++, score++, aid_respawn();
} while
!= ' ');
{ for (int
i = (a[y][x]
0;% i200
< N;
if (frame
==i++)
100)
voidifbullet_move()
a[y][x]
=
'+';
(xb
==
0)
return;
//
бота
нет (например,
он рождается
погиб и пока
не бот
возродился)
a[i][0]
=
a[i][M
1]
= brick;
= ' ';
new_bot();
// через
каждые
200 тактов
ещёещё
один
{ } int a[yt][xt]
dx,+=dy;
xt
dxt;
bullets_move();
// xs
каждый
продвигается
на одну
клетку
if
(xsj !=
0)xt)
//<>
если
==
0,снаряд
то//
снаряд
не летит
(его
впо
игре
нет)и вертикали
if(int
(abs(xb
abs(yb
yt))
расстояние
до
танка
гориз.
for
=
1;
j
M-1;
j++)
... { yt += dyt;
dx = sign(xt
xb),
dybrick;
=
0; // dx
будет +1 или -1 в направлении танка
a[0][j]
= a[N
--1][j]
=
254;
// код
символа
танчика
ifa[yt][xt]
(frame
% =3=
==
0)
a[ys][xs]
'
';
}
void
check_keyboard()
}else
// боты двигаются раз в три такта
xsbots_move();
dxs; - yb),
dy
=+=
sign(yt
dx = 0; // dy будет +1 или -1 в направлении танка
{
}
if (frame
% 2 == 0 && !tank_shot)
void draw_field()
ys
+=
dys;
while (_kbhit())
tank_move();
// танк
двигается
раз==в xt
два
{ void tank_die()
if (a[yb
+ dy][xb
+ dx]
== ' '
|| xb + dx
&& такта
yb + dy == yt)
switch
(_getch())
{ system("cls");
if
(xb
!=
0
&&
xs
==
xb
&&
ys
==
yb)
{
{
a[yt][xt]
'X';
for
(int
i = 0;
i=xs
<' N;
i++,
printf("\n"))
anim_explosion();
//
нарисовать
очередной кадр анимации взрыва (если есть)
=';0,
bot_die(),
a[yb][xb]
case
'K':
dxt
= -1; dytscore++;
= 0; break;
}
for
j =yb
0;+=
j < M;
j++)
anim_bot_respawn();
// =
нарисовать
очередной
xb(int
+= else
dx;
case
'M':dy;
dxt
+1; dyt = 0;
break; кадр анимации [пере]рождения бота
a[i][j]);
if'H':
(a[ys][xs]
==dyt
'+')
draw_field();
//
вывести
на
экран
массив
с текущим тактом игры
if printf("%c",
(xb case
== xt
&&
yb
===yt)
void tank_harm()
dxt
0;
= -1;
break;
}{
= 0,
aid_respawn();
draw_footer();
//=xs
вывести
наdyt
экран
футер:
tank_shot
true,
tank_die();
case 'P':
dxt
= bot_die(),
0;
= +1;
break;информацию о счёте и здоровье
else
else
system("color
04");
case
' ': new_bullet(); break;
void draw_footer()
(a[ys][xs]
' ') повреждения танку
if (tank_shot)
tank_harm();
// ==
нанести
a[yb][xb]
=if
'A';
system("color
07");
case
27:
exit(0);
{
a[ys][xs] = 249; // код символа снаряда
}
tank_shot
} = false;
printf("Score:
%d. Health:
", score);
else
Sleep(40);
//
задержка
40 миллисекунд, функция из windows.h
else
hp--;
}for (int i = 0; i < hp; i++) на
printf("+");
xs
=
0;
;==//0)=здесь
хорошо
повторить
то
check_keyboard();
//бы
отработать
нажатые
a[yt][xt]
254;
// код
символа
танчика
if
(hp
{
printf("none.\n\n
GжеA самое,
M Eклавиши
OноV сE условием
R "); _getch(); exit(0); }
}
...
//
if
(abs(xb
xt)
<
abs(yb
yt)),
либо
сделать
случайный ход
}
}
} }
} }

9.

// парочка лайфхаков, чтобы уменьшить мерцание и ускорить вывод
#include <windows.h>
...
void gotoxy(int xpos, int ypos) // поставит курсор в нужную позицию консоли
{
COORD scrn;
HANDLE hOuput = GetStdHandle(STD_OUTPUT_HANDLE);
scrn.X = xpos; scrn.Y = ypos;
SetConsoleCursorPosition(hOuput, scrn);
}
void draw_field()
{
gotoxy(0, 0); // вместо очистки экрана ставим курсор в начало и выводим поверх
//system("cls");
for (int i = 0; i < N; i++, printf("\n"))
for (int j = 0; j < M; j++)
printf("%c", a[i][j]);
}
void cursor_off() // прячет курсор, чтобы не мигал (вызвать единожды в начале main)
{
void* handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO structCursorInfo;
GetConsoleCursorInfo(handle, &structCursorInfo);
structCursorInfo.bVisible = FALSE;
SetConsoleCursorInfo(handle, &structCursorInfo);
}
...

10.

Домашнее задание
Реализовать генератор псевдо-случайных чисел в виде
собственных функций, аналогичных rand() и srand(), добавив
перегрузку rand(int min, int max) и отдельную функцию
rand_double(), возвращающую случайное число из [0; 1).
English     Русский Правила