added double jump and sitting state
This commit is contained in:
parent
2e5c5a8dde
commit
90d07dde3f
148 changed files with 13050 additions and 0 deletions
BIN
term1/questions_1.pdf
Normal file
BIN
term1/questions_1.pdf
Normal file
Binary file not shown.
14
term1/seminar01_overload/01_myspace/myspace.cpp
Normal file
14
term1/seminar01_overload/01_myspace/myspace.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <iostream>
|
||||
using std::cout;
|
||||
|
||||
namespace myspace {
|
||||
void print_n_times(char str[], int n = 10) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
cout << str;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
char s[] = "nya\n";
|
||||
myspace::print_n_times(s);
|
||||
}
|
11
term1/seminar01_overload/02_cubev/cubev.cpp
Normal file
11
term1/seminar01_overload/02_cubev/cubev.cpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <iostream>
|
||||
using std::cout, std::endl;
|
||||
|
||||
int cubeV(int x) {
|
||||
return x * x * x;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int x = 3;
|
||||
cout << cubeV(x) << endl;
|
||||
}
|
12
term1/seminar01_overload/03_cuber/cuber.cpp
Normal file
12
term1/seminar01_overload/03_cuber/cuber.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include <iostream>
|
||||
|
||||
using std::cout, std::endl;
|
||||
|
||||
int cubeR(int& x) {
|
||||
return x * x * x;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int x = 3;
|
||||
cout << cubeR(x) << endl;
|
||||
}
|
26
term1/seminar01_overload/04_count_letters/count_letters.cpp
Normal file
26
term1/seminar01_overload/04_count_letters/count_letters.cpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include <iostream>
|
||||
using std::cout, std::endl;
|
||||
|
||||
void count_letters(char str[], int& n_letters, int& n_digits, int& n_other) {
|
||||
while (*str) {
|
||||
if (*str >= 'a' && *str <= 'z' || *str >= 'A' && *str <= 'Z') {
|
||||
n_letters += 1;
|
||||
}
|
||||
else if (*str >= '0' && *str <= '9') {
|
||||
n_digits += 1;
|
||||
}
|
||||
else {
|
||||
n_other += 1;
|
||||
}
|
||||
str += 1;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
int n_letters = 0, n_digits = 0, n_other = 0;
|
||||
|
||||
char s[] = "1n!2y#3a$";
|
||||
count_letters(s, n_letters, n_digits, n_other);
|
||||
|
||||
cout << "letters: " << n_letters << endl << "digits: " << n_digits << endl << "n_other: " << n_other << endl;
|
||||
}
|
20
term1/seminar01_overload/05_add_price/add_price.cpp
Normal file
20
term1/seminar01_overload/05_add_price/add_price.cpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include <iostream>
|
||||
|
||||
using std::cout, std::endl;
|
||||
|
||||
struct Book {
|
||||
char title[100];
|
||||
int pages;
|
||||
float price;
|
||||
};
|
||||
|
||||
void addPrice(Book& b, float x) {
|
||||
b.price += x;
|
||||
}
|
||||
|
||||
int main() {
|
||||
Book b = {"One Hundred Years of Solitude", 456, 1200};
|
||||
float x = 15.6;
|
||||
addPrice(b, x);
|
||||
cout << b.price << endl;
|
||||
}
|
20
term1/seminar01_overload/06_is_expensive/is_expensive.cpp
Normal file
20
term1/seminar01_overload/06_is_expensive/is_expensive.cpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include <iostream>
|
||||
using std::cout, std::endl;
|
||||
|
||||
struct Book {
|
||||
char title[100];
|
||||
int pages;
|
||||
float price;
|
||||
};
|
||||
|
||||
bool isExpensive(const Book& b) {
|
||||
if (b.price > 1000) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int main() {
|
||||
Book b = {"One Hundred Years of Solitude", 456, 1200};
|
||||
cout << isExpensive(b) << endl;
|
||||
}
|
38
term1/seminar01_overload/07_vector3f/main.cpp
Normal file
38
term1/seminar01_overload/07_vector3f/main.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include <iostream>
|
||||
#include "vector3f.h"
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
Vector3f a = {1.0, 2.0, -2.0};
|
||||
Vector3f b = {4.0, -1.0, 3.0};
|
||||
cout << "a = " << a << endl << "b = " << b << endl;
|
||||
cout << "a + b = " << a + b << endl;
|
||||
cout << "a - b = " << a - b << endl;
|
||||
|
||||
cout << "0.5 * a = " << 0.5 * a << endl;
|
||||
cout << "a * 0.5 = " << a * 0.5 << endl;
|
||||
|
||||
cout << "(a, b) = " << a * b << endl;
|
||||
|
||||
cout << "a / 5 = " << a / 5 << endl;
|
||||
|
||||
cout << "-a = " << -a << endl;
|
||||
cout << "+a = " << +a << endl;
|
||||
|
||||
cout << "a == b = " << (a == b) << endl;
|
||||
cout << "a != b = " << (a != b) << endl;
|
||||
|
||||
a += b;
|
||||
cout << "a += b: " << a << endl;
|
||||
|
||||
a -= b;
|
||||
cout << "a -= b: " << a << endl;
|
||||
|
||||
a *= 2;
|
||||
cout << "a *= 2: " << a << endl;
|
||||
a /= 2;
|
||||
cout << "a /= 2: " << a << endl;
|
||||
|
||||
normalize(a);
|
||||
cout << "normalize(a): " << a << " |a| = " << norm(a) << endl;
|
||||
}
|
96
term1/seminar01_overload/07_vector3f/vector3f.h
Normal file
96
term1/seminar01_overload/07_vector3f/vector3f.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
#pragma once
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
struct Vector3f {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
Vector3f operator+(const Vector3f& a, const Vector3f& b) {
|
||||
Vector3f result = {a.x + b.x, a.y + b.y, a.z + b.z};
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3f operator-(const Vector3f& a, const Vector3f& b) {
|
||||
Vector3f result = {a.x - b.x, a.y - b.y, a.z - b.z};
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3f operator*(const Vector3f& a, float f) {
|
||||
Vector3f result = {f * a.x, f * a.y, f * a.z};
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3f operator*(float f, const Vector3f& a) {
|
||||
Vector3f result = {f * a.x, f * a.y, f * a.z};
|
||||
return result;
|
||||
}
|
||||
|
||||
int operator*(const Vector3f& a, const Vector3f& b) {
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
}
|
||||
|
||||
Vector3f operator/(const Vector3f& a, float f) {
|
||||
Vector3f result = {a.x / f, a.y / f, a.z / f};
|
||||
return result;
|
||||
}
|
||||
|
||||
Vector3f operator+(const Vector3f& a) {
|
||||
return a;
|
||||
}
|
||||
|
||||
Vector3f operator-(const Vector3f& a) {
|
||||
Vector3f result = {-a.x, -a.y, -a.z};
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator==(const Vector3f& a, const Vector3f& b) {
|
||||
if (a.x == b.x && a.y == b.y && a.z == b.z) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator!=(const Vector3f& a, const Vector3f& b) {
|
||||
return not (a == b);
|
||||
}
|
||||
|
||||
void operator+=(Vector3f& a, const Vector3f& b) {
|
||||
a = a + b;
|
||||
}
|
||||
|
||||
void operator-=(Vector3f& a, const Vector3f& b) {
|
||||
a = a - b;
|
||||
}
|
||||
|
||||
void operator*=(Vector3f& a, float f) {
|
||||
a = f * a;
|
||||
}
|
||||
|
||||
void operator/=(Vector3f& a, float f) {
|
||||
a = a / f;
|
||||
}
|
||||
|
||||
float squared_norm(const Vector3f& a) {
|
||||
return a * a;
|
||||
}
|
||||
|
||||
float norm(const Vector3f& a) {
|
||||
return sqrt(squared_norm(a));
|
||||
}
|
||||
|
||||
void normalize(Vector3f& a) {
|
||||
a /= norm(a);
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream& in, Vector3f& a) {
|
||||
in >> a.x >> a.y >> a.z;
|
||||
return in;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const Vector3f& a) {
|
||||
out << "(" << a.x << ", " << a.y << ", " << a.z << ")";
|
||||
return out;
|
||||
}
|
189
term1/seminar01_overload/08_complex/complex.h
Normal file
189
term1/seminar01_overload/08_complex/complex.h
Normal file
|
@ -0,0 +1,189 @@
|
|||
#pragma once
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
struct Complex {
|
||||
float re;
|
||||
float im;
|
||||
};
|
||||
|
||||
|
||||
// Передаёмм аргументы через ссылки
|
||||
// В данном случае можно было передавать по значению
|
||||
// (так как Complex имеет малый размер)
|
||||
// Но в общем случае лучше для структур лучше
|
||||
// всегда использовать ссылки
|
||||
|
||||
Complex operator+(const Complex& a, const Complex& b) {
|
||||
Complex result = {a.re + b.re, a.im + b.im};
|
||||
return result;
|
||||
}
|
||||
|
||||
Complex operator-(const Complex& a, const Complex& b) {
|
||||
Complex result = {a.re - b.re, a.im - b.im};
|
||||
return result;
|
||||
}
|
||||
|
||||
Complex operator*(const Complex& a, const Complex& b) {
|
||||
Complex result = {a.re * b.re - a.im * b.im, a.re * b.im + a.im * b.re};
|
||||
return result;
|
||||
}
|
||||
|
||||
Complex operator/(const Complex& a, const Complex& b) {
|
||||
float b_squared = b.re * b.re + b.im * b.im;
|
||||
|
||||
Complex result;
|
||||
result.re = (a.re * b.re + a.im * b.im) / b_squared;
|
||||
result.im = (a.im * b.re - a.re * b.im) / b_squared;
|
||||
return result;
|
||||
}
|
||||
|
||||
Complex& operator+=(Complex &a, const Complex &b) {
|
||||
a.re += b.re;
|
||||
a.im += b.im;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
// Унарный оператор -
|
||||
// То есть если z - комплексное число x + iy, то -z = - x - iy
|
||||
Complex operator-(const Complex& a) {
|
||||
Complex result;
|
||||
result.re = -a.re;
|
||||
result.im = -a.im;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Унарный оператор +
|
||||
// Ничего не меняет
|
||||
Complex operator+(const Complex& a) {
|
||||
Complex result = a;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Унарный оператор *
|
||||
// То есть если z - комплексное число x + iy, то *z = x - iy
|
||||
// Оператор сопряжения
|
||||
Complex operator*(const Complex& a) {
|
||||
Complex result;
|
||||
result.re = a.re;
|
||||
result.im = -a.im;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Число + комплексное число (в таком порядке)
|
||||
Complex operator+(float a, const Complex& b) {
|
||||
Complex result = b;
|
||||
result.re += a;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Комплексное число + число
|
||||
Complex operator+(const Complex& a, float b) {
|
||||
Complex result = a;
|
||||
result.re += b;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Число - комплексное число (в таком порядке)
|
||||
Complex operator-(float a, const Complex& b) {
|
||||
Complex result = -b;
|
||||
result.re += a;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Комплексное число - число
|
||||
Complex operator-(const Complex& a, float b) {
|
||||
Complex result = a;
|
||||
result.re -= b;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Комплексное число * число
|
||||
Complex operator*(const Complex& a, float b) {
|
||||
Complex result = a;
|
||||
result.re *= b;
|
||||
result.im *= b;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Число * комплексное число
|
||||
Complex operator*(float a, const Complex& b) {
|
||||
Complex result = b;
|
||||
result.re *= a;
|
||||
result.im *= a;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// Комплексное число / число
|
||||
Complex operator/(const Complex& a, float b) {
|
||||
Complex result = a;
|
||||
result.re /= b;
|
||||
result.im /= b;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Число / комплексное число
|
||||
Complex operator/(float a, const Complex& b) {
|
||||
float b_squared = b.re * b.re + b.im * b.im;
|
||||
return (a * (*b)) / b_squared;
|
||||
}
|
||||
|
||||
|
||||
// Перегружаем оператор<< между типами
|
||||
// std::ostream (такой тип имеет std::cout) и Complex
|
||||
// Обратите внимание, что мы возвращаем ссылку на ostream
|
||||
// Таким образом результатом выражения cout << a будет cout
|
||||
// Поэтому можно делать так: cout << a << b << c ...
|
||||
std::ostream& operator<<(std::ostream& out, const Complex& a) {
|
||||
if (a.re != 0)
|
||||
out << a.re;
|
||||
|
||||
if (a.im > 0) {
|
||||
if (a.im != 1.0)
|
||||
out << " + " << a.im << "i";
|
||||
else
|
||||
out << " + i";
|
||||
}
|
||||
else if (a.im < 0) {
|
||||
if (a.im != -1.0)
|
||||
out << " - " << -a.im << "i";
|
||||
else
|
||||
out << " - i";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream& in, Complex& c) {
|
||||
in >> c.re >> c.im;
|
||||
return in;
|
||||
}
|
||||
|
||||
float abs(const Complex& a) {
|
||||
return sqrtf(a.re * a.re + a.im * a.im);
|
||||
}
|
||||
|
||||
Complex exp(const Complex& a) {
|
||||
Complex result;
|
||||
result.re = expf(a.re) * cosf(a.im);
|
||||
result.im = expf(a.re) * sinf(a.im);
|
||||
return result;
|
||||
}
|
||||
|
||||
Complex sin(const Complex& a) {
|
||||
Complex result;
|
||||
result.re = sinf(a.re) * coshf(a.im);
|
||||
result.im = cosf(a.re) * sinhf(a.im);
|
||||
return result;
|
||||
}
|
||||
|
||||
Complex cos(const Complex& a) {
|
||||
Complex result;
|
||||
result.re = cosf(a.re) * coshf(a.im);
|
||||
result.im = sinf(a.re) * sinhf(a.im);
|
||||
return result;
|
||||
}
|
56
term1/seminar01_overload/08_complex/complex_image.cpp
Normal file
56
term1/seminar01_overload/08_complex/complex_image.cpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include "complex.h"
|
||||
using namespace std;
|
||||
|
||||
// В этой программе мы рисуем в картинку комплексную функцию,
|
||||
// которая задаётся в функции func
|
||||
|
||||
struct Color {
|
||||
unsigned char r, g, b;
|
||||
};
|
||||
|
||||
Complex func(Complex z) {
|
||||
Complex f = 100/(z - 1)*exp(z);
|
||||
f.re = fabs(f.re);
|
||||
f.im = fabs(f.im);
|
||||
if (f.re > 255)
|
||||
f.re = 255;
|
||||
if (f.im > 255)
|
||||
f.im = 255;
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
int width = 800, height = 800;
|
||||
float x0 = -2.0f, x1 = 2.0f;
|
||||
float y0 = -2.0f, y1 = 2.0f;
|
||||
|
||||
// Выделяем память под пиксели
|
||||
Color* data = (Color*)malloc(sizeof(Color) * width * height);
|
||||
|
||||
// data - это массив цветов размером width * height
|
||||
// Задаём значения этого массива так, чтобы
|
||||
// реальная часть функции func соответствовала зелёному цвету,
|
||||
// а мнимая часть -- синей компоненте цвета
|
||||
for (int j = 0; j < height; j++) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
Complex z = {x0 + (x1-x0) / width * i, y0 + (y1-y0) / width * j};
|
||||
Complex f = func(z);
|
||||
data[i + width * j].r = 0;
|
||||
data[i + width * j].g = f.re;
|
||||
data[i + width * j].b = f.im;
|
||||
}
|
||||
}
|
||||
|
||||
// Сохраняем массив цветов data как картинку в формате .ppm
|
||||
FILE* file = fopen("complex_image.ppm", "wb");
|
||||
fprintf(file, "P6\n%d %d\n255\n", width, height);
|
||||
fwrite(data, sizeof(Color), height * width, file);
|
||||
fclose(file);
|
||||
|
||||
// Освобождаем память
|
||||
free(data);
|
||||
}
|
63
term1/seminar01_overload/08_complex/complex_movie.cpp
Normal file
63
term1/seminar01_overload/08_complex/complex_movie.cpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include "complex.h"
|
||||
using namespace std;
|
||||
|
||||
// Это программа создаёт анимацию (набор картинок)
|
||||
// которая задаётся как меняющееся во времени
|
||||
// комплексная функция (описана в функции func)
|
||||
|
||||
|
||||
struct Color {
|
||||
unsigned char r, g, b;
|
||||
};
|
||||
|
||||
Complex func(Complex z, int time) {
|
||||
Complex f = 100/(z - (0.02f*time))*exp(z*sin(z));
|
||||
f.re = fabs(f.re);
|
||||
f.im = fabs(f.im);
|
||||
if (f.re > 255)
|
||||
f.re = 255;
|
||||
if (f.im > 255)
|
||||
f.im = 255;
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
int width = 800, height = 800;
|
||||
float x0 = -2.0f, x1 = 2.0f;
|
||||
float y0 = -2.0f, y1 = 2.0f;
|
||||
Color* data = (Color*)malloc(sizeof(Color) * width * height);
|
||||
|
||||
// Повторяем 200 раз
|
||||
int max_time_steps = 200;
|
||||
for (int time = 0; time < max_time_steps; time++)
|
||||
{
|
||||
// Задаём изображение в массиве data
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
for (int i = 0; i < width; i++)
|
||||
{
|
||||
Complex z = {x0 + (x1-x0) / width * i, y0 + (y1-y0) / width * j};
|
||||
Complex f = func(z, time);
|
||||
data[i + width * j].r = 0;
|
||||
data[i + width * j].g = f.re;
|
||||
data[i + width * j].b = f.im;
|
||||
}
|
||||
}
|
||||
|
||||
// Создаём в строке filename имя изображения
|
||||
// Папка animation должна существовать!
|
||||
char filename[100];
|
||||
sprintf(filename, "animation/complex_%03d.ppm", time);
|
||||
|
||||
// Сохраняем изображение в картинке по имени filename
|
||||
FILE* file = fopen(filename, "wb");
|
||||
fprintf(file, "P6\n%d %d\n255\n", width, height);
|
||||
fwrite(data, sizeof(Color), height * width, file);
|
||||
fclose(file);
|
||||
}
|
||||
free(data);
|
||||
}
|
BIN
term1/seminar01_overload/08_complex/complex_movie.mp4
Normal file
BIN
term1/seminar01_overload/08_complex/complex_movie.mp4
Normal file
Binary file not shown.
38
term1/seminar01_overload/08_complex/complex_test.cpp
Normal file
38
term1/seminar01_overload/08_complex/complex_test.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include <iostream>
|
||||
#include "complex.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Тут мы тестируем нашу реализацию комплексных чисел
|
||||
|
||||
int main() {
|
||||
Complex a;
|
||||
Complex b;
|
||||
|
||||
cin >> a >> b;
|
||||
|
||||
cout << "a = " << a << endl
|
||||
<< "b = " << b << endl
|
||||
<< "a + b = " << a + b << endl
|
||||
<< "a - b = " << a - b << endl
|
||||
<< "a * b = " << a * b << endl
|
||||
<< "a / b = " << a / b << endl
|
||||
<< "-a = " << -a << endl
|
||||
<< "+a = " << +a << endl
|
||||
<< "*a = " << *a << endl
|
||||
<< "a + 5 = " << a + 5 << endl
|
||||
<< "5 + a = " << 5 + a << endl
|
||||
<< "a * 5 = " << a * 5 << endl
|
||||
<< "5 * a = " << 5 * a << endl
|
||||
<< "Exp(a) = " << exp(a) << endl
|
||||
<< "Sin(a) = " << sin(a) << endl
|
||||
<< "Cos(a) = " << cos(a) << endl
|
||||
<< "Exp((a + b) / a) * Cos(a - b) = " << exp((a + b) / a) * cos(a - b) << endl;
|
||||
|
||||
a += b;
|
||||
cout << "a += b; a = " << a << endl;
|
||||
|
||||
// Оператор = мы не перегружали, но это всё равно работает
|
||||
b = a;
|
||||
cout << "b = a; b = " << b << endl;
|
||||
}
|
64
term1/seminar01_overload/08_complex/julia.cpp
Normal file
64
term1/seminar01_overload/08_complex/julia.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include "complex.h"
|
||||
using namespace std;
|
||||
|
||||
struct Color {
|
||||
unsigned char r, g, b;
|
||||
};
|
||||
|
||||
Complex func(Complex z, Complex c) {
|
||||
return z * z + c;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
Complex c = {0, 0};
|
||||
int n = 20;
|
||||
int width = 800, height = 800;
|
||||
float x0 = -2.0f, x1 = 2.0f;
|
||||
float y0 = -2.0f, y1 = 2.0f;
|
||||
|
||||
if (argc < 4) {
|
||||
cout << "usage: julia [re] [im] [n]" << endl
|
||||
<< "using default values: 0 + 0i, n = 20 "<< endl;
|
||||
}
|
||||
else {
|
||||
cout << argv[1] << " + " << argv[2] << "i" << endl << "n = " << n << endl;
|
||||
sscanf(argv[1], "%f", &c.re);
|
||||
sscanf(argv[2], "%f", &c.im);
|
||||
sscanf(argv[3], "%d", &n);
|
||||
}
|
||||
|
||||
Color* data = (Color*)malloc(sizeof(Color) * width * height);
|
||||
|
||||
for (int j = 0; j < height; j++) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
Complex z = {x0 + (x1-x0) / width * i, y0 + (y1-y0) / width * j};
|
||||
for (int k = 0; k < n; ++k) {
|
||||
z = func(z, c);
|
||||
}
|
||||
|
||||
float r = abs(z.re);
|
||||
float b = abs(z.im);
|
||||
if (r > 255) {
|
||||
r = 255;
|
||||
}
|
||||
if (b > 255) {
|
||||
b = 255;
|
||||
}
|
||||
|
||||
data[i + width * j].r = 255 - r;
|
||||
data[i + width * j].g = 0;
|
||||
data[i + width * j].b = 255 - b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FILE* file = fopen("julia.ppm", "wb");
|
||||
fprintf(file, "P6\n%d %d\n255\n", width, height);
|
||||
fwrite(data, sizeof(Color), height * width, file);
|
||||
fclose(file);
|
||||
|
||||
free(data);
|
||||
}
|
BIN
term1/seminar01_overload/08_complex/julia_images/-0.4+0.6i.ppm
Normal file
BIN
term1/seminar01_overload/08_complex/julia_images/-0.4+0.6i.ppm
Normal file
Binary file not shown.
BIN
term1/seminar01_overload/08_complex/julia_images/-0.7-0.38i.ppm
Normal file
BIN
term1/seminar01_overload/08_complex/julia_images/-0.7-0.38i.ppm
Normal file
Binary file not shown.
BIN
term1/seminar01_overload/08_complex/julia_images/-0.8+0.16i.ppm
Normal file
BIN
term1/seminar01_overload/08_complex/julia_images/-0.8+0.16i.ppm
Normal file
Binary file not shown.
BIN
term1/seminar01_overload/08_complex/julia_images/0.28+0.011i.ppm
Normal file
BIN
term1/seminar01_overload/08_complex/julia_images/0.28+0.011i.ppm
Normal file
Binary file not shown.
60
term1/seminar01_overload/08_complex/julia_movie.cpp
Normal file
60
term1/seminar01_overload/08_complex/julia_movie.cpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include "complex.h"
|
||||
using namespace std;
|
||||
|
||||
struct Color {
|
||||
unsigned char r, g, b;
|
||||
};
|
||||
|
||||
Complex func(Complex z, Complex c) {
|
||||
return z * z + c;
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
int width = 800, height = 800;
|
||||
float x0 = -2.0f, x1 = 2.0f;
|
||||
float y0 = -2.0f, y1 = 2.0f;
|
||||
int n = 20;
|
||||
|
||||
Color* data = (Color*)malloc(sizeof(Color) * width * height);
|
||||
|
||||
int max_time_steps = 500;
|
||||
for (int time = 0; time < max_time_steps; time++)
|
||||
{
|
||||
Complex c = {-1.5 + (1.5 / max_time_steps) * time, -1.5 + (1.5 / max_time_steps) * time + 1};
|
||||
for (int j = 0; j < height; j++)
|
||||
{
|
||||
for (int i = 0; i < width; i++)
|
||||
{
|
||||
Complex z = {x0 + (x1-x0) / width * i, y0 + (y1-y0) / width * j};
|
||||
for (int k = 0; k < n; ++k) {
|
||||
z = func(z, c);
|
||||
}
|
||||
|
||||
float r = abs(z.re);
|
||||
float b = abs(z.im);
|
||||
if (r > 255) {
|
||||
r = 255;
|
||||
}
|
||||
if (b > 255) {
|
||||
b = 255;
|
||||
}
|
||||
data[i + width * j].r = 255 - r;
|
||||
data[i + width * j].g = 0;
|
||||
data[i + width * j].b = 255 - b;
|
||||
}
|
||||
}
|
||||
|
||||
char filename[100];
|
||||
sprintf(filename, "animation/complex_%03d.ppm", time);
|
||||
|
||||
FILE* file = fopen(filename, "wb");
|
||||
fprintf(file, "P6\n%d %d\n255\n", width, height);
|
||||
fwrite(data, sizeof(Color), height * width, file);
|
||||
fclose(file);
|
||||
}
|
||||
free(data);
|
||||
}
|
54
term1/seminar01_overload/08_complex/mandelbrot.cpp
Normal file
54
term1/seminar01_overload/08_complex/mandelbrot.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include "complex.h"
|
||||
using namespace std;
|
||||
|
||||
struct Color {
|
||||
unsigned char r, g, b;
|
||||
};
|
||||
|
||||
Complex func(Complex z, Complex c) {
|
||||
return z * z + c;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int n = 20;
|
||||
Complex z = {0, 0};
|
||||
int width = 800, height = 800;
|
||||
float x0 = -2.0f, x1 = 2.0f;
|
||||
float y0 = -2.0f, y1 = 2.0f;
|
||||
|
||||
|
||||
Color* data = (Color*)malloc(sizeof(Color) * width * height);
|
||||
|
||||
for (int j = 0; j < height; j++) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
z = {0, 0};
|
||||
Complex c = {x0 + (x1-x0) / width * i, y0 + (y1-y0) / width * j};
|
||||
for (int k = 0; k < n; ++k) {
|
||||
z = func(z, c);
|
||||
}
|
||||
|
||||
float r = abs(z.re);
|
||||
float b = abs(z.im);
|
||||
if (r > 255) {
|
||||
r = 255;
|
||||
}
|
||||
if (b > 255) {
|
||||
b = 255;
|
||||
}
|
||||
data[i + width * j].r = 255 - r;
|
||||
data[i + width * j].g = 0;
|
||||
data[i + width * j].b = 255 - b;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FILE* file = fopen("mandelbrot.ppm", "wb");
|
||||
fprintf(file, "P6\n%d %d\n255\n", width, height);
|
||||
fwrite(data, sizeof(Color), height * width, file);
|
||||
fclose(file);
|
||||
|
||||
free(data);
|
||||
}
|
Binary file not shown.
BIN
term1/seminar01_overload/homework_overload.pdf
Normal file
BIN
term1/seminar01_overload/homework_overload.pdf
Normal file
Binary file not shown.
39
term1/seminar02_encapsulation/0circle/circle.cpp
Normal file
39
term1/seminar02_encapsulation/0circle/circle.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <cstdlib>
|
||||
#include "circle.h"
|
||||
#include "point.h"
|
||||
|
||||
Circle::Circle(const Point& acenter, float aradius) {
|
||||
mCenter = acenter;
|
||||
mRadius = aradius;
|
||||
}
|
||||
Circle::Circle() {
|
||||
mCenter = Point {0, 0};
|
||||
mRadius = 1;
|
||||
}
|
||||
Circle::Circle(const Circle& circle) {
|
||||
mCenter = circle.mCenter;
|
||||
mRadius = circle.mRadius;
|
||||
}
|
||||
Point Circle::getCenter() const { return mCenter; }
|
||||
float Circle::getRadius() const { return mRadius; }
|
||||
|
||||
void Circle::setCenter(const Point& p) {
|
||||
mCenter = p;
|
||||
}
|
||||
void Circle::setRadius(float radius) {
|
||||
mRadius = radius > 0 ? radius : 0;
|
||||
}
|
||||
float Circle::getArea() const {
|
||||
return abs(mRadius * mRadius * M_PI);
|
||||
}
|
||||
float Circle::getDistance(const Point& p) {
|
||||
return mCenter.distance(p) - mRadius;
|
||||
}
|
||||
bool Circle::isColliding(const Circle& c) const {
|
||||
return (mCenter.distance(c.getCenter()) - (mRadius + c.getRadius()) > 0) ? false : true;
|
||||
}
|
||||
void Circle::move(const Point& p) {
|
||||
mCenter = mCenter + p;
|
||||
}
|
23
term1/seminar02_encapsulation/0circle/circle.h
Normal file
23
term1/seminar02_encapsulation/0circle/circle.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include "point.h"
|
||||
class Circle
|
||||
{
|
||||
private:
|
||||
Point mCenter;
|
||||
float mRadius;
|
||||
|
||||
public:
|
||||
Circle(const Point& acenter, float aradius);
|
||||
Circle();
|
||||
Circle(const Circle& circle);
|
||||
Point getCenter() const;
|
||||
float getRadius() const;
|
||||
|
||||
void setCenter(const Point& p);
|
||||
void setRadius(float radius);
|
||||
float getArea() const;
|
||||
float getDistance(const Point& p);
|
||||
bool isColliding(const Circle& c) const;
|
||||
void move(const Point& p);
|
||||
};
|
||||
|
||||
|
44
term1/seminar02_encapsulation/0circle/main.cpp
Normal file
44
term1/seminar02_encapsulation/0circle/main.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include <iostream>
|
||||
#include "point.h"
|
||||
#include "circle.h"
|
||||
|
||||
using std::cout, std::endl;
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
Point p = {7, -1};
|
||||
Point q = {-4, 2};
|
||||
cout << "Point p = " << p << endl;
|
||||
cout << "Point q = " << q << endl;
|
||||
cout << "p + q = " << p + q << endl;
|
||||
|
||||
|
||||
Circle a {{4, 1}, 3};
|
||||
Circle b;
|
||||
// b = a;
|
||||
|
||||
cout << "Circle a: center: " << a.getCenter() << " radius: " << a.getRadius() << endl;
|
||||
cout << "Circle b: center: " << b.getCenter() << " radius: " << b.getRadius() << endl;
|
||||
|
||||
cout << "Area of a = " << a.getArea() << endl;
|
||||
cout << "Distance from point p to circle a = " << a.getDistance(p) << endl;
|
||||
|
||||
|
||||
|
||||
cout << "Collisions:" << endl;
|
||||
if (a.isColliding(b))
|
||||
cout << "Yes, a is colliding b" << endl;
|
||||
else
|
||||
cout << "No, a isn't colliding b" << endl;
|
||||
|
||||
|
||||
|
||||
cout << "Moving b by {1, 1}:" << endl;
|
||||
b.move({1, 1});
|
||||
if (a.isColliding(b))
|
||||
cout << "Yes, a is colliding b" << endl;
|
||||
else
|
||||
cout << "No, a isn't colliding b" << endl;
|
||||
|
||||
}
|
82
term1/seminar02_encapsulation/0circle/point.cpp
Normal file
82
term1/seminar02_encapsulation/0circle/point.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
#include "point.h"
|
||||
|
||||
|
||||
Point::Point(float x, float y)
|
||||
{
|
||||
mx = x;
|
||||
my = y;
|
||||
}
|
||||
|
||||
Point::Point()
|
||||
{
|
||||
mx = 0;
|
||||
my = 0;
|
||||
}
|
||||
|
||||
|
||||
float Point::getX() const
|
||||
{
|
||||
return mx;
|
||||
}
|
||||
|
||||
float Point::getY() const
|
||||
{
|
||||
return my;
|
||||
}
|
||||
|
||||
void Point::setX(float x)
|
||||
{
|
||||
mx = x;
|
||||
}
|
||||
|
||||
void Point::setY(float y)
|
||||
{
|
||||
my = y;
|
||||
}
|
||||
|
||||
float Point::norm() const
|
||||
{
|
||||
return std::sqrt(mx * mx + my * my);
|
||||
}
|
||||
|
||||
void Point::normalize()
|
||||
{
|
||||
float pnorm = norm();
|
||||
mx /= pnorm;
|
||||
my /= pnorm;
|
||||
}
|
||||
|
||||
float Point::distance(const Point& p) const
|
||||
{
|
||||
return std::sqrt((p.mx - mx) * (p.mx - mx) + (p.my - my) * (p.my - my));
|
||||
}
|
||||
|
||||
Point Point::operator+(const Point& right) const
|
||||
{
|
||||
Point result = {mx + right.mx, my + right.my};
|
||||
return result;
|
||||
}
|
||||
|
||||
Point Point::operator*(float a) const
|
||||
{
|
||||
Point result = {a * mx, a * my};
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Point operator*(float a, const Point& p)
|
||||
{
|
||||
Point result = {a * p.mx, a * p.my};
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& left, const Point& right)
|
||||
{
|
||||
left << "(" << right.mx << ", " << right.my << ")";
|
||||
return left;
|
||||
}
|
37
term1/seminar02_encapsulation/0circle/point.h
Normal file
37
term1/seminar02_encapsulation/0circle/point.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
Поля x и y сделаны приватными
|
||||
Конкретно для этого класса их можно было сделать публичными
|
||||
Так как пользователь всё-равно будет иметь доступ без ограничений к этим полям через геттеры и сеттеры
|
||||
Но они сделаны приватными для образовательных целей
|
||||
*/
|
||||
|
||||
class Point
|
||||
{
|
||||
private:
|
||||
float mx, my;
|
||||
|
||||
public:
|
||||
|
||||
Point(float x, float y);
|
||||
Point();
|
||||
|
||||
float getX() const;
|
||||
float getY() const;
|
||||
void setX(float x);
|
||||
void setY(float y);
|
||||
|
||||
void normalize();
|
||||
float distance(const Point& p) const;
|
||||
float norm() const;
|
||||
Point operator+(const Point& right) const;
|
||||
Point operator*(float a) const;
|
||||
|
||||
|
||||
|
||||
friend Point operator*(float a, const Point& p);
|
||||
friend std::ostream& operator<<(std::ostream& left, const Point& right);
|
||||
};
|
||||
|
||||
|
75
term1/seminar02_encapsulation/1number/main.cpp
Normal file
75
term1/seminar02_encapsulation/1number/main.cpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include "number.h"
|
||||
|
||||
Number fib(int n)
|
||||
{
|
||||
Number a = 0; // F0
|
||||
Number b = 1; // F1
|
||||
for (int i = 1; i <= n; ++i) {
|
||||
if (i % 2) {
|
||||
a += b;
|
||||
} else {
|
||||
b += a;
|
||||
}
|
||||
}
|
||||
if (n % 2) {
|
||||
return b;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
Number factorial(int n)
|
||||
{
|
||||
Number result {
|
||||
1};
|
||||
for (int i = 2; i < n + 1; ++i) {
|
||||
result = Number(i) * result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void grad(Number n)
|
||||
{
|
||||
|
||||
std::cout << "n = " << n;
|
||||
Number max = n;
|
||||
unsigned long long int steps = 0;
|
||||
while (n != Number(1)) {
|
||||
if (n > max) {
|
||||
#ifdef _DEBUG_COMP
|
||||
std::cout << n << " is greater than " << max << std::endl;
|
||||
#endif
|
||||
max = n;
|
||||
}
|
||||
if (n.isEven()) {
|
||||
n.div2();
|
||||
} else {
|
||||
n = Number(3) * n + Number(1);
|
||||
}
|
||||
#ifdef _DEBUG_GRAD
|
||||
if (steps > 100) {
|
||||
std::cout << "break" << std::endl;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
++steps;
|
||||
}
|
||||
std::cout << " steps = " << steps << " max = " << max << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "===FIB===" << std::endl;
|
||||
std::cout << "F(1000) = " << fib(1000) << std::endl;
|
||||
std::cout << "===FAC===" << std::endl;
|
||||
std::cout << "1000! = " << factorial(1000) << std::endl;
|
||||
std::cout << "===GRAD===" << std::endl;
|
||||
grad(Number("7"));
|
||||
grad(Number("256"));
|
||||
grad(Number("1117065"));
|
||||
grad(Number("4761963248413673697"));
|
||||
grad(Number("90560792656972947582439785608972465789628974587264056284658721771"));
|
||||
}
|
343
term1/seminar02_encapsulation/1number/number.cpp
Normal file
343
term1/seminar02_encapsulation/1number/number.cpp
Normal file
|
@ -0,0 +1,343 @@
|
|||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <cstring>
|
||||
#include "number.h"
|
||||
|
||||
Number::Number(int a)
|
||||
{
|
||||
#ifdef _DEBUG_CONSTRUCTOR
|
||||
std::cout << "(Number constructor " << a << " -> ";
|
||||
#endif
|
||||
// Находим размер необходимой памяти под это число
|
||||
int temp = a;
|
||||
capacity = 0;
|
||||
while (temp != 0) {
|
||||
temp /= base;
|
||||
capacity += 1;
|
||||
}
|
||||
|
||||
// Отдельно обрабатываем случай, когда число равно 0
|
||||
if (capacity == 0)
|
||||
capacity = 1;
|
||||
|
||||
// Выделяем память и записывем число a в массив data
|
||||
// Например, число 12345678 представится в виде массива [78, 56, 34, 12]
|
||||
|
||||
data = new char[capacity];
|
||||
|
||||
for (int i = 0; i < capacity; ++i) {
|
||||
data[i] = a % base;
|
||||
a /= base;
|
||||
}
|
||||
|
||||
// В данном случае размер будет равен вместимости
|
||||
size = capacity;
|
||||
#ifdef _DEBUG_CONSTRUCTOR
|
||||
std::cout << *this << ")" << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Конструктор по умолчанию
|
||||
Number::Number():Number(0){}
|
||||
|
||||
// Конструктор копирования
|
||||
Number::Number(const Number & n)
|
||||
{
|
||||
size = n.size;
|
||||
capacity = n.capacity;
|
||||
data = new char[capacity];
|
||||
for (int i = 0; i < size; i++) {
|
||||
data[i] = n.data[i];
|
||||
}
|
||||
}
|
||||
|
||||
Number::Number(const char *str)
|
||||
{
|
||||
int len = std::strlen(str);
|
||||
size = (len + len % 2) / 2;
|
||||
capacity = size;
|
||||
data = new char[capacity];
|
||||
char buf[2];
|
||||
for (int i = 0; i < size; i++) {
|
||||
buf[1] = str[len - 2 * i - 1];
|
||||
if (len - 2 * i - 1 > 0) {
|
||||
buf[0] = str[len - 2 * i - 2];
|
||||
} else {
|
||||
buf[0] = '0';
|
||||
}
|
||||
data[i] = std::stoi(buf);
|
||||
}
|
||||
}
|
||||
|
||||
Number::~Number()
|
||||
{
|
||||
delete[]data;
|
||||
}
|
||||
|
||||
Number & Number::operator=(const Number & right)
|
||||
{
|
||||
capacity = right.capacity;
|
||||
size = right.size;
|
||||
data = new char[capacity];
|
||||
for (int i = 0; i < size; i++) {
|
||||
data[i] = right.data[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Number Number::operator+(Number a)
|
||||
{
|
||||
#ifdef _DEBUG_ADD
|
||||
std::cout << "arg1=" << a << "capacity=" << a.
|
||||
capacity << ",size=" << a.size << std::endl;
|
||||
std::cout << "arg2=" << *this << "capacity=" << this->
|
||||
capacity << ",size=" << this->size << std::endl;
|
||||
|
||||
#endif
|
||||
Number result;
|
||||
Number temp;
|
||||
int i;
|
||||
int carry = 0;
|
||||
if (size < a.size) {
|
||||
temp = *this;
|
||||
*this = a;
|
||||
a = temp;
|
||||
}
|
||||
result.capacity = size + 1;
|
||||
//result.data = new char[capacity];
|
||||
result.data = (char *) calloc(result.capacity, sizeof(char));
|
||||
for (i = 0; i < a.size; ++i) {
|
||||
result.data[i] = (data[i] + a.data[i] + carry) % base;
|
||||
carry = (data[i] + a.data[i] + carry) / base;
|
||||
}
|
||||
for (; i < size; ++i) {
|
||||
result.data[i] = (data[i] + carry) % base;
|
||||
carry = (data[i] + carry) / base;
|
||||
}
|
||||
if (carry) {
|
||||
#ifdef _DEBUG_ADD
|
||||
std::cout << "applied carry" << std::endl;
|
||||
#endif
|
||||
result.data[i] = carry;
|
||||
result.size = size + 1;
|
||||
} else {
|
||||
result.size = size;
|
||||
}
|
||||
#ifdef _DEBUG_ADD
|
||||
std::cout << result << " capacity=" << result.
|
||||
capacity << ",size=" << result.size << std::endl;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
void Number::operator+=(const Number & a)
|
||||
{
|
||||
*this = *this + a;
|
||||
}
|
||||
|
||||
bool Number::isEven() const
|
||||
{
|
||||
if (data[0] % 2) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Number Number::operator*(const Number & right) const
|
||||
{
|
||||
#ifdef _DEBUG_MUL
|
||||
std::
|
||||
cout << "arg1=" << *this << "(capacity=" << capacity << ",size=" <<
|
||||
size << ")" << " " << "arg2=" << right << "(capacity=" << right.
|
||||
capacity << ",size=" << right.size << ")" << std::endl;
|
||||
#endif
|
||||
if (*this == Number("0") || right == Number("0"))
|
||||
return Number("0");
|
||||
int i, j;
|
||||
int temp;
|
||||
Number result;
|
||||
|
||||
result.capacity = capacity + right.capacity;
|
||||
int *carry = (int *) std::calloc(result.capacity, sizeof(int));
|
||||
|
||||
result.data = (char *) calloc(result.capacity, sizeof(char));
|
||||
#ifdef _DEBUG_MUL
|
||||
std::cout << "carry:[" << carry[0];
|
||||
for (int k = 1; k < result.capacity; ++k) {
|
||||
std::cout << "," << carry[k];
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
#endif
|
||||
for (i = 0; i < size; ++i) {
|
||||
for (j = 0; j < right.size; ++j) {
|
||||
#ifdef _DEBUG_MUL
|
||||
std::cout << i + j << ":" << static_cast <
|
||||
int >(result.data[i + j]) << " + " << static_cast <
|
||||
int >(data[i]) << " * " << static_cast <
|
||||
int >(right.data[j]) << " + " << carry[i + j] << std::endl;
|
||||
#endif
|
||||
temp =
|
||||
(result.data[i + j] + data[i] * right.data[j] +
|
||||
carry[i + j]);
|
||||
result.data[i + j] = temp % base;
|
||||
carry[i + j + 1] += temp / base;
|
||||
carry[i + j] = 0;
|
||||
|
||||
}
|
||||
}
|
||||
#ifdef _DEBUG_MUL
|
||||
std::cout << "result before applying carry:" << result << std::endl;
|
||||
std::cout << "carry:[" << carry[0];
|
||||
for (int k = 1; k < result.capacity; ++k) {
|
||||
std::cout << "," << carry[k];
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
#endif
|
||||
if (carry[i + j - 1]) {
|
||||
result.data[i + j - 1] = carry[i + j - 1];
|
||||
result.size = i + j;
|
||||
} else {
|
||||
result.size = i + j - 1;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG_MUL
|
||||
std::cout << "before correcting capacity, result=" << result << std::
|
||||
endl;
|
||||
#endif
|
||||
// correcting capacity
|
||||
/*char* temp_data = (char *)calloc(result.size, sizeof(char));
|
||||
for (i = 0; i < result.size; ++i) {
|
||||
temp_data[i] = result.data[i];
|
||||
}
|
||||
|
||||
free(result.data);
|
||||
result.capacity = result.size;
|
||||
result.data = (char*)calloc(result.size,sizeof(char));
|
||||
for (i = 0; i < result.size; ++i) {
|
||||
result.data[i] = temp_data[i];
|
||||
}
|
||||
|
||||
free(temp_data); */
|
||||
free(carry);
|
||||
#ifdef _DEBUG_MUL
|
||||
std::cout << "return value=" << result << "(capacity=" << result.
|
||||
capacity << ",size=" << result.
|
||||
size << ")" << std::endl << "======" << std::endl;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
void Number::operator*=(const Number & a)
|
||||
{
|
||||
*this = *this * a;
|
||||
}
|
||||
|
||||
bool Number::operator==(const Number & a) const
|
||||
{
|
||||
if (size != a.size) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (data[i] != a.data[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Number::operator!=(const Number & a) const
|
||||
{
|
||||
return not(*this == a);
|
||||
}
|
||||
|
||||
bool Number::operator>(const Number & a) const
|
||||
{
|
||||
#ifdef _DEBUG_COMP
|
||||
std::
|
||||
cout << "comp " << *this << "(size=" << size << ") and " << a <<
|
||||
"(size=" << a.size << ")" << std::endl;
|
||||
#endif
|
||||
if (size > a.size) {
|
||||
#ifdef _DEBUG_COMP
|
||||
std::cout << "size > a.size => true" << std::endl;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
if (size < a.size) {
|
||||
#ifdef _DEBUG_COMP
|
||||
std::cout << "size < a.size => false" << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
for (int i = size - 1; i >= 0; --i) {
|
||||
if (data[i] > a.data[i]) {
|
||||
return true;
|
||||
#ifdef _DEBUG_COMP
|
||||
std::cout << static_cast <
|
||||
int >(data[i]) << ">" << static_cast <
|
||||
int >(a.data[i]) << std::endl;
|
||||
#endif
|
||||
}
|
||||
if (data[i] < a.data[i]) {
|
||||
#ifdef _DEBUG_COMP
|
||||
std::cout << static_cast <
|
||||
int >(data[i]) << "<" << static_cast <
|
||||
int >(a.data[i]) << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
#ifdef _DEBUG_COMP
|
||||
std::cout << "using final false" << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Number::operator<(const Number & a) const
|
||||
{
|
||||
return not(*this > a) and(*this != a);
|
||||
}
|
||||
|
||||
void Number::div2()
|
||||
{
|
||||
#ifdef _DEBUG_DIV2
|
||||
std::cout << "n = " << *this << std::endl;
|
||||
#endif
|
||||
int carry = 0;
|
||||
int temp;
|
||||
for (int i = size - 1; i >= 0; --i) {
|
||||
temp = data[i] + carry * base;
|
||||
data[i] = temp / 2;
|
||||
carry = temp % 2;
|
||||
}
|
||||
if (data[size - 1] == 0) {
|
||||
--size;
|
||||
}
|
||||
#ifdef _DEBUG_DIV2
|
||||
std::cout << "unstripped result " << *this << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
std::ostream & operator<<(std::ostream & stream, const Number & right)
|
||||
{
|
||||
#ifdef _DEBUG_COUT
|
||||
stream << "[";
|
||||
for (std::size_t i = 0; i < right.size; ++i) {
|
||||
stream << static_cast <
|
||||
int >(right.data[right.size - 2 - i]) << ",";
|
||||
}
|
||||
stream << "]";
|
||||
#else
|
||||
// Печатаем самый большой разряд
|
||||
stream << (int) right.data[right.size - 1];
|
||||
|
||||
// Печатаем остальные разряды с заполнением нулями до 2-х цифр
|
||||
// setfill и setw это то же самое, что и в языке C спецификатор %02d
|
||||
for (std::size_t i = 0; i < right.size - 1; ++i)
|
||||
stream << std::setfill('0') << std::setw(2) << (int) right.
|
||||
data[right.size - 2 - i];
|
||||
#endif
|
||||
return stream;
|
||||
}
|
63
term1/seminar02_encapsulation/1number/number.h
Normal file
63
term1/seminar02_encapsulation/1number/number.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
#pragma once
|
||||
/*
|
||||
Класс Number -- класс положительных больших чисел
|
||||
|
||||
Большое число будет храниться в динамическом массиве data
|
||||
Каждый элемент этого массива содержит разряд числа в 100-ричной системе счисления
|
||||
(так как base = 100)
|
||||
По сути, каждый элемент data хранит две цифры числа в десятичной записи
|
||||
|
||||
Значение 100 для системы счисления выбрано как компромис между
|
||||
эффективностью и удобством написания программы.
|
||||
Если выбрать значения базы 10 - то программа будет не так эффективна по памяти
|
||||
Если выбрать значения базы 256 (максимально эффективное использование памяти для типа char),
|
||||
то алгоритм печати на экран сильно усложнится
|
||||
В качестве альтернативы, можно было выбрать базу 1e9,
|
||||
изменив при этом тип элементов c char на int
|
||||
|
||||
capacity - размер массива data
|
||||
size - сколько ячеек занимет число в массиве data
|
||||
size <= capacity
|
||||
|
||||
Для удобства разряды числа хранятся в обратном порядке
|
||||
Например, число 12345678 соответствует массиву
|
||||
data = {78, 56, 34, 12}
|
||||
(это упрощает многие алгоритмы с такими числами)
|
||||
*/
|
||||
|
||||
class Number {
|
||||
private:
|
||||
static const int base = 100;
|
||||
std::size_t size;
|
||||
std::size_t capacity;
|
||||
char *data;
|
||||
|
||||
public:
|
||||
|
||||
Number(int a);
|
||||
Number();
|
||||
// Конструктор копирования
|
||||
Number(const Number & n);
|
||||
Number(const char *str);
|
||||
~Number();
|
||||
Number & operator=(const Number & right);
|
||||
|
||||
Number operator+(Number a);
|
||||
void operator+=(const Number & a);
|
||||
|
||||
bool isEven() const;
|
||||
|
||||
Number operator*(const Number & right) const;
|
||||
void operator*=(const Number & a);
|
||||
|
||||
bool operator==(const Number & a) const;
|
||||
bool operator!=(const Number & a) const;
|
||||
bool operator>(const Number & a) const;
|
||||
bool operator<(const Number & a) const;
|
||||
void div2();
|
||||
|
||||
friend std::ostream & operator<<(std::ostream & stream,
|
||||
const Number & right);
|
||||
};
|
||||
|
||||
std::ostream & operator<<(std::ostream & stream, const Number & right);
|
BIN
term1/seminar02_encapsulation/homework_encapsulation.pdf
Normal file
BIN
term1/seminar02_encapsulation/homework_encapsulation.pdf
Normal file
Binary file not shown.
|
@ -0,0 +1,22 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
|
||||
using namespace std;
|
||||
|
||||
string letter_case_switch(const string & str)
|
||||
{
|
||||
string result = str;
|
||||
if (str.size() == 0)
|
||||
return result;
|
||||
result[0] =
|
||||
isupper(result[0]) ? tolower(result[0]) : toupper(result[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
string meow;
|
||||
cin >> meow;
|
||||
cout << letter_case_switch(meow) << endl;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
|
||||
using namespace std;
|
||||
|
||||
string letter_case_switch(const string& str) {
|
||||
string result = str;
|
||||
if (str.size() == 0)
|
||||
return result;
|
||||
result[0] = isupper(result[0]) ? tolower(result[0]) : toupper(result[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
int main() {
|
||||
string meow;
|
||||
cin >> meow;
|
||||
cout << letter_case_switch(meow) << endl;
|
||||
}
|
BIN
term1/seminar03_initialization/02_repeat/a.out~
Normal file
BIN
term1/seminar03_initialization/02_repeat/a.out~
Normal file
Binary file not shown.
48
term1/seminar03_initialization/02_repeat/main.cpp
Normal file
48
term1/seminar03_initialization/02_repeat/main.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
using namespace std;
|
||||
|
||||
string repeat1(string_view s)
|
||||
{
|
||||
return string {
|
||||
s}
|
||||
+string {
|
||||
s};
|
||||
}
|
||||
|
||||
void repeat2(string & s)
|
||||
{
|
||||
s += s;
|
||||
}
|
||||
|
||||
void repeat3(string * s)
|
||||
{
|
||||
*s += *s;
|
||||
}
|
||||
|
||||
string *repeat4(string_view s)
|
||||
{
|
||||
string *result = new string;
|
||||
*result = string {
|
||||
s} +string {
|
||||
s};
|
||||
return result;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
string meow;
|
||||
cin >> meow;
|
||||
|
||||
cout << "test of repeat1:" << endl << repeat1(meow) << endl;
|
||||
|
||||
repeat2(meow);
|
||||
cout << "test of repeat2:" << endl << meow << endl;
|
||||
|
||||
repeat3(&meow);
|
||||
cout << "test of repeat3:" << endl << meow << endl;
|
||||
|
||||
cout << "test of repeat4:" << endl << *repeat4(meow) << endl;
|
||||
}
|
38
term1/seminar03_initialization/02_repeat/main.cpp~
Normal file
38
term1/seminar03_initialization/02_repeat/main.cpp~
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
using namespace std;
|
||||
|
||||
string repeat1(string_view s) {
|
||||
return string{s} + string{s};
|
||||
}
|
||||
|
||||
void repeat2(string& s) {
|
||||
s += s;
|
||||
}
|
||||
|
||||
void repeat3(string* s) {
|
||||
*s += *s;
|
||||
}
|
||||
|
||||
string* repeat4(string_view s) {
|
||||
string* result = new string;
|
||||
*result = string{s} + string{s};
|
||||
return result;
|
||||
}
|
||||
|
||||
int main() {
|
||||
string meow;
|
||||
cin >> meow;
|
||||
|
||||
cout << "test of repeat1:" << endl << repeat1(meow) << endl;
|
||||
|
||||
repeat2(meow);
|
||||
cout << "test of repeat2:" << endl << meow << endl;
|
||||
|
||||
repeat3(&meow);
|
||||
cout << "test of repeat3:" << endl << meow << endl;
|
||||
|
||||
cout << "test of repeat4:" << endl << *repeat4(meow) << endl;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
string operator*(const string str, int n) {
|
||||
string result;
|
||||
for (int i = 0; i < n; ++i)
|
||||
result += str;
|
||||
return result;
|
||||
}
|
||||
|
||||
string operator*(int n, const string str) {
|
||||
string result;
|
||||
for (int i = 0; i < n; ++i)
|
||||
result += str;
|
||||
return result;
|
||||
}
|
||||
|
||||
int main() {
|
||||
string meow;
|
||||
cin >> meow;
|
||||
cout << 3 * meow << endl;
|
||||
}
|
22
term1/seminar03_initialization/04_truncate_to_dot/main.cpp
Normal file
22
term1/seminar03_initialization/04_truncate_to_dot/main.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void truncateToDot(string& s) {
|
||||
s.resize(s.find('.'));
|
||||
s.shrink_to_fit();
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::string a = "cat.dog.mouse.elephant.tiger.lion";
|
||||
std::string b = "wikipedia.org";
|
||||
std::string c = ".com";
|
||||
truncateToDot(a);
|
||||
truncateToDot(b);
|
||||
truncateToDot(c);
|
||||
|
||||
cout << a << endl
|
||||
<< b << endl
|
||||
<< c << endl;
|
||||
}
|
35
term1/seminar03_initialization/05_string_sum/main.cpp
Normal file
35
term1/seminar03_initialization/05_string_sum/main.cpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
#include <iostream>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int string_sum(const string& str) {
|
||||
int res = 0;
|
||||
int x;
|
||||
int n = str.size();
|
||||
int i = 0;
|
||||
while (i < n) {
|
||||
switch (str[i]) {
|
||||
case '[':
|
||||
case ',' :
|
||||
sscanf((str.c_str()) + i + 1, "%d", &x);
|
||||
res += x;
|
||||
break;
|
||||
case ']' :
|
||||
return res;
|
||||
case ' ':
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main() {
|
||||
string meow;
|
||||
getline(cin, meow);
|
||||
cout << string_sum(meow) << endl;
|
||||
}
|
34
term1/seminar03_initialization/06_new/main.cpp
Normal file
34
term1/seminar03_initialization/06_new/main.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
int *x = new int{123};
|
||||
cout << *x << endl;
|
||||
|
||||
string *str = new string{"Cats and Dogs"};
|
||||
cout << *str << endl;
|
||||
|
||||
int *xs = new int[]{10, 20, 30, 40, 50};
|
||||
for (int i = 0; i < 5; ++i)
|
||||
cout << xs[i] << " ";
|
||||
cout << endl;
|
||||
|
||||
string *strs = new string[]{"Cat", "Dog", "Mouse"};
|
||||
for (int i = 0; i < 3; ++i)
|
||||
cout << strs[i] << " ";
|
||||
cout << endl;
|
||||
|
||||
string_view *str_views = new string_view[]{strs[0], strs[1], strs[2]};
|
||||
for (int i = 0; i < 3; ++i)
|
||||
cout << str_views[i] << " ";
|
||||
cout << endl;
|
||||
|
||||
delete x;
|
||||
delete str;
|
||||
delete[] xs;
|
||||
delete[] strs;
|
||||
delete[] str_views;
|
||||
}
|
22
term1/seminar03_initialization/07_placement/main.cpp
Normal file
22
term1/seminar03_initialization/07_placement/main.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include <iostream>
|
||||
#include "miptstring.cpp"
|
||||
|
||||
using std::cout, std::endl;
|
||||
|
||||
int main() {
|
||||
mipt::String stack{"Cat"};
|
||||
cout << stack << endl;
|
||||
|
||||
mipt::String* heap = new mipt::String{"Dog"};
|
||||
cout << *heap << endl;
|
||||
|
||||
char *x = (char*)malloc(sizeof(mipt::String));
|
||||
mipt::String* px = new(x) mipt::String{"Elephant"};
|
||||
|
||||
cout << *px << endl;
|
||||
|
||||
px->~String();
|
||||
free(px);
|
||||
delete heap;
|
||||
|
||||
}
|
215
term1/seminar03_initialization/07_placement/miptstring.cpp
Normal file
215
term1/seminar03_initialization/07_placement/miptstring.cpp
Normal file
|
@ -0,0 +1,215 @@
|
|||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
|
||||
namespace mipt{
|
||||
|
||||
class String
|
||||
{
|
||||
private:
|
||||
|
||||
std::size_t mSize {0};
|
||||
std::size_t mCapacity {0};
|
||||
char* mpData {nullptr};
|
||||
|
||||
public:
|
||||
|
||||
String(const char* str)
|
||||
{
|
||||
std::size_t strSize = std::strlen(str);
|
||||
resize(strSize);
|
||||
std::memcpy(mpData, str, mSize);
|
||||
|
||||
std::cout << "mipt::String Constructor (" << mpData << ")" << std::endl;
|
||||
}
|
||||
|
||||
String() : String("") {}
|
||||
String(const String& s) : String(s.cStr()) {}
|
||||
|
||||
String(std::size_t n, char a)
|
||||
{
|
||||
resize(n);
|
||||
|
||||
for (std::size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = a;
|
||||
|
||||
std::cout << "mipt::String Constructor (" << mpData << ")" << std::endl;
|
||||
}
|
||||
|
||||
~String()
|
||||
{
|
||||
std::cout << "mipt::String Destructor (" << mpData << ")" << std::endl;
|
||||
delete [] mpData;
|
||||
}
|
||||
|
||||
void reserve(std::size_t capacity)
|
||||
{
|
||||
if (capacity <= mCapacity)
|
||||
return;
|
||||
|
||||
mCapacity = std::max(2 * mCapacity, capacity);
|
||||
char* newData = new char[mCapacity]; // errorCheckedMalloc(mCapacity);
|
||||
|
||||
if (mpData)
|
||||
std::memcpy(newData, mpData, mSize + 1);
|
||||
|
||||
delete [] mpData;
|
||||
mpData = newData;
|
||||
}
|
||||
|
||||
|
||||
void resize(std::size_t size)
|
||||
{
|
||||
reserve(size + 1);
|
||||
mSize = size;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
String& operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
mSize = right.mSize;
|
||||
resize(mSize);
|
||||
|
||||
std::memcpy(mpData, right.mpData, mSize + 1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
String operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
result.resize(mSize + b.mSize);
|
||||
|
||||
std::memcpy(result.mpData, mpData, mSize);
|
||||
std::memcpy(result.mpData + mSize, b.mpData, b.mSize);
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String& operator+=(const String& right)
|
||||
{
|
||||
*this = *this + right;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const String& right) const
|
||||
{
|
||||
if (mSize != right.mSize)
|
||||
return false;
|
||||
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return i == mSize;
|
||||
}
|
||||
|
||||
bool operator<(const String& right) const
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] < right.mpData[i];
|
||||
}
|
||||
|
||||
bool operator<=(const String& right) const
|
||||
{
|
||||
std::size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] <= right.mpData[i];
|
||||
}
|
||||
|
||||
bool operator!=(const String& right) const
|
||||
{
|
||||
return !(*this == right);
|
||||
}
|
||||
|
||||
bool operator>(const String& right) const
|
||||
{
|
||||
return !(*this <= right);
|
||||
}
|
||||
|
||||
bool operator>=(const String& right) const
|
||||
{
|
||||
return !(*this < right);
|
||||
}
|
||||
|
||||
char& operator[](std::size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
const char& operator[](std::size_t i) const
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
char& at(std::size_t i)
|
||||
{
|
||||
if (i >= mSize)
|
||||
throw std::out_of_range{"mipt::String::at: index >= this->size()"};
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
const char& at(std::size_t i) const
|
||||
{
|
||||
if (i >= mSize)
|
||||
throw std::out_of_range{"mipt::String::at: index >= this->size()"};
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
delete [] mpData;
|
||||
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = new char[mCapacity];
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
void addCharacter(char c)
|
||||
{
|
||||
if (mSize + 1 == mCapacity)
|
||||
reserve(2 * mCapacity);
|
||||
|
||||
mpData[mSize] = c;
|
||||
resize(mSize + 1);
|
||||
}
|
||||
|
||||
|
||||
std::size_t getSize() const {return mSize;}
|
||||
std::size_t getCapacity() const {return mCapacity;}
|
||||
const char* cStr() const {return mpData;}
|
||||
};
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||
{
|
||||
out << s.cStr();
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream& in, String& s)
|
||||
{
|
||||
s.clear();
|
||||
while (true)
|
||||
{
|
||||
char x = in.get();
|
||||
if (std::isspace(x))
|
||||
break;
|
||||
s.addCharacter(x);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
}
|
18
term1/seminar03_initialization/08_stringview/main.cpp
Normal file
18
term1/seminar03_initialization/08_stringview/main.cpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <iostream>
|
||||
#include "miptstring.h"
|
||||
#include "miptstringview.h"
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
mipt::String a = "abcd";
|
||||
mipt::String b = "abce";
|
||||
mipt::StringView av = a;
|
||||
mipt::StringView bv = b;
|
||||
//cout << (b < a) << endl;
|
||||
//cout << (bv < av) << endl;
|
||||
cout << av.substr(1,10) << endl;
|
||||
av.remove_suffix(2);
|
||||
cout << av << endl;
|
||||
mipt::String meow = av;
|
||||
cout << "sv to string: " << meow << endl;
|
||||
}
|
218
term1/seminar03_initialization/08_stringview/miptstring.cpp
Normal file
218
term1/seminar03_initialization/08_stringview/miptstring.cpp
Normal file
|
@ -0,0 +1,218 @@
|
|||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include "miptstring.h"
|
||||
#include "miptstringview.h"
|
||||
using std::cout, std::cin, std::endl, std::size_t;
|
||||
|
||||
namespace mipt{
|
||||
|
||||
char* errorCheckedMalloc(size_t newCapacity)
|
||||
{
|
||||
char* result = static_cast<char*>(std::malloc(newCapacity * sizeof(char)));
|
||||
if (result == NULL)
|
||||
{
|
||||
cout << "Error! Out of memory" << endl;
|
||||
std::exit(1);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String::String(const char* str)
|
||||
{
|
||||
size_t strSize = std::strlen(str);
|
||||
resize(strSize);
|
||||
std::memcpy(mpData, str, mSize);
|
||||
}
|
||||
|
||||
String::String() : String("") {}
|
||||
String::String(const String& s) : String(s.cStr()) {}
|
||||
String::String(const StringView& sv) {
|
||||
mSize = sv.size();
|
||||
(*this).reserve(mSize);
|
||||
for(int i = 0; i < mSize; ++i)
|
||||
mpData[i] = sv[i];
|
||||
mpData[mSize] = '\0';
|
||||
|
||||
}
|
||||
|
||||
String::String(size_t n, char a)
|
||||
{
|
||||
resize(n);
|
||||
|
||||
for (size_t i = 0; i < mSize; ++i)
|
||||
mpData[i] = a;
|
||||
}
|
||||
|
||||
String::~String()
|
||||
{
|
||||
std::free(mpData);
|
||||
}
|
||||
|
||||
void String::reserve(size_t capacity)
|
||||
{
|
||||
if (capacity <= mCapacity)
|
||||
return;
|
||||
|
||||
mCapacity = std::max(2 * mCapacity, capacity);
|
||||
char* newData = errorCheckedMalloc(mCapacity);
|
||||
|
||||
if (mpData)
|
||||
std::memcpy(newData, mpData, mSize + 1);
|
||||
|
||||
std::free(mpData);
|
||||
mpData = newData;
|
||||
}
|
||||
|
||||
|
||||
void String::resize(size_t size)
|
||||
{
|
||||
reserve(size + 1);
|
||||
mSize = size;
|
||||
mpData[mSize] = '\0';
|
||||
}
|
||||
|
||||
|
||||
String& String::operator=(const String& right)
|
||||
{
|
||||
if (this == &right)
|
||||
return *this;
|
||||
|
||||
mSize = right.mSize;
|
||||
resize(mSize);
|
||||
|
||||
std::memcpy(mpData, right.mpData, mSize + 1);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
String String::operator+(const String& b)
|
||||
{
|
||||
String result;
|
||||
result.resize(mSize + b.mSize);
|
||||
|
||||
std::memcpy(result.mpData, mpData, mSize);
|
||||
std::memcpy(result.mpData + mSize, b.mpData, b.mSize);
|
||||
result.mpData[result.mSize] = '\0';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
String& String::operator+=(const String& right)
|
||||
{
|
||||
*this = *this + right;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool String::operator==(const String& right) const
|
||||
{
|
||||
if (mSize != right.mSize)
|
||||
return false;
|
||||
|
||||
size_t i = 0;
|
||||
while (i < mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return i == mSize;
|
||||
}
|
||||
|
||||
bool String::operator<(const String& right) const
|
||||
{
|
||||
size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] < right.mpData[i];
|
||||
}
|
||||
|
||||
bool String::operator<=(const String& right) const
|
||||
{
|
||||
size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] <= right.mpData[i];
|
||||
}
|
||||
|
||||
bool String::operator!=(const String& right) const
|
||||
{
|
||||
return !(*this == right);
|
||||
}
|
||||
|
||||
bool String::operator>(const String& right) const
|
||||
{
|
||||
return !(*this <= right);
|
||||
}
|
||||
|
||||
bool String::operator>=(const String& right) const
|
||||
{
|
||||
return !(*this < right);
|
||||
}
|
||||
|
||||
char& String::operator[](size_t i)
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
const char& String::operator[](size_t i) const
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
char& String::at(size_t i)
|
||||
{
|
||||
if (i >= mSize)
|
||||
{
|
||||
cout << "Error! Index is out of bounds." << endl;
|
||||
}
|
||||
return mpData[i];
|
||||
}
|
||||
|
||||
void String::clear()
|
||||
{
|
||||
std::free(mpData);
|
||||
|
||||
mSize = 0;
|
||||
mCapacity = 1;
|
||||
mpData = errorCheckedMalloc(mCapacity);
|
||||
mpData[0] = '\0';
|
||||
}
|
||||
|
||||
void String::addCharacter(char c)
|
||||
{
|
||||
if (mSize + 1 == mCapacity)
|
||||
reserve(2 * mCapacity);
|
||||
|
||||
mpData[mSize] = c;
|
||||
resize(mSize + 1);
|
||||
}
|
||||
|
||||
|
||||
size_t String::getSize() const {return mSize;}
|
||||
size_t String::getCapacity() const {return mCapacity;}
|
||||
const char* String::cStr() const {return mpData;}
|
||||
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||
{
|
||||
out << s.cStr();
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream& in, String& s)
|
||||
{
|
||||
s.clear();
|
||||
while (true)
|
||||
{
|
||||
char x = in.get();
|
||||
if (x == ' ' || x == '\n' || x == '\t')
|
||||
break;
|
||||
s.addCharacter(x);
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
}
|
43
term1/seminar03_initialization/08_stringview/miptstring.h
Normal file
43
term1/seminar03_initialization/08_stringview/miptstring.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
#include <iostream>
|
||||
|
||||
namespace mipt {
|
||||
|
||||
class StringView;
|
||||
class String
|
||||
{
|
||||
private:
|
||||
size_t mSize {0};
|
||||
size_t mCapacity {0};
|
||||
char* mpData {nullptr};
|
||||
public:
|
||||
String(const char* str);
|
||||
String();
|
||||
String(const String& s);
|
||||
String(const mipt::StringView& sv);
|
||||
String(size_t n, char a);
|
||||
~String();
|
||||
void reserve(size_t capacity);
|
||||
void resize(size_t size);
|
||||
String& operator=(const String& right);
|
||||
String operator+(const String& b);
|
||||
String& operator+=(const String& right);
|
||||
bool operator==(const String& right) const;
|
||||
bool operator<(const String& right) const;
|
||||
bool operator<=(const String& right) const;
|
||||
bool operator!=(const String& right) const;
|
||||
bool operator>(const String& right) const;
|
||||
bool operator>=(const String& right) const;
|
||||
char& operator[](size_t i);
|
||||
const char& operator[](size_t i) const;
|
||||
char& at(size_t i);
|
||||
void clear();
|
||||
void addCharacter(char c);
|
||||
size_t getSize() const;
|
||||
size_t getCapacity() const;
|
||||
const char* cStr() const;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const String& s);
|
||||
std::istream& operator>>(std::istream& in, String& s);
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include "miptstring.h"
|
||||
#include "miptstringview.h"
|
||||
using std::cout, std::cin, std::endl, std::size_t;
|
||||
|
||||
namespace mipt {
|
||||
|
||||
StringView::StringView() {;
|
||||
mSize = 0;
|
||||
mpData = nullptr;
|
||||
}
|
||||
StringView::StringView(const StringView& str) {
|
||||
mSize = str.mSize;
|
||||
mpData = str.mpData;
|
||||
}
|
||||
StringView::StringView(const mipt::String& s) {
|
||||
mSize = s.getSize();
|
||||
mpData = s.cStr();
|
||||
}
|
||||
StringView::StringView(const char* s) {
|
||||
mpData = s;
|
||||
mSize = strlen(s);
|
||||
}
|
||||
const char& StringView::at(size_t i)
|
||||
{
|
||||
if (i >= mSize)
|
||||
{
|
||||
throw std::out_of_range("Error! Index is out of bounds.");
|
||||
std::exit(1);
|
||||
}
|
||||
return mpData[i];
|
||||
}
|
||||
const char& StringView::operator[](size_t i) const
|
||||
{
|
||||
return mpData[i];
|
||||
}
|
||||
bool StringView::operator<(const StringView& right) const
|
||||
{
|
||||
size_t i = 0;
|
||||
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||
i++;
|
||||
|
||||
return mpData[i] < right.mpData[i];
|
||||
}
|
||||
size_t StringView::size() const {
|
||||
return mSize;
|
||||
}
|
||||
StringView StringView::substr(size_t pos, size_t count) {
|
||||
if (pos > mSize)
|
||||
throw std::out_of_range("Error! Index is out of bounds.");
|
||||
if (pos + count > mSize)
|
||||
count = mSize - pos;
|
||||
StringView result;
|
||||
result.mpData = mpData + pos;
|
||||
result.mSize = count;
|
||||
return result;
|
||||
}
|
||||
void StringView::remove_prefix(size_t n) {
|
||||
mSize -= n;
|
||||
}
|
||||
void StringView::remove_suffix(size_t n) {
|
||||
mSize -= n;
|
||||
mpData += n;
|
||||
}
|
||||
/*std::ostream& StringView::operator<<(std::ostream& out, mipt::StringView sv) {
|
||||
size_t size = sv.size();
|
||||
for (int i = 0; i < size; ++i)
|
||||
out << sv[i];
|
||||
return out;
|
||||
}*/
|
||||
std::ostream& operator<<(std::ostream& out, const mipt::StringView& sv) {
|
||||
size_t size = sv.size();
|
||||
for (int i = 0; i < size; ++i)
|
||||
out << sv[i];
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace mipt {
|
||||
class String;
|
||||
class StringView
|
||||
{
|
||||
private:
|
||||
const char* mpData;
|
||||
size_t mSize;
|
||||
public:
|
||||
StringView();
|
||||
StringView(const StringView& str);
|
||||
StringView(const mipt::String& s);
|
||||
StringView(const char* s);
|
||||
const char& at(size_t i);
|
||||
const char& operator[](size_t i) const;
|
||||
bool operator<(const StringView& right) const;
|
||||
size_t size() const;
|
||||
StringView substr(size_t pos, size_t count);
|
||||
void remove_prefix(size_t n);
|
||||
void remove_suffix(size_t n);
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const StringView& sv);
|
||||
|
||||
}
|
BIN
term1/seminar03_initialization/homework_initialization.pdf
Normal file
BIN
term1/seminar03_initialization/homework_initialization.pdf
Normal file
Binary file not shown.
18
term1/seminar04_templates/01_sum_even/main.cpp
Normal file
18
term1/seminar04_templates/01_sum_even/main.cpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using std::cout, std::endl;
|
||||
|
||||
int sumEven(const std::vector<int>& v) {
|
||||
int sum = 0;
|
||||
size_t s = v.size();
|
||||
for (int i = 0; i < s; ++i)
|
||||
if (v[i] % 2 == 0)
|
||||
sum += v[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::vector<int> v {4, 8, 15, 16, 23, 42};
|
||||
cout << sumEven(v) << endl;
|
||||
}
|
58
term1/seminar04_templates/02_last_digits/main.cpp
Normal file
58
term1/seminar04_templates/02_last_digits/main.cpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <span>
|
||||
|
||||
using std::cout, std::endl, std::vector, std::span;
|
||||
|
||||
vector<int> lastDigits1(const vector<int>& v) {
|
||||
vector<int> result;
|
||||
size_t size = v.size();
|
||||
for(int i = 0; i < size; ++i) {
|
||||
result.push_back(v[i] % 10);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
void lastDigits2(vector<int>& v) {
|
||||
size_t size = v.size();
|
||||
for(int i = 0; i < size; ++i) {
|
||||
v[i] %= 10;
|
||||
}
|
||||
}
|
||||
|
||||
void lastDigits3(vector<int>* pv) {
|
||||
size_t size = pv->size();
|
||||
for(int i = 0; i < size; ++i)
|
||||
(*pv)[i] %= 10;
|
||||
}
|
||||
|
||||
void lastDigits4(span<int> sp) {
|
||||
size_t size = sp.size();
|
||||
for(int i = 0; i < size; ++i)
|
||||
sp[i] %= 10;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const vector<int>& v) {
|
||||
cout << "[";
|
||||
size_t size = v.size();
|
||||
for(int i = 0; i < size; ++i)
|
||||
cout << v[i] << (i == size - 1 ? "]" : " ");
|
||||
return out;
|
||||
}
|
||||
|
||||
int main() {
|
||||
vector<int> meow{1, 2, 3, 12, 45, 32,313123,3245};
|
||||
vector<int> result1 = lastDigits1(meow);
|
||||
cout << result1 << endl;
|
||||
|
||||
vector<int> result2 = meow;
|
||||
lastDigits2(result2);
|
||||
cout << result2 << endl;
|
||||
|
||||
vector<int> result3 = meow;
|
||||
lastDigits3(&result3);
|
||||
cout << result3 << endl;
|
||||
|
||||
span<int> sp = meow;
|
||||
lastDigits4(sp);
|
||||
cout << meow << endl;
|
||||
}
|
52
term1/seminar04_templates/03_factorization/main.cpp
Normal file
52
term1/seminar04_templates/03_factorization/main.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
#include <iostream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
using std::cout, std::endl, std::pair, std::vector;
|
||||
|
||||
vector<pair<int, int>> factorization(int n) {
|
||||
if (n == 1) {
|
||||
return vector<pair<int,int>>{{1, 1}};
|
||||
}
|
||||
int d = 2;
|
||||
int c;
|
||||
vector<pair<int, int>> result;
|
||||
|
||||
while(n != 1) {
|
||||
c = 0;
|
||||
while(n % d == 0) {
|
||||
c++;
|
||||
n /= d;
|
||||
}
|
||||
if (c)
|
||||
result.push_back(pair{d, c});
|
||||
d++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, pair<int,int> p) {
|
||||
out << "{" << p.first << ", " << p.second << "}";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, vector<pair<int,int>> v) {
|
||||
out << "{";
|
||||
size_t size = v.size();
|
||||
for(int i = 0; i < size; ++i) {
|
||||
out << v[i] << (i == size - 1 ? "}" : ", ");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int main() {
|
||||
vector<pair<int, int>> res = factorization(60);
|
||||
cout << res << endl;
|
||||
res = factorization(626215995);
|
||||
cout << res << endl;
|
||||
res = factorization(107);
|
||||
cout << res << endl;
|
||||
res = factorization(1);
|
||||
cout << res << endl;
|
||||
}
|
27
term1/seminar04_templates/04_time/main.cpp
Normal file
27
term1/seminar04_templates/04_time/main.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include <iostream>
|
||||
#include "time.h"
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using std::cout, std::endl, std::string, std::string_view, std::vector;
|
||||
|
||||
int main()
|
||||
{
|
||||
string t1s = "23:59:59";
|
||||
string_view t1sv = t1s;
|
||||
string t2s = "23:59:59";
|
||||
string_view t2sv = t2s;
|
||||
|
||||
Time t1 = t1sv;
|
||||
Time t2 = t2sv;
|
||||
cout << t1 + t2 << endl;
|
||||
|
||||
string tss = "23:59:59 23:59:59 23:59:59";
|
||||
string_view tssv = tss;
|
||||
vector < Time > tsv = getTimesFromString(tss);
|
||||
for (int i = 0, size = tsv.size(); i < size; ++i) {
|
||||
cout << tsv[i] << endl;
|
||||
}
|
||||
cout << sumTimes(tsv) << endl;
|
||||
}
|
78
term1/seminar04_templates/04_time/time.cpp
Normal file
78
term1/seminar04_templates/04_time/time.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
#include "time.h"
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
|
||||
using std::cout, std::endl, std::vector, std::string_view, std::string;
|
||||
|
||||
Time::Time(int hours, int minutes, int seconds)
|
||||
{
|
||||
mHours = hours;
|
||||
mMinutes = minutes;
|
||||
mSeconds = seconds;
|
||||
}
|
||||
|
||||
Time::Time(string_view s)
|
||||
{
|
||||
string buf;
|
||||
buf = s.substr(0, 2);
|
||||
mHours = stoi(buf);
|
||||
buf = s.substr(3, 2);
|
||||
mMinutes = stoi(buf);
|
||||
buf = s.substr(6, 2);
|
||||
mSeconds = stoi(buf);
|
||||
}
|
||||
|
||||
Time::Time():Time(0, 0, 0)
|
||||
{
|
||||
};
|
||||
|
||||
Time Time::operator+(Time b) const
|
||||
{
|
||||
return Time((mHours + b.mHours + (mMinutes + b.mMinutes) / 60) % 24,
|
||||
(mMinutes + b.mMinutes +
|
||||
(mSeconds + b.mSeconds) / 60) % 60,
|
||||
(mSeconds + b.mSeconds) % 60);
|
||||
}
|
||||
|
||||
int Time::hours() const
|
||||
{
|
||||
return mHours;
|
||||
}
|
||||
|
||||
int Time::minutes() const
|
||||
{
|
||||
return mMinutes;
|
||||
}
|
||||
|
||||
int Time::seconds() const
|
||||
{
|
||||
return mSeconds;
|
||||
}
|
||||
|
||||
vector < Time > getTimesFromString(string_view s)
|
||||
{
|
||||
vector < Time > res;
|
||||
for (int i = 0, size = s.size(); i < size; i += 9) {
|
||||
res.push_back(Time(s.substr(i, 9)));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Time sumTimes(const vector < Time > &v)
|
||||
{
|
||||
Time res;
|
||||
for (int i = 0, size = v.size(); i < size; ++i) {
|
||||
res = res + v[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & out, Time t)
|
||||
{
|
||||
out << std::setw(2) << std::setfill('0') << t.mHours
|
||||
<< ":"
|
||||
<< std::setw(2) << std::setfill('0') << t.mMinutes
|
||||
<< ":" << std::setw(2) << std::setfill('0') << t.mSeconds;
|
||||
return out;
|
||||
}
|
21
term1/seminar04_templates/04_time/time.h
Normal file
21
term1/seminar04_templates/04_time/time.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
#include <string_view>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
using std::string_view, std::vector;
|
||||
|
||||
class Time {
|
||||
private:
|
||||
int mHours = 0, mMinutes = 0, mSeconds = 0;
|
||||
public:
|
||||
Time(int hours, int minutes, int seconds);
|
||||
Time();
|
||||
Time(string_view s);
|
||||
Time operator+(Time b) const;
|
||||
int hours() const; int minutes() const; int seconds() const;
|
||||
friend std::ostream& operator<<(std::ostream& out, Time t);
|
||||
};
|
||||
|
||||
Time sumTimes(const vector<Time>& v);
|
||||
vector<Time> getTimesFromString(string_view s);
|
34
term1/seminar04_templates/05_maximum/main.cpp
Normal file
34
term1/seminar04_templates/05_maximum/main.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using std::string, std::pair, std::cout, std::endl, std::vector;
|
||||
|
||||
template <typename T>
|
||||
T maximum(const vector<T>& v) {
|
||||
T max{};
|
||||
for(int i = 0, size = v.size(); i < size; ++i) {
|
||||
if (v[i] > max)
|
||||
max = v[i];
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
int main() {
|
||||
vector<int> int_v {1,3,5,3,23,113,34,54};
|
||||
cout << maximum(int_v) << endl;
|
||||
vector<float> float_v {1.5,5.64,5.67,45.65,113,67.5,98.12};
|
||||
cout << maximum(float_v) << endl;
|
||||
vector<string> string_v {"aaaa", "dfg", "dsfdgjb", "meow", "dsfewvcv", "klafdn"};
|
||||
cout << maximum(string_v) << endl;
|
||||
vector<pair<int, int>> pair_v {
|
||||
{113, 1},
|
||||
{12, 3},
|
||||
{45, 34},
|
||||
{113, 113},
|
||||
{112, 12233}
|
||||
};
|
||||
pair<int, int> res = maximum(pair_v);
|
||||
cout << "(" << res.first << ", " << res.second << ")" << endl;
|
||||
}
|
65
term1/seminar04_templates/06_pairing/main.cpp
Normal file
65
term1/seminar04_templates/06_pairing/main.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
using std::cout, std::endl, std::vector, std::pair;
|
||||
|
||||
template <typename T, typename U>
|
||||
std::ostream& operator<<(std::ostream& out, const std::pair<T, U>& p)
|
||||
{
|
||||
out << "(" << p.first << ", " << p.second << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::ostream& operator<<(std::ostream& out, const std::vector<T>& v)
|
||||
{
|
||||
out << "[";
|
||||
for (size_t i = 0; i < v.size() - 1; ++i)
|
||||
out << v[i] << ", ";
|
||||
|
||||
if (!v.empty())
|
||||
{
|
||||
out << v.back();
|
||||
}
|
||||
out << "]";
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
vector<pair<typename T::value_type,typename T::value_type>> pairing(T& xs) {
|
||||
typedef typename T::value_type U;
|
||||
vector<pair<U, U>> res;
|
||||
|
||||
size_t size = xs.size();
|
||||
|
||||
for (int i = 0, n = (size % 2 ? size - 1: size); i < n; i += 2)
|
||||
res.push_back(pair(xs[i], xs[i+1]));
|
||||
if (size % 2)
|
||||
res.push_back(pair(xs[size - 1], U()));
|
||||
return res;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector v {10, 20, 30, 40, 50, 60};
|
||||
cout << pairing(v) << endl;
|
||||
|
||||
|
||||
std::array<std::string, 7> a {"cat", "dog", "mouse", "elephant", "tiget", "axolotl", "wolf"};
|
||||
cout << pairing(a) << endl;
|
||||
|
||||
|
||||
std::string s {"Cats and dogs!"};
|
||||
cout << pairing(s) << endl;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Программа должна напечатать:
|
||||
|
||||
[(10, 20), (30, 40), (50, 60)]
|
||||
[(cat, dog), (mouse, elephant), (tiget, axolotl), (wolf, )]
|
||||
[(C, a), (t, s), ( , a), (n, d), ( , d), (o, g), (s, !)]
|
||||
*/
|
42
term1/seminar04_templates/07_manager/main.cpp
Normal file
42
term1/seminar04_templates/07_manager/main.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
template <typename T>
|
||||
class Manager {
|
||||
private:
|
||||
T* mPtr;
|
||||
public:
|
||||
Manager() {
|
||||
mPtr = nullptr;
|
||||
}
|
||||
void allocate() {
|
||||
mPtr = (T*)malloc(sizeof(T));
|
||||
}
|
||||
void construct(const T& t) {
|
||||
new(mPtr) T{t};
|
||||
}
|
||||
T& get() {
|
||||
return *mPtr;
|
||||
}
|
||||
void destruct() {
|
||||
mPtr->~T();
|
||||
}
|
||||
void deallocate() {
|
||||
free(mPtr);
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
Manager<std::string> a;
|
||||
a.allocate();
|
||||
a.construct("Cats and dogs");
|
||||
a.get() += " and elephants";
|
||||
std::cout << a.get() << std::endl;
|
||||
a.destruct();
|
||||
|
||||
a.construct("Sapere aude");
|
||||
std::cout << a.get() << std::endl;
|
||||
|
||||
a.destruct();
|
||||
a.deallocate();
|
||||
}
|
74
term1/seminar04_templates/08_ref/main.cpp
Normal file
74
term1/seminar04_templates/08_ref/main.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using std::cout, std::endl, std::string, std::vector;
|
||||
|
||||
template <typename T>
|
||||
class Ref {
|
||||
private:
|
||||
T* mPtr;
|
||||
public:
|
||||
Ref(T& t) {
|
||||
mPtr = &t;
|
||||
}
|
||||
Ref(Ref& t) {
|
||||
mPtr = t.mPtr;
|
||||
}
|
||||
Ref() {
|
||||
mPtr = nullptr;
|
||||
}
|
||||
T& get() {
|
||||
return *mPtr;
|
||||
}
|
||||
T operator=(const T& t) {
|
||||
new(mPtr) T{t};
|
||||
return *mPtr;
|
||||
}
|
||||
T operator+(const T& t) {
|
||||
return *mPtr + t;
|
||||
}
|
||||
T operator+=(const T& t) {
|
||||
*mPtr = *mPtr + t;
|
||||
return *mPtr;
|
||||
}
|
||||
T* operator->() {
|
||||
return mPtr;
|
||||
}
|
||||
template <typename U>
|
||||
friend std::ostream& operator<<(std::ostream& out, Ref<U> r);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
std::ostream& operator<<(std::ostream& out, Ref<T> r) {
|
||||
out << *(r.mPtr);
|
||||
return out;
|
||||
}
|
||||
|
||||
void toUpper(Ref<string> r) {
|
||||
for(size_t i = 0; i < r->size(); ++i)
|
||||
r.get()[i] = toupper(r.get()[i]);
|
||||
}
|
||||
|
||||
int main() {
|
||||
int a = 10;
|
||||
Ref<int> ra = a;
|
||||
cout << ra << endl;
|
||||
|
||||
string s = "Cat";
|
||||
Ref<string> rs = s;
|
||||
rs = "Mouse";
|
||||
rs += "Elephant";
|
||||
cout << rs << endl;
|
||||
cout << s << endl;
|
||||
|
||||
toUpper(s);
|
||||
cout << s << endl;
|
||||
|
||||
vector<string> animals {"Cat", "Dogs", "Elephants", "Worms"};
|
||||
vector<Ref<string>> refs {animals.begin(), animals.end()};
|
||||
|
||||
for (int i = 0; i < refs.size(); ++i)
|
||||
cout << animals[i] << " ";
|
||||
cout << endl;
|
||||
}
|
BIN
term1/seminar04_templates/homework_templates.pdf
Normal file
BIN
term1/seminar04_templates/homework_templates.pdf
Normal file
Binary file not shown.
22
term1/seminar05_iterators/01_slide/main.cpp
Normal file
22
term1/seminar05_iterators/01_slide/main.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
using std::cout, std::endl, std::vector, std::cin;
|
||||
|
||||
int main() {
|
||||
size_t n;
|
||||
cin >> n;
|
||||
vector<int> v(n);
|
||||
for (int i = 0; i < n; ++i)
|
||||
cin >> v[i];
|
||||
|
||||
vector<int>::iterator max = std::max_element(v.begin(), v.end());
|
||||
std::sort(v.begin(), max);
|
||||
std::sort(max, v.end());
|
||||
std::reverse(max, v.end());
|
||||
|
||||
for (int i = 0; i < v.size(); ++i)
|
||||
cout << v[i] << (i == v.size() - 1 ? "": " ");
|
||||
cout << endl;
|
||||
}
|
27
term1/seminar05_iterators/02_string_vector_reverse/main.cpp
Normal file
27
term1/seminar05_iterators/02_string_vector_reverse/main.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
using std::cout, std::endl, std::string, std::vector;
|
||||
|
||||
void string_vector_reverse(vector<string>& sv) {
|
||||
std::for_each(sv.begin(), sv.end(), [](string& s){ std::reverse(s.begin(), s.end()); });
|
||||
std::reverse(sv.begin(), sv.end());
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
vector<string> sv1 {"cat", "dog", "mouse", "elephant"};
|
||||
vector<string> sv2 {"a", "bc"};
|
||||
|
||||
string_vector_reverse(sv1);
|
||||
string_vector_reverse(sv2);
|
||||
|
||||
for (int i = 0; i < sv1.size(); ++i)
|
||||
cout << sv1[i] << (i == sv1.size() - 1 ? "" : " ");
|
||||
cout << endl;
|
||||
for (int i = 0; i < sv2.size(); ++i)
|
||||
cout << sv2[i] << (i == sv2.size() - 1 ? "" : " ");
|
||||
cout << endl;
|
||||
}
|
18
term1/seminar05_iterators/03_is_uppper/main.cpp
Normal file
18
term1/seminar05_iterators/03_is_uppper/main.cpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <numeric>
|
||||
#include <cctype>
|
||||
|
||||
using std::string, std::cin, std::cout, std::endl;
|
||||
|
||||
bool strIsUpper(const string& s) {
|
||||
return std::accumulate(s.begin(), s.end(), true, [](bool res, char c) {return res && (!isalpha(c) || isupper(c)); });
|
||||
}
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
getline(cin, s);
|
||||
cout << strIsUpper(s) << endl;
|
||||
}
|
22
term1/seminar05_iterators/04_is_identifier/main.cpp
Normal file
22
term1/seminar05_iterators/04_is_identifier/main.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <cctype>
|
||||
|
||||
using std::cout, std::endl, std::string, std::string_view;
|
||||
|
||||
bool isIdentifier(string_view sv) {
|
||||
bool is = true;
|
||||
if (!(std::isalpha(sv[0]) || sv[0] == '_'))
|
||||
return false;
|
||||
if (std::all_of(sv.begin(), sv.end(), [](const char c){ return isalpha(c) || isdigit(c) || c == '_' ;}))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
getline(std::cin, s);
|
||||
cout << isIdentifier(s) << endl;
|
||||
}
|
18
term1/seminar05_iterators/05_move_spaces/main.cpp
Normal file
18
term1/seminar05_iterators/05_move_spaces/main.cpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
using std::cout, std::string, std::endl;
|
||||
|
||||
void move_spaces(string& s) {
|
||||
std::stable_sort(s.begin(), s.end(), [](const char& a, const char& b){ return (b == ' '); });
|
||||
}
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
std::getline(std::cin, s);
|
||||
move_spaces(s);
|
||||
// So we can see spaces
|
||||
cout << s << "###" << endl;
|
||||
|
||||
}
|
BIN
term1/seminar05_iterators/homework_iterators.pdf
Normal file
BIN
term1/seminar05_iterators/homework_iterators.pdf
Normal file
Binary file not shown.
2
term1/seminar09_libraries/01_balls/Makefile
Normal file
2
term1/seminar09_libraries/01_balls/Makefile
Normal file
|
@ -0,0 +1,2 @@
|
|||
balls:
|
||||
g++ ./balls.cpp -std=c++11 -o balls.exe -I../../../3rdparty/SFML-2.5.1/include -L ../../../3rdparty/SFML-2.5.1/lib/ -lsfml-graphics -lsfml-window -lsfml-system
|
94
term1/seminar09_libraries/01_balls/balls.cpp
Normal file
94
term1/seminar09_libraries/01_balls/balls.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
struct Ball
|
||||
{
|
||||
float radius;
|
||||
sf::Vector2f position;
|
||||
sf::Vector2f velocity;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
srand(time(0));
|
||||
|
||||
const int width = 1000;
|
||||
const int height = 800;
|
||||
const int n_balls = 100;
|
||||
|
||||
// Шаг по времени
|
||||
const float delta_t = 0.1;
|
||||
|
||||
// Создаём экземпляр класса окно
|
||||
sf::RenderWindow window(sf::VideoMode(width, height), "My window");
|
||||
// Задаём максимальное количество кадров в секунду
|
||||
window.setFramerateLimit(60);
|
||||
|
||||
// Так как sf::CircleShape занимает много памяти, создаём всего 1 экземпляр
|
||||
sf::CircleShape circle(50.0f);
|
||||
circle.setFillColor({200, 216, 200});
|
||||
|
||||
std::vector<Ball> balls;
|
||||
balls.resize(n_balls);
|
||||
for (int i = 0; i < n_balls; i++)
|
||||
{
|
||||
balls[i].radius = 4 + rand() % 8;
|
||||
balls[i].position = {(float)(rand() % width), (float)(rand() % height)};
|
||||
balls[i].velocity = {(float)(rand() % 100 - 50), (float)(rand() % 100 - 50)};
|
||||
}
|
||||
|
||||
while (window.isOpen())
|
||||
{
|
||||
sf::Event event;
|
||||
while (window.pollEvent(event))
|
||||
{
|
||||
// В данном примере проверяем окно на закрытие
|
||||
if (event.type == sf::Event::Closed)
|
||||
window.close();
|
||||
}
|
||||
|
||||
// очистить скрытый холст черным цветом
|
||||
window.clear(sf::Color::Black);
|
||||
|
||||
for (int i = 0; i < n_balls; i++)
|
||||
{
|
||||
balls[i].position += balls[i].velocity * delta_t;
|
||||
|
||||
/*
|
||||
if (balls[i].position.x < 0)
|
||||
balls[i].position.x += width;
|
||||
if (balls[i].position.x > width)
|
||||
balls[i].position.x -= width;
|
||||
|
||||
if (balls[i].position.y < 0)
|
||||
balls[i].position.y += height;
|
||||
if (balls[i].position.y > height)
|
||||
balls[i].position.y -= height;
|
||||
*/
|
||||
|
||||
// Используем 1 sf::CircleShape, чтобы нарисовать все шары
|
||||
circle.setRadius(balls[i].radius);
|
||||
// setOrigin - задаёт центр объекта
|
||||
// По умолчанию центр - в левом верхнем угле объекта
|
||||
// Строка ниже устанавливает центр в центре шарика
|
||||
// В дальнейшем функция, setPosition устанавливает положение шарика так,
|
||||
// чтобы его центр был в точке balls[i].position
|
||||
circle.setOrigin(balls[i].radius, balls[i].radius);
|
||||
circle.setPosition(balls[i].position);
|
||||
|
||||
window.draw(circle);
|
||||
}
|
||||
|
||||
// отображаем содержимое скрытого холста на экран
|
||||
window.display();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
2
term1/seminar09_libraries/02_thor/Makefile
Normal file
2
term1/seminar09_libraries/02_thor/Makefile
Normal file
|
@ -0,0 +1,2 @@
|
|||
balls:
|
||||
g++ ./balls.cpp -std=c++11 -o balls.exe -I../../../3rdparty/SFML-2.5.1/include -L ../../../3rdparty/SFML-2.5.1/lib/ -lsfml-graphics -lsfml-window -lsfml-system
|
93
term1/seminar09_libraries/02_thor/balls.cpp
Normal file
93
term1/seminar09_libraries/02_thor/balls.cpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
struct Ball
|
||||
{
|
||||
float radius;
|
||||
sf::Vector2f position;
|
||||
sf::Vector2f velocity;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
srand(time(0));
|
||||
|
||||
const int width = 1000;
|
||||
const int height = 800;
|
||||
const int n_balls = 100;
|
||||
// Шаг по времени
|
||||
const float delta_t = 0.1;
|
||||
|
||||
// Создаём экземпляр класса окно
|
||||
sf::RenderWindow window(sf::VideoMode(width, height), "My window");
|
||||
// Задаём максимальное количество кадров в секунду
|
||||
window.setFramerateLimit(60);
|
||||
|
||||
// Так как sf::CircleShape занимает много памяти, создаём всего 1 экземпляр
|
||||
sf::CircleShape circle(50.0f);
|
||||
circle.setFillColor({200, 216, 200});
|
||||
|
||||
std::vector<Ball> balls;
|
||||
balls.resize(n_balls);
|
||||
for (int i = 0; i < n_balls; i++)
|
||||
{
|
||||
balls[i].radius = 4 + rand() % 8;
|
||||
balls[i].position = {(float)(rand() % width), (float)(rand() % height)};
|
||||
balls[i].velocity = {(float)(rand() % 100 - 50), (float)(rand() % 100 - 50)};
|
||||
}
|
||||
|
||||
while (window.isOpen())
|
||||
{
|
||||
sf::Event event;
|
||||
while (window.pollEvent(event))
|
||||
{
|
||||
// В данном примере проверяем окно на закрытие
|
||||
if (event.type == sf::Event::Closed)
|
||||
window.close();
|
||||
}
|
||||
|
||||
// очистить скрытый холст черным цветом
|
||||
window.clear(sf::Color::Black);
|
||||
|
||||
for (int i = 0; i < n_balls; i++)
|
||||
{
|
||||
balls[i].position += balls[i].velocity * delta_t;
|
||||
|
||||
|
||||
if (balls[i].position.x < 0)
|
||||
balls[i].position.x += width;
|
||||
if (balls[i].position.x > width)
|
||||
balls[i].position.x -= width;
|
||||
|
||||
if (balls[i].position.y < 0)
|
||||
balls[i].position.y += height;
|
||||
if (balls[i].position.y > height)
|
||||
balls[i].position.y -= height;
|
||||
|
||||
|
||||
// Используем 1 sf::CircleShape, чтобы нарисовать все шары
|
||||
circle.setRadius(balls[i].radius);
|
||||
// setOrigin - задаёт центр объекта
|
||||
// По умолчанию центр - в левом верхнем угле объекта
|
||||
// Строка ниже устанавливает центр в центре шарика
|
||||
// В дальнейшем функция, setPosition устанавливает положение шарика так,
|
||||
// чтобы его центр был в точке balls[i].position
|
||||
circle.setOrigin(balls[i].radius, balls[i].radius);
|
||||
circle.setPosition(balls[i].position);
|
||||
|
||||
window.draw(circle);
|
||||
}
|
||||
|
||||
// отображаем содержимое скрытого холста на экран
|
||||
window.display();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
90
term1/seminar09_libraries/03_walls/balls.cpp
Normal file
90
term1/seminar09_libraries/03_walls/balls.cpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
struct Ball
|
||||
{
|
||||
float radius;
|
||||
sf::Vector2f position;
|
||||
sf::Vector2f velocity;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
srand(time(0));
|
||||
|
||||
const int width = 1000;
|
||||
const int height = 800;
|
||||
const int n_balls = 100;
|
||||
|
||||
// Шаг по времени
|
||||
const float delta_t = 0.1; ///
|
||||
|
||||
// Создаём экземпляр класса окно
|
||||
sf::RenderWindow window(sf::VideoMode(width, height), "My window");
|
||||
// Задаём максимальное количество кадров в секунду
|
||||
window.setFramerateLimit(60);
|
||||
|
||||
// Так как sf::CircleShape занимает много памяти, создаём всего 1 экземпляр
|
||||
sf::CircleShape circle(50.0f);
|
||||
circle.setFillColor({200, 216, 200});
|
||||
|
||||
std::vector<Ball> balls;
|
||||
balls.resize(n_balls);
|
||||
for (int i = 0; i < n_balls; i++)
|
||||
{
|
||||
balls[i].radius = 4 + rand() % 8;
|
||||
balls[i].position = {(float)(rand() % width), (float)(rand() % height)};
|
||||
balls[i].velocity = {(float)(rand() % 100 - 50), (float)(rand() % 100 - 50)};
|
||||
}
|
||||
|
||||
while (window.isOpen())
|
||||
{
|
||||
sf::Event event;
|
||||
while (window.pollEvent(event))
|
||||
{
|
||||
// В данном примере проверяем окно на закрытие
|
||||
if (event.type == sf::Event::Closed)
|
||||
window.close();
|
||||
}
|
||||
|
||||
// очистить скрытый холст черным цветом
|
||||
window.clear(sf::Color::Black);
|
||||
|
||||
for (int i = 0; i < n_balls; i++)
|
||||
{
|
||||
balls[i].position += balls[i].velocity * delta_t;
|
||||
|
||||
|
||||
if ((balls[i].position.x < 0) || (balls[i].position.x > width))
|
||||
balls[i].velocity.x = -balls[i].velocity.x;
|
||||
|
||||
if ((balls[i].position.y < 0) || (balls[i].position.y > height))
|
||||
balls[i].velocity.y = -balls[i].velocity.y;
|
||||
|
||||
|
||||
// Используем 1 sf::CircleShape, чтобы нарисовать все шары
|
||||
circle.setRadius(balls[i].radius);
|
||||
// setOrigin - задаёт центр объекта
|
||||
// По умолчанию центр - в левом верхнем угле объекта
|
||||
// Строка ниже устанавливает центр в центре шарика
|
||||
// В дальнейшем функция, setPosition устанавливает положение шарика так,
|
||||
// чтобы его центр был в точке balls[i].position
|
||||
circle.setOrigin(balls[i].radius, balls[i].radius);
|
||||
circle.setPosition(balls[i].position);
|
||||
|
||||
window.draw(circle);
|
||||
}
|
||||
|
||||
// отображаем содержимое скрытого холста на экран
|
||||
window.display();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
89
term1/seminar09_libraries/04_n_bodies/balls.cpp
Normal file
89
term1/seminar09_libraries/04_n_bodies/balls.cpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const int min_distance = 5;
|
||||
const float G = 500;
|
||||
|
||||
struct Ball
|
||||
{
|
||||
float radius;
|
||||
float mass = 1;
|
||||
sf::Vector2f position;
|
||||
sf::Vector2f velocity;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
srand(time(0));
|
||||
|
||||
const int width = 1000;
|
||||
const int height = 800;
|
||||
const int n_balls = 15;
|
||||
|
||||
// Шаг по времени
|
||||
const float delta_t = 0.1;
|
||||
sf::RenderWindow window(sf::VideoMode(width, height), "My window");
|
||||
window.setFramerateLimit(60);
|
||||
sf::CircleShape circle(50.0f);
|
||||
circle.setFillColor({200, 216, 200});
|
||||
std::vector<Ball> balls;
|
||||
balls.resize(n_balls);
|
||||
for (int i = 0; i < n_balls; i++)
|
||||
{
|
||||
balls[i].radius = 4 + rand() % 8;
|
||||
balls[i].position = {(float)(rand() % width), (float)(rand() % height)};
|
||||
balls[i].velocity = {(float)(rand() % 100 - 50), (float)(rand() % 100 - 50)};
|
||||
}
|
||||
while (window.isOpen())
|
||||
{
|
||||
sf::Event event;
|
||||
while (window.pollEvent(event))
|
||||
{
|
||||
if (event.type == sf::Event::Closed)
|
||||
window.close();
|
||||
}
|
||||
|
||||
window.clear(sf::Color::Black);
|
||||
|
||||
for (int i = 0; i < n_balls; i++)
|
||||
{
|
||||
|
||||
balls[i].position += balls[i].velocity * delta_t;
|
||||
for (int j = 0; j < n_balls; ++j) {
|
||||
if (i == j)
|
||||
continue;
|
||||
float distance = std::sqrt((balls[j].position.x - balls[i].position.x) * (balls[j].position.x - balls[i].position.x) + (balls[j].position.y - balls[i].position.y) * (balls[j].position.y - balls[i].position.y));
|
||||
if (distance < min_distance)
|
||||
continue;
|
||||
auto direction = balls[j].position - balls[i].position;
|
||||
balls[i].velocity += (direction * G * delta_t * balls[j].mass) / (distance * distance);
|
||||
}
|
||||
|
||||
if (((balls[i].position.x - balls[i].radius) < 0) || (balls[i].position.x + balls[i].radius> width)) {
|
||||
balls[i].velocity.x = -balls[i].velocity.x;
|
||||
balls[i].position.x = (balls[i].position.x - balls[i].radius < 0 ? balls[i].radius : width - balls[i].radius);
|
||||
}
|
||||
if ((balls[i].position.y - balls[i].radius < 0) || (balls[i].position.y + balls[i].radius > height)) {
|
||||
balls[i].velocity.y = -balls[i].velocity.y;
|
||||
balls[i].position.y = (balls[i].position.y - balls[i].radius < 0 ? balls[i].radius : height - balls[i].radius);
|
||||
}
|
||||
|
||||
circle.setRadius(balls[i].radius);
|
||||
circle.setOrigin(balls[i].radius, balls[i].radius);
|
||||
circle.setPosition(balls[i].position);
|
||||
|
||||
window.draw(circle);
|
||||
}
|
||||
|
||||
window.display();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
95
term1/seminar09_libraries/05_n_bodies_mass/balls.cpp
Normal file
95
term1/seminar09_libraries/05_n_bodies_mass/balls.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const int min_distance = 5;
|
||||
const float G = 500;
|
||||
|
||||
struct Ball
|
||||
{
|
||||
float radius;
|
||||
float mass;
|
||||
sf::Vector2f position;
|
||||
sf::Vector2f velocity;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
srand(time(0));
|
||||
|
||||
const int width = 1000;
|
||||
const int height = 800;
|
||||
const int n_balls = 15;
|
||||
|
||||
// Шаг по времени
|
||||
const float delta_t = 0.1;
|
||||
sf::RenderWindow window(sf::VideoMode(width, height), "My window");
|
||||
window.setFramerateLimit(60);
|
||||
sf::CircleShape circle(50.0f);
|
||||
circle.setFillColor({200, 216, 200});
|
||||
std::vector<Ball> balls;
|
||||
balls.resize(n_balls);
|
||||
for (int i = 0; i < n_balls; i++)
|
||||
{
|
||||
balls[i].radius = 4 + rand() % 8;
|
||||
balls[i].mass = balls[i].radius * balls[i].radius / 100;
|
||||
balls[i].position = {(float)(rand() % width), (float)(rand() % height)};
|
||||
balls[i].velocity = {(float)(rand() % 100 - 50), (float)(rand() % 100 - 50)};
|
||||
}
|
||||
/* balls[0].radius = 15;
|
||||
balls[0].mass = 1000;
|
||||
balls[0].position = {(float)(rand() % width), (float)(rand() % height)};
|
||||
balls[0].velocity = {(float)(rand() % 100 - 50), (float)(rand() % 100 - 50)};
|
||||
*/
|
||||
while (window.isOpen())
|
||||
{
|
||||
sf::Event event;
|
||||
while (window.pollEvent(event))
|
||||
{
|
||||
if (event.type == sf::Event::Closed)
|
||||
window.close();
|
||||
}
|
||||
|
||||
window.clear(sf::Color::Black);
|
||||
|
||||
for (int i = 0; i < n_balls; i++)
|
||||
{
|
||||
|
||||
balls[i].position += balls[i].velocity * delta_t;
|
||||
for (int j = 0; j < n_balls; ++j) {
|
||||
if (i == j)
|
||||
continue;
|
||||
float distance = std::sqrt((balls[j].position.x - balls[i].position.x) * (balls[j].position.x - balls[i].position.x) + (balls[j].position.y - balls[i].position.y) * (balls[j].position.y - balls[i].position.y));
|
||||
if (distance < min_distance)
|
||||
continue;
|
||||
auto direction = balls[j].position - balls[i].position;
|
||||
balls[i].velocity += (direction * G * delta_t * balls[j].mass) / (distance * distance);
|
||||
}
|
||||
|
||||
if (((balls[i].position.x - balls[i].radius) < 0) || (balls[i].position.x + balls[i].radius> width)) {
|
||||
balls[i].velocity.x = -balls[i].velocity.x;
|
||||
balls[i].position.x = (balls[i].position.x - balls[i].radius < 0 ? balls[i].radius : width - balls[i].radius);
|
||||
}
|
||||
if ((balls[i].position.y - balls[i].radius < 0) || (balls[i].position.y + balls[i].radius > height)) {
|
||||
balls[i].velocity.y = -balls[i].velocity.y;
|
||||
balls[i].position.y = (balls[i].position.y - balls[i].radius < 0 ? balls[i].radius : height - balls[i].radius);
|
||||
}
|
||||
|
||||
circle.setRadius(balls[i].radius);
|
||||
circle.setOrigin(balls[i].radius, balls[i].radius);
|
||||
circle.setPosition(balls[i].position);
|
||||
|
||||
window.draw(circle);
|
||||
}
|
||||
|
||||
window.display();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
99
term1/seminar09_libraries/06_n_bodies_charges/balls.cpp
Normal file
99
term1/seminar09_libraries/06_n_bodies_charges/balls.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const int min_distance = 5;
|
||||
const float K = 25;
|
||||
|
||||
struct Ball
|
||||
{
|
||||
float radius;
|
||||
float charge;
|
||||
sf::Vector2f position;
|
||||
sf::Vector2f velocity;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
srand(time(0));
|
||||
|
||||
const int width = 1000;
|
||||
const int height = 800;
|
||||
int n_balls = 4;
|
||||
|
||||
const float delta_t = 0.1;
|
||||
sf::RenderWindow window(sf::VideoMode(width, height), "My window");
|
||||
window.setFramerateLimit(60);
|
||||
sf::CircleShape circle(50.0f);
|
||||
|
||||
std::vector<Ball> balls;
|
||||
balls.resize(n_balls);
|
||||
for (int i = 0; i < n_balls; i++)
|
||||
{
|
||||
balls[i].radius = 4 + rand() % 8;
|
||||
balls[i].charge = (rand() % 8 - rand() % 8) * balls[i].radius * balls[i].radius;
|
||||
while (!balls[i].charge) {
|
||||
balls[i].charge = (rand() % 8 - rand() % 8) * balls[i].radius * balls[i].radius;
|
||||
}
|
||||
balls[i].position = {(float)(rand() % width), (float)(rand() % height)};
|
||||
balls[i].velocity = {(float)(rand() % 100 - 50), (float)(rand() % 100 - 50)};
|
||||
}
|
||||
while (window.isOpen())
|
||||
{
|
||||
sf::Event event;
|
||||
while (window.pollEvent(event))
|
||||
{
|
||||
if (event.type == sf::Event::Closed)
|
||||
window.close();
|
||||
}
|
||||
|
||||
window.clear(sf::Color::Black);
|
||||
|
||||
for (int i = 0; i < n_balls; i++)
|
||||
{
|
||||
|
||||
balls[i].position += balls[i].velocity * delta_t;
|
||||
for (int j = 0; j < n_balls; ++j) {
|
||||
if (i == j)
|
||||
continue;
|
||||
float distance = std::sqrt((balls[j].position.x - balls[i].position.x) * (balls[j].position.x - balls[i].position.x) + (balls[j].position.y - balls[i].position.y) * (balls[j].position.y - balls[i].position.y));
|
||||
if (distance < min_distance)
|
||||
continue;
|
||||
auto direction = balls[j].position - balls[i].position;
|
||||
if (balls[i].charge * balls[j].charge > 0)
|
||||
balls[i].velocity -= (direction * K * delta_t * std::abs(balls[j].charge)) / (distance * distance);
|
||||
else
|
||||
balls[i].velocity += (direction * K * delta_t * std::abs(balls[j].charge)) / (distance * distance);
|
||||
}
|
||||
|
||||
if (((balls[i].position.x - balls[i].radius) < 0) || (balls[i].position.x + balls[i].radius> width)) {
|
||||
balls[i].velocity.x = -balls[i].velocity.x;
|
||||
balls[i].position.x = (balls[i].position.x - balls[i].radius < 0 ? balls[i].radius : width - balls[i].radius);
|
||||
}
|
||||
if ((balls[i].position.y - balls[i].radius < 0) || (balls[i].position.y + balls[i].radius > height)) {
|
||||
balls[i].velocity.y = -balls[i].velocity.y;
|
||||
balls[i].position.y = (balls[i].position.y - balls[i].radius < 0 ? balls[i].radius : height - balls[i].radius);
|
||||
}
|
||||
|
||||
circle.setRadius(balls[i].radius);
|
||||
circle.setOrigin(balls[i].radius, balls[i].radius);
|
||||
circle.setPosition(balls[i].position);
|
||||
|
||||
if (balls[i].charge > 0)
|
||||
circle.setFillColor({static_cast<unsigned char>(balls[i].charge/1152 * 255 + 100), 0, 0});
|
||||
else
|
||||
circle.setFillColor({0, 0, static_cast<unsigned char>(std::abs(balls[i].charge)/1152 * 255 + 100)});
|
||||
window.draw(circle);
|
||||
}
|
||||
|
||||
window.display();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
114
term1/seminar09_libraries/07_n_bodies_charges_mouse/balls.cpp
Normal file
114
term1/seminar09_libraries/07_n_bodies_charges_mouse/balls.cpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
#include <SFML/Graphics.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const int min_distance = 5;
|
||||
const float K = 5;
|
||||
|
||||
struct Ball
|
||||
{
|
||||
float radius;
|
||||
float charge;
|
||||
sf::Vector2f position;
|
||||
sf::Vector2f velocity;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
srand(time(0));
|
||||
|
||||
const int width = 1000;
|
||||
const int height = 800;
|
||||
int n_balls = 0;
|
||||
|
||||
char sign = 1;
|
||||
|
||||
// Шаг по времени
|
||||
const float delta_t = 0.1;
|
||||
sf::RenderWindow window(sf::VideoMode(width, height), "My window");
|
||||
window.setFramerateLimit(60);
|
||||
sf::CircleShape circle(50.0f);
|
||||
|
||||
std::vector<Ball> balls;
|
||||
balls.resize(n_balls);
|
||||
while (window.isOpen())
|
||||
{
|
||||
sf::Event event;
|
||||
while (window.pollEvent(event))
|
||||
{
|
||||
if (event.type == sf::Event::Closed)
|
||||
window.close();
|
||||
if (event.type == sf::Event::KeyPressed) {
|
||||
if (event.key.code == sf::Keyboard::LShift) {
|
||||
sign = -1;
|
||||
}
|
||||
}
|
||||
if (event.type == sf::Event::KeyReleased) {
|
||||
if (event.key.code == sf::Keyboard::LShift) {
|
||||
sign = 1;
|
||||
}
|
||||
}
|
||||
if(event.type == sf::Event::MouseButtonPressed) {
|
||||
Ball b;
|
||||
if(event.mouseButton.button == sf::Mouse::Right)
|
||||
b.radius = 15;
|
||||
else if(event.mouseButton.button == sf::Mouse::Left)
|
||||
b.radius = 5;
|
||||
b.charge = sign * b.radius * b.radius;
|
||||
b.position = {(float)(event.mouseButton.x), (float)(event.mouseButton.y)};
|
||||
b.velocity = {(float)(0), (float)(0)};
|
||||
balls.push_back(b);
|
||||
n_balls++;
|
||||
}
|
||||
}
|
||||
|
||||
window.clear(sf::Color::Black);
|
||||
|
||||
for (int i = 0; i < n_balls; i++)
|
||||
{
|
||||
|
||||
balls[i].position += balls[i].velocity * delta_t;
|
||||
for (int j = 0; j < n_balls; ++j) {
|
||||
if (i == j)
|
||||
continue;
|
||||
float distance = std::sqrt((balls[j].position.x - balls[i].position.x) * (balls[j].position.x - balls[i].position.x) + (balls[j].position.y - balls[i].position.y) * (balls[j].position.y - balls[i].position.y));
|
||||
if (distance < min_distance)
|
||||
continue;
|
||||
auto direction = balls[j].position - balls[i].position;
|
||||
if (balls[i].charge * balls[j].charge > 0)
|
||||
balls[i].velocity -= (direction * K * delta_t * std::abs(balls[j].charge)) / (distance * distance);
|
||||
else
|
||||
balls[i].velocity += (direction * K * delta_t * std::abs(balls[j].charge)) / (distance * distance);
|
||||
}
|
||||
|
||||
if (((balls[i].position.x - balls[i].radius) < 0) || (balls[i].position.x + balls[i].radius> width)) {
|
||||
balls[i].velocity.x = -balls[i].velocity.x;
|
||||
balls[i].position.x = (balls[i].position.x - balls[i].radius < 0 ? balls[i].radius : width - balls[i].radius);
|
||||
}
|
||||
if ((balls[i].position.y - balls[i].radius < 0) || (balls[i].position.y + balls[i].radius > height)) {
|
||||
balls[i].velocity.y = -balls[i].velocity.y;
|
||||
balls[i].position.y = (balls[i].position.y - balls[i].radius < 0 ? balls[i].radius : height - balls[i].radius);
|
||||
}
|
||||
|
||||
circle.setRadius(balls[i].radius);
|
||||
circle.setOrigin(balls[i].radius, balls[i].radius);
|
||||
circle.setPosition(balls[i].position);
|
||||
|
||||
if (balls[i].charge > 0)
|
||||
circle.setFillColor({200, 0, 0});
|
||||
else
|
||||
circle.setFillColor({0, 0, 200});
|
||||
window.draw(circle);
|
||||
}
|
||||
|
||||
window.display();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
1
term1/seminar09_libraries/final
Symbolic link
1
term1/seminar09_libraries/final
Symbolic link
|
@ -0,0 +1 @@
|
|||
07_n_bodies_charges_mouse
|
BIN
term1/seminar09_libraries/homework_libraries.pdf
Normal file
BIN
term1/seminar09_libraries/homework_libraries.pdf
Normal file
Binary file not shown.
9
term1/seminar11_events/01_select_move_delete/Makefile
Normal file
9
term1/seminar11_events/01_select_move_delete/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
|||
#path = ../../../3rdparty/SFML-2.5.1
|
||||
#select_move_delete:
|
||||
# g++ ./select_move_delete.cpp -std=c++11 -o select_move_delete.exe -I $(path)/include -L $(path)/lib/ -lsfml-graphics -lsfml-window -lsfml-system
|
||||
#select_move_delete:
|
||||
# g++ ./select_move_delete.cpp -std=c++11 -o select_move_delete.exe -I $(path)/include -L $(path)/lib/ -lsfml-graphics -lsfml-window -lsfml-system
|
||||
build:
|
||||
g++ ./select_move_delete.cpp -std=c++11 -o select_move_delete -lsfml-graphics -lsfml-window -lsfml-system
|
||||
build_debug:
|
||||
g++ ./select_move_delete.cpp -std=c++11 -o select_move_delete -lsfml-graphics -lsfml-window -lsfml-system -D_DEBUG
|
BIN
term1/seminar11_events/01_select_move_delete/consolas.ttf
Normal file
BIN
term1/seminar11_events/01_select_move_delete/consolas.ttf
Normal file
Binary file not shown.
143
term1/seminar11_events/01_select_move_delete/context_menu.hpp
Normal file
143
term1/seminar11_events/01_select_move_delete/context_menu.hpp
Normal file
|
@ -0,0 +1,143 @@
|
|||
#pragma once
|
||||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
|
||||
/*
|
||||
Класс ContextMenu - контекстное меню
|
||||
При нажатии правой кнопки мыши на экране появляется контекстное меню
|
||||
|
||||
Публичные методы:
|
||||
ContextMenu(sf::RenderWindow&, const sf::Font&)
|
||||
Конструктор принимает окно для отрисовки и шрифт
|
||||
|
||||
void addButton(const sf::String& name)
|
||||
Добавить новый элемент в контекстное меню по имени name
|
||||
|
||||
void draw()
|
||||
Нарисовать контекстное меню в окне, которое было передано в конструктор
|
||||
|
||||
int handleEvent(const sf::Event& event)
|
||||
Обрабатывает событие event и возвращает целое число
|
||||
Если это событие MousePressed и был выбран один из вариантов
|
||||
контекстного меню, то вернёт номер этого варианта
|
||||
Нумерация начинается с нуля
|
||||
В ином случае вернёт -1
|
||||
|
||||
*/
|
||||
|
||||
|
||||
class ContextMenu
|
||||
{
|
||||
private:
|
||||
inline static const sf::Color kDefaultColor {sf::Color(190, 210, 190)};
|
||||
inline static const sf::Color kHoverColor {sf::Color(150, 170, 150)};
|
||||
inline static const sf::Color kTextColor {sf::Color::Black};
|
||||
inline static const int kButtonHeight = 20;
|
||||
inline static const int kCharacterSize = 16;
|
||||
inline static const float kMenuWidthMultiplier = 1.2;
|
||||
|
||||
sf::RenderWindow& mRenderWindow;
|
||||
sf::RectangleShape mShape;
|
||||
sf::RectangleShape mHoverShape;
|
||||
sf::Text mText;
|
||||
std::vector<sf::String> mButtons;
|
||||
|
||||
bool mIsOpened = false;
|
||||
bool mIsUpdated = false;
|
||||
int mHoverPosition = -1;
|
||||
|
||||
int onMousePressed(const sf::Event& event)
|
||||
{
|
||||
if (event.mouseButton.button == sf::Mouse::Right) {
|
||||
mIsOpened = true;
|
||||
sf::Vector2f mousePosition = mRenderWindow.mapPixelToCoords({event.mouseButton.x, event.mouseButton.y});
|
||||
mShape.setPosition(mousePosition);
|
||||
}
|
||||
if (event.mouseButton.button == sf::Mouse::Left && mIsOpened) {
|
||||
mIsOpened = false;
|
||||
return mHoverPosition;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void onMouseMove(const sf::Event& event)
|
||||
{
|
||||
if (!mIsOpened) {
|
||||
return;
|
||||
}
|
||||
sf::Vector2f mousePosition = mRenderWindow.mapPixelToCoords({event.mouseMove.x, event.mouseMove.y});
|
||||
if (mShape.getGlobalBounds().contains(mousePosition)) {
|
||||
mHoverPosition = (mousePosition.y - mShape.getPosition().y) / kButtonHeight;
|
||||
}
|
||||
else {
|
||||
mHoverPosition = -1;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
ContextMenu(sf::RenderWindow& window, const sf::Font& font) : mRenderWindow(window)
|
||||
{
|
||||
mText.setFont(font);
|
||||
mText.setCharacterSize(kCharacterSize);
|
||||
mText.setFillColor(kTextColor);
|
||||
mShape.setFillColor(kDefaultColor);
|
||||
mHoverShape.setFillColor(kHoverColor);
|
||||
|
||||
mIsOpened = false;
|
||||
mIsUpdated = false;
|
||||
mHoverPosition = -1;
|
||||
}
|
||||
|
||||
void addButton(const sf::String& name)
|
||||
{
|
||||
mButtons.push_back(name);
|
||||
mIsUpdated = false;
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
if (!mIsOpened) {
|
||||
return;
|
||||
}
|
||||
// Если добавили новый вариант, то её текст может быть длиннее
|
||||
// чем у других. Нужно расширить прямоугольники.
|
||||
if (!mIsUpdated) {
|
||||
int maxSizeX = 0;
|
||||
for (int i = 0; i < mButtons.size(); i++) {
|
||||
mText.setString(mButtons[i]);
|
||||
if (mText.getLocalBounds().width > maxSizeX) {
|
||||
maxSizeX = mText.getLocalBounds().width;
|
||||
}
|
||||
}
|
||||
maxSizeX *= kMenuWidthMultiplier;
|
||||
mShape.setSize({(float)maxSizeX, (float)(kButtonHeight * mButtons.size())});
|
||||
mHoverShape.setSize({(float)maxSizeX, (float)(kButtonHeight)});
|
||||
mIsUpdated = true;
|
||||
}
|
||||
|
||||
|
||||
mRenderWindow.draw(mShape);
|
||||
if (mHoverPosition >= 0){
|
||||
mHoverShape.setPosition(mShape.getPosition().x, mShape.getPosition().y + mHoverPosition * kButtonHeight);
|
||||
mRenderWindow.draw(mHoverShape);
|
||||
}
|
||||
for (int i = 0; i < mButtons.size(); i++) {
|
||||
mText.setString(mButtons[i]);
|
||||
mText.setPosition(mShape.getPosition().x, mShape.getPosition().y + i * kButtonHeight);
|
||||
mRenderWindow.draw(mText);
|
||||
}
|
||||
}
|
||||
|
||||
int handleEvent(const sf::Event& event) {
|
||||
if (event.type == sf::Event::MouseMoved) {
|
||||
onMouseMove(event);
|
||||
}
|
||||
else if (event.type == sf::Event::MouseButtonPressed) {
|
||||
return onMousePressed(event);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,287 @@
|
|||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <list>
|
||||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "context_menu.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
float distance(sf::Vector2f start, sf::Vector2f finish)
|
||||
{
|
||||
return sqrtf((start.x - finish.x)*(start.x - finish.x) + (start.y - finish.y)*(start.y - finish.y));
|
||||
}
|
||||
|
||||
void drawLine(sf::RenderWindow& window, sf::Vector2f start, sf::Vector2f finish, sf::Color color = sf::Color::White)
|
||||
{
|
||||
sf::Vertex line_vertices[2] = {sf::Vertex(start, color), sf::Vertex(finish, color)};
|
||||
window.draw(line_vertices, 2, sf::Lines);
|
||||
}
|
||||
|
||||
struct Ball
|
||||
{
|
||||
sf::Vector2f position;
|
||||
float radius;
|
||||
bool isChoosen;
|
||||
sf::Color color;
|
||||
|
||||
Ball(sf::Vector2f position, float radius, sf::Color color = sf::Color::White) : position(position), radius(radius), color(color)
|
||||
{
|
||||
isChoosen = false;
|
||||
}
|
||||
|
||||
void draw(sf::RenderWindow& window) const
|
||||
{
|
||||
sf::CircleShape circle(radius);
|
||||
circle.setFillColor(color);
|
||||
circle.setOrigin({radius, radius});
|
||||
circle.setPosition(position);
|
||||
window.draw(circle);
|
||||
|
||||
if (isChoosen) {
|
||||
const float fraction = 0.7;
|
||||
drawLine(window, {position.x - radius, position.y + radius}, {position.x - radius, position.y + radius*fraction});
|
||||
drawLine(window, {position.x - radius, position.y + radius}, {position.x - fraction * radius, position.y + radius});
|
||||
|
||||
drawLine(window, {position.x + radius, position.y + radius}, {position.x + radius, position.y + radius*fraction});
|
||||
drawLine(window, {position.x + radius, position.y + radius}, {position.x + radius*fraction, position.y + radius});
|
||||
|
||||
drawLine(window, {position.x + radius, position.y - radius}, {position.x + radius*fraction, position.y - radius});
|
||||
drawLine(window, {position.x + radius, position.y - radius}, {position.x + radius, position.y - radius*fraction});
|
||||
|
||||
drawLine(window, {position.x - radius, position.y - radius}, {position.x - radius*fraction, position.y - radius});
|
||||
drawLine(window, {position.x - radius, position.y - radius}, {position.x - radius, position.y - radius*fraction});
|
||||
}
|
||||
}
|
||||
void setColor(sf::Uint8 r, sf::Uint8 g, sf::Uint8 b, sf::Uint8 a = 255) {
|
||||
color.r = r;
|
||||
color.g = g;
|
||||
color.b = b;
|
||||
color.a = a;
|
||||
}
|
||||
};
|
||||
|
||||
void deleteChoosen(list<Ball>& balls) {
|
||||
for (list<Ball>::const_iterator it = balls.begin(); it != balls.end();) {
|
||||
if (it->isChoosen)
|
||||
it = balls.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void copyBalls(list<Ball>& balls, list<Ball>& buffer) {
|
||||
buffer.clear();
|
||||
for (list<Ball>::iterator it = balls.begin(); it != balls.end(); ++it)
|
||||
if (it->isChoosen)
|
||||
buffer.push_back(*it);
|
||||
}
|
||||
|
||||
void pasteBalls(list<Ball>& balls, list<Ball>& buffer) {
|
||||
for (list<Ball>::iterator it = buffer.begin(); it != buffer.end(); ++it)
|
||||
balls.push_back(*it);
|
||||
}
|
||||
|
||||
void recolorChoosen(list<Ball>& balls) {
|
||||
for (Ball& b : balls)
|
||||
if (b.isChoosen)
|
||||
b.setColor(rand() % 255, rand() % 255, rand() % 255);
|
||||
}
|
||||
|
||||
void resizeChoosen(list<Ball>& balls, double scaling) {
|
||||
for (list<Ball>::iterator it = balls.begin(); it != balls.end(); ++it) {
|
||||
if (it->isChoosen)
|
||||
it->radius += it->radius * scaling;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
sf::ContextSettings settings;
|
||||
settings.antialiasingLevel = 8;
|
||||
sf::RenderWindow window(sf::VideoMode(800, 600), "Select, Move, Delete!", sf::Style::Default, settings);
|
||||
window.setFramerateLimit(60);
|
||||
|
||||
std::list<Ball> balls;
|
||||
balls.push_back(Ball({200, 200}, 26));
|
||||
balls.push_back(Ball({400, 300}, 20));
|
||||
balls.push_back(Ball({500, 100}, 16));
|
||||
balls.push_back(Ball({200, 400}, 18));
|
||||
balls.push_back(Ball({350, 150}, 22));
|
||||
balls.push_back(Ball({750, 400}, 21));
|
||||
|
||||
list<Ball> buffer{};
|
||||
|
||||
sf::RectangleShape selectionRect;
|
||||
selectionRect.setFillColor(sf::Color(150, 150, 240, 50));
|
||||
selectionRect.setOutlineColor(sf::Color(200, 200, 255));
|
||||
selectionRect.setOutlineThickness(1);
|
||||
|
||||
bool isSelecting = false;
|
||||
/* "Режим выделения" */
|
||||
bool isMovingMode = false;
|
||||
/* Необходимо, чтоб в режиме выделения считать смещение */
|
||||
Ball* selected_ball = nullptr;
|
||||
|
||||
bool isContextMenu = false;
|
||||
|
||||
sf::Vector2f mousePosition{};
|
||||
|
||||
sf::Font font;
|
||||
if (!font.loadFromFile("consolas.ttf")) {
|
||||
std::cout << "Can't load button font" << std::endl;
|
||||
}
|
||||
|
||||
std::vector<sf::String> contextMenuStrings {"Delete", "Create", "Random Color", "Increase", "Decrease", "Copy", "Cut", "Paste"};
|
||||
ContextMenu contextMenu(window, font);
|
||||
for (const auto& el : contextMenuStrings) {
|
||||
contextMenu.addButton(el);
|
||||
}
|
||||
|
||||
while (window.isOpen()) {
|
||||
sf::Event event;
|
||||
while (window.pollEvent(event)) {
|
||||
if (event.type == sf::Event::Closed) {
|
||||
window.close();
|
||||
}
|
||||
int result = contextMenu.handleEvent(event);
|
||||
switch(result) {
|
||||
case 0:
|
||||
deleteChoosen(balls);
|
||||
break;
|
||||
case 1:
|
||||
mousePosition = window.mapPixelToCoords({event.mouseButton.x, event.mouseButton.y});
|
||||
balls.push_back(Ball(mousePosition, 5 + rand() % 40));
|
||||
break;
|
||||
case 2:
|
||||
recolorChoosen(balls);
|
||||
break;
|
||||
case 3:
|
||||
resizeChoosen(balls, 0.25);
|
||||
break;
|
||||
case 4:
|
||||
resizeChoosen(balls, -0.25);
|
||||
break;
|
||||
case 5:
|
||||
copyBalls(balls, buffer);
|
||||
break;
|
||||
case 6:
|
||||
copyBalls(balls, buffer);
|
||||
deleteChoosen(balls);
|
||||
break;
|
||||
case 7:
|
||||
pasteBalls(balls, buffer);
|
||||
break;
|
||||
}
|
||||
if (event.type == sf::Event::MouseMoved) {
|
||||
mousePosition = window.mapPixelToCoords({event.mouseMove.x, event.mouseMove.y});
|
||||
|
||||
// Если мы находимся в режиме выделения и не попали в уже выделенный шарик, то меняем прямоугольник выделения
|
||||
if (isSelecting & !isMovingMode) {
|
||||
selectionRect.setSize(mousePosition - selectionRect.getPosition());
|
||||
}
|
||||
// Если в режиме перемещения, то двигаем все выделенные шарики
|
||||
if (isMovingMode) {
|
||||
sf::Vector2f direction = selected_ball->position - mousePosition;
|
||||
for (Ball& b : balls) {
|
||||
if (b.isChoosen) {
|
||||
b.position -= direction;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type == sf::Event::MouseButtonPressed) {
|
||||
mousePosition = window.mapPixelToCoords({event.mouseButton.x, event.mouseButton.y});
|
||||
if (event.mouseButton.button == sf::Mouse::Left) {
|
||||
for (Ball& b : balls) {
|
||||
/* Если попали в какой-то шарик */
|
||||
if (distance(mousePosition, b.position) < b.radius) {
|
||||
selected_ball = &b;
|
||||
// Если попали в еще не выбранный шарик и не зажат левый Ctrl, то снимаем выделение со всех остальных
|
||||
if(!b.isChoosen && !sf::Keyboard::isKeyPressed(sf::Keyboard::LControl)) {
|
||||
for (Ball& ball : balls) {
|
||||
ball.isChoosen = false;
|
||||
}
|
||||
}
|
||||
b.isChoosen = true; //
|
||||
isMovingMode = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// ЛКМ + левый Alt - добавляем новый случайный шарик
|
||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt)) {
|
||||
balls.push_back(Ball(mousePosition, 5 + rand() % 40));
|
||||
}
|
||||
// Задаём новое положения прямоугольника выделения
|
||||
if (!isMovingMode) {
|
||||
isSelecting = true;
|
||||
selectionRect.setPosition(mousePosition);
|
||||
selectionRect.setSize({0, 0});
|
||||
}
|
||||
}
|
||||
if (event.mouseButton.button == sf::Mouse::Right) {
|
||||
isContextMenu = true;
|
||||
}
|
||||
}
|
||||
// При отпускании кнопки мыши выходим из режима выделения
|
||||
if (event.type == sf::Event::MouseButtonReleased) {
|
||||
// Если не зажат левый Ctrl и не в режиме перемещения шариков, то все выделения снимаются
|
||||
if (!sf::Keyboard::isKeyPressed(sf::Keyboard::LControl) && !isMovingMode && !isContextMenu) {
|
||||
for (Ball& b : balls) {
|
||||
b.isChoosen = false;
|
||||
}
|
||||
}
|
||||
if (isSelecting) {
|
||||
sf::Vector2f size = selectionRect.getSize();
|
||||
sf::Vector2f position = selectionRect.getPosition();
|
||||
for (Ball& b : balls) {
|
||||
if ( ((b.position.x - b.radius > position.x) && (b.position.x + b.radius < position.x + size.x)) ||
|
||||
((b.position.x + b.radius < position.x) && (b.position.x - b.radius > position.x + size.x))
|
||||
)
|
||||
if (((b.position.y - b.radius > position.y) && (b.position.y + b.radius < position.y + size.y)) ||
|
||||
((b.position.y + b.radius < position.y) && (b.position.y - b.radius > position.y + size.y))
|
||||
)
|
||||
b.isChoosen = true;
|
||||
}
|
||||
}
|
||||
isSelecting = false;
|
||||
isMovingMode = false;
|
||||
isContextMenu = false;
|
||||
}
|
||||
|
||||
if (event.type == sf::Event::KeyPressed) {
|
||||
if (event.key.code == sf::Keyboard::C)
|
||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl))
|
||||
copyBalls(balls, buffer);
|
||||
if (event.key.code == sf::Keyboard::V)
|
||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl))
|
||||
pasteBalls(balls, buffer);
|
||||
if (event.key.code == sf::Keyboard::X)
|
||||
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LControl)) {
|
||||
copyBalls(balls, buffer);
|
||||
deleteChoosen(balls);
|
||||
}
|
||||
if (event.key.code == sf::Keyboard::Space)
|
||||
recolorChoosen(balls);
|
||||
if (event.key.code == sf::Keyboard::Delete) {
|
||||
deleteChoosen(balls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.clear(sf::Color::Black);
|
||||
// Рисуем все шарики
|
||||
for (Ball& b : balls) {
|
||||
b.draw(window);
|
||||
}
|
||||
// Рисуем прямоугольник выделения
|
||||
if (isSelecting) {
|
||||
window.draw(selectionRect);
|
||||
}
|
||||
contextMenu.draw();
|
||||
window.display();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
11
term1/seminar11_events/01_select_move_delete/tags
Normal file
11
term1/seminar11_events/01_select_move_delete/tags
Normal file
|
@ -0,0 +1,11 @@
|
|||
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
||||
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
||||
!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/
|
||||
!_TAG_OUTPUT_FILESEP slash /slash or backslash/
|
||||
!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/
|
||||
!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/
|
||||
!_TAG_PROC_CWD /home/nihonium/projects/mipt_cpp/seminar11_events/01_select_move_delete/ //
|
||||
!_TAG_PROGRAM_AUTHOR Universal Ctags Team //
|
||||
!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/
|
||||
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
|
||||
!_TAG_PROGRAM_VERSION 5.9.0 /p5.9.20220828.0/
|
6
term1/seminar11_events/02_slider/Makefile
Normal file
6
term1/seminar11_events/02_slider/Makefile
Normal file
|
@ -0,0 +1,6 @@
|
|||
build:
|
||||
g++ ./slider.cpp -std=c++11 -o slider -lsfml-graphics -lsfml-window -lsfml-system
|
||||
build_debug:
|
||||
g++ ./slider.cpp -std=c++11 -o slider -lsfml-graphics -lsfml-window -lsfml-system -D_DEBUG
|
||||
build_circle:
|
||||
g++ ./circle.cpp -std=c++11 -o circle -lsfml-graphics -lsfml-window -lsfml-system
|
57
term1/seminar11_events/02_slider/circle.cpp
Normal file
57
term1/seminar11_events/02_slider/circle.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
#include <iostream>
|
||||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "slider.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
int result;
|
||||
unsigned char r, g, b;
|
||||
|
||||
sf::RenderWindow window(sf::VideoMode(800, 600), "Slider");
|
||||
window.setFramerateLimit(60);
|
||||
|
||||
sf::Font font;
|
||||
if (!font.loadFromFile("consolas.ttf")) {
|
||||
std::cout << "Can't load button font" << std::endl;
|
||||
}
|
||||
|
||||
Slider slider(window, font, sf::Vector2f{200, 100}, 10, 250);
|
||||
|
||||
Slider slider_r(window, font, sf::Vector2f{800, 200}, 0, 255);
|
||||
Slider slider_g(window, font, sf::Vector2f{800, 300}, 0, 255);
|
||||
Slider slider_b(window, font, sf::Vector2f{800, 400}, 0, 255);
|
||||
|
||||
sf::CircleShape circle(10);
|
||||
circle.setPosition(sf::Vector2f{400, 400});
|
||||
|
||||
while (window.isOpen()) {
|
||||
sf::Event event;
|
||||
while (window.pollEvent(event)) {
|
||||
if (event.type == sf::Event::Closed) {
|
||||
window.close();
|
||||
}
|
||||
|
||||
result = slider.handleEvent(event);
|
||||
|
||||
/* Centering of the circle */
|
||||
circle.setPosition(circle.getPosition() + sf::Vector2f{circle.getRadius() - result, circle.getRadius() - result});
|
||||
circle.setRadius(result);
|
||||
|
||||
r = slider_r.handleEvent(event);
|
||||
g = slider_g.handleEvent(event);
|
||||
b = slider_b.handleEvent(event);
|
||||
circle.setFillColor(sf::Color{r, g, b});
|
||||
}
|
||||
window.clear(sf::Color::Black);
|
||||
|
||||
slider.draw();
|
||||
slider_r.draw();
|
||||
slider_g.draw();
|
||||
slider_b.draw();
|
||||
|
||||
window.draw(circle);
|
||||
window.display();
|
||||
}
|
||||
return 0;
|
||||
}
|
BIN
term1/seminar11_events/02_slider/consolas.ttf
Normal file
BIN
term1/seminar11_events/02_slider/consolas.ttf
Normal file
Binary file not shown.
36
term1/seminar11_events/02_slider/slider.cpp
Normal file
36
term1/seminar11_events/02_slider/slider.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include <iostream>
|
||||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "slider.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
int result;
|
||||
|
||||
sf::RenderWindow window(sf::VideoMode(800, 600), "Slider");
|
||||
window.setFramerateLimit(60);
|
||||
|
||||
sf::Font font;
|
||||
if (!font.loadFromFile("consolas.ttf")) {
|
||||
std::cout << "Can't load button font" << std::endl;
|
||||
}
|
||||
|
||||
Slider slider(window, font);
|
||||
|
||||
while (window.isOpen()) {
|
||||
sf::Event event;
|
||||
while (window.pollEvent(event)) {
|
||||
if (event.type == sf::Event::Closed) {
|
||||
window.close();
|
||||
}
|
||||
|
||||
result = slider.handleEvent(event);
|
||||
std::cout << result << std::endl;
|
||||
}
|
||||
window.clear(sf::Color::Black);
|
||||
|
||||
slider.draw();
|
||||
window.display();
|
||||
}
|
||||
return 0;
|
||||
}
|
113
term1/seminar11_events/02_slider/slider.hpp
Normal file
113
term1/seminar11_events/02_slider/slider.hpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
#pragma once
|
||||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <sstream>
|
||||
|
||||
class Slider
|
||||
{
|
||||
private:
|
||||
const int kCharacterSize = 14;
|
||||
|
||||
int mMinValue;
|
||||
int mMaxValue;
|
||||
float mSliderPosition = 0;
|
||||
|
||||
sf::RenderWindow& mRenderWindow;
|
||||
sf::RectangleShape mSlider;
|
||||
sf::RectangleShape mAxis;
|
||||
sf::Text mText;
|
||||
|
||||
bool mIsPressed = false;
|
||||
|
||||
void onMousePressed(const sf::Event& event)
|
||||
{
|
||||
if (event.mouseButton.button == sf::Mouse::Left) {
|
||||
sf::Vector2f mousePosition = mRenderWindow.mapPixelToCoords({event.mouseButton.x, event.mouseButton.y});
|
||||
if (mSlider.getGlobalBounds().contains(mousePosition))
|
||||
mIsPressed = true;
|
||||
else if (mAxis.getGlobalBounds().contains(mousePosition))
|
||||
{
|
||||
mIsPressed = true;
|
||||
if (mousePosition.x + mSlider.getSize().x <= mAxis.getPosition().x + mAxis.getSize().x) {
|
||||
mSlider.setPosition({mousePosition.x, mSlider.getPosition().y});
|
||||
mSliderPosition = (mSlider.getPosition().x - mAxis.getPosition().x) / (mAxis.getSize().x - mSlider.getSize().x);
|
||||
}
|
||||
else {
|
||||
mSlider.setPosition({mAxis.getPosition().x + mAxis.getSize().x - mSlider.getSize().x, mSlider.getPosition().y});
|
||||
mSliderPosition = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onMouseMove(const sf::Event& event)
|
||||
{
|
||||
if (!mIsPressed) {
|
||||
return;
|
||||
}
|
||||
sf::Vector2f mousePosition = mRenderWindow.mapPixelToCoords({event.mouseMove.x, event.mouseMove.y});
|
||||
if ((mousePosition.x >= mAxis.getPosition().x) && (mousePosition.x + mSlider.getSize().x <= mAxis.getPosition().x + mAxis.getSize().x)) {
|
||||
mSlider.setPosition({mousePosition.x, mSlider.getPosition().y});
|
||||
}
|
||||
else if (mousePosition.x < mAxis.getPosition().x) {
|
||||
mSlider.setPosition({mAxis.getPosition().x, mSlider.getPosition().y});
|
||||
}
|
||||
else if (mousePosition.x + mSlider.getSize().x > mAxis.getPosition().x + mAxis.getSize().x) {
|
||||
mSlider.setPosition({mAxis.getPosition().x + mAxis.getSize().x - mSlider.getSize().x, mSlider.getPosition().y});
|
||||
}
|
||||
|
||||
mSliderPosition = (mSlider.getPosition().x - mAxis.getPosition().x) / (mAxis.getSize().x - mSlider.getSize().x);
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Slider(sf::RenderWindow& window, const sf::Font& font, sf::Vector2f position = {100,200},int min = 0, int max = 100) : mRenderWindow(window)
|
||||
{
|
||||
mSlider.setFillColor(sf::Color::Red);
|
||||
mSlider.setSize({10,30});
|
||||
mSlider.setPosition(position - sf::Vector2f{0, 10});
|
||||
mSlider.setOutlineColor(sf::Color::Black);
|
||||
mSlider.setOutlineThickness(2);
|
||||
|
||||
mAxis.setFillColor(sf::Color::White);
|
||||
mAxis.setSize({500,10});
|
||||
mAxis.setPosition(position);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << mMinValue;
|
||||
mText.setString(ss.str());
|
||||
mText.setFont(font);
|
||||
mText.setCharacterSize(kCharacterSize);
|
||||
mText.setFillColor(sf::Color::White);
|
||||
mText.setPosition(position + sf::Vector2f{mAxis.getSize().x + 10, -4});
|
||||
|
||||
mMinValue = min;
|
||||
mMaxValue = max;
|
||||
mIsPressed = false;
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << mMinValue + (mMaxValue - mMinValue) * mSliderPosition;
|
||||
mText.setString(ss.str());
|
||||
|
||||
mRenderWindow.draw(mAxis);
|
||||
mRenderWindow.draw(mSlider);
|
||||
mRenderWindow.draw(mText);
|
||||
}
|
||||
|
||||
int handleEvent(const sf::Event& event) {
|
||||
if (event.type == sf::Event::MouseMoved) {
|
||||
onMouseMove(event);
|
||||
}
|
||||
else if (event.type == sf::Event::MouseButtonPressed) {
|
||||
onMousePressed(event);
|
||||
}
|
||||
else if (event.type == sf::Event::MouseButtonReleased) {
|
||||
mIsPressed = false;
|
||||
}
|
||||
return mMinValue + (mMaxValue - mMinValue) * mSliderPosition;
|
||||
}
|
||||
};
|
11
term1/seminar11_events/02_slider/tags
Normal file
11
term1/seminar11_events/02_slider/tags
Normal file
|
@ -0,0 +1,11 @@
|
|||
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
||||
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
||||
!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/
|
||||
!_TAG_OUTPUT_FILESEP slash /slash or backslash/
|
||||
!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/
|
||||
!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/
|
||||
!_TAG_PROC_CWD /home/nihonium/projects/mipt_cpp/seminar11_events/02_slider/ //
|
||||
!_TAG_PROGRAM_AUTHOR Universal Ctags Team //
|
||||
!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/
|
||||
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
|
||||
!_TAG_PROGRAM_VERSION 5.9.0 /p5.9.20220828.0/
|
BIN
term1/seminar11_events/homework_events.pdf
Normal file
BIN
term1/seminar11_events/homework_events.pdf
Normal file
Binary file not shown.
3
term1/seminar13_polymorphism/arkanoid/Makefile
Normal file
3
term1/seminar13_polymorphism/arkanoid/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
path = ../../../../3rdparty/SFML-2.5.1
|
||||
arkanoid:
|
||||
g++ -Wall -Wextra arkanoid.cpp bonus.cpp main.cpp ball.cpp brick_grid.cpp paddle.cpp -std=c++17 -o arkanoid -lsfml-graphics -lsfml-window -lsfml-system
|
BIN
term1/seminar13_polymorphism/arkanoid/arkanoid
Executable file
BIN
term1/seminar13_polymorphism/arkanoid/arkanoid
Executable file
Binary file not shown.
258
term1/seminar13_polymorphism/arkanoid/arkanoid.cpp
Normal file
258
term1/seminar13_polymorphism/arkanoid/arkanoid.cpp
Normal file
|
@ -0,0 +1,258 @@
|
|||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include <list>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include "arkanoid.hpp"
|
||||
#include "bonus.hpp"
|
||||
|
||||
const double pi = 3.14159265358979323846;
|
||||
|
||||
void Arkanoid::addRandomBonus(sf::Vector2f position)
|
||||
{
|
||||
if (m_bonuses.size() > kMaxNumBonuses)
|
||||
return;
|
||||
int max_rand = 10000;
|
||||
if ((rand() % max_rand) * 1.0f / max_rand < m_bonusProbability)
|
||||
{
|
||||
int max = 4; int min = 1;
|
||||
int range = max - min + 1;
|
||||
int num = rand() % range + min;
|
||||
switch (num) {
|
||||
case 1:
|
||||
m_bonuses.push_back(new TripleBallBonus(position));
|
||||
break;
|
||||
case 2:
|
||||
m_bonuses.push_back(new EnlargePaddleBonus(position));
|
||||
break;
|
||||
case 3:
|
||||
m_bonuses.push_back(new ShrinkPaddleBonus(position));
|
||||
break;
|
||||
case 4:
|
||||
m_bonuses.push_back(new SlowingBonus(position));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Функция, которая обрабатывает все столкновения шарика
|
||||
void Arkanoid::handleBallCollisions(Ball& ball)
|
||||
{
|
||||
ball.handleWallsCollision(m_border);
|
||||
ball.handlePaddleCollision(m_paddle);
|
||||
|
||||
auto indexes = ball.handleBrickGridCollision(m_brickGrid);
|
||||
if (indexes.first == -1)
|
||||
return;
|
||||
m_brickGrid.deactivateBrick(indexes);
|
||||
addRandomBonus(ball.position);
|
||||
}
|
||||
|
||||
|
||||
Arkanoid::Arkanoid(sf::FloatRect border, sf::Font& font) :
|
||||
m_time{0.0},
|
||||
m_border{border},
|
||||
m_paddle{{m_border.left + m_border.width / 2, m_border.top + m_border.height - 100}, {120, 20}},
|
||||
m_gameState{GameState::stuck},
|
||||
m_numLives{7}
|
||||
{
|
||||
float gap = border.width / 10;
|
||||
m_brickGrid = BrickGrid({border.left + gap, border.top + gap, border.width - 2 * gap, border.height / 2}, 50, 30);
|
||||
m_bonusProbability = 0.1;
|
||||
|
||||
m_endText.setFont(font);
|
||||
m_endText.setString("You Win!");
|
||||
m_endText.setCharacterSize(100);
|
||||
m_endText.setFillColor(sf::Color::White);
|
||||
sf::FloatRect textRect = m_endText.getLocalBounds();
|
||||
m_endText.setOrigin(textRect.left + textRect.width / 2.0f, textRect.top + textRect.height / 2.0f);
|
||||
m_endText.setPosition({border.left + border.width / 2, border.top + border.height / 2});
|
||||
}
|
||||
|
||||
sf::FloatRect Arkanoid::getBorder() const
|
||||
{
|
||||
return m_border;
|
||||
}
|
||||
|
||||
const Paddle& Arkanoid::getPaddle() const
|
||||
{
|
||||
return m_paddle;
|
||||
}
|
||||
|
||||
const BrickGrid& Arkanoid::getBrickGrid() const
|
||||
{
|
||||
return m_brickGrid;
|
||||
}
|
||||
|
||||
void Arkanoid::addBall(const Ball& ball)
|
||||
{
|
||||
if (m_balls.size() < kMaxNumBalls)
|
||||
m_balls.push_back(ball);
|
||||
}
|
||||
|
||||
bool Arkanoid::isMaxBalls()
|
||||
{
|
||||
return m_balls.size() == kMaxNumBalls - 1;
|
||||
}
|
||||
|
||||
// Эта функция вызывается каждый кадр
|
||||
void Arkanoid::update(const sf::RenderWindow& window, float dt)
|
||||
{
|
||||
m_time += dt;
|
||||
|
||||
// Устанавливаем положение ракетки
|
||||
sf::Vector2f mousePosition = window.mapPixelToCoords(sf::Mouse::getPosition(window));
|
||||
m_paddle.position.x = mousePosition.x;
|
||||
|
||||
// Обрабатываем шарики
|
||||
for (std::list<Ball>::iterator it = m_balls.begin(); it != m_balls.end();)
|
||||
{
|
||||
(*it).update(dt);
|
||||
handleBallCollisions(*it);
|
||||
if ((*it).position.y > m_border.top + m_border.height)
|
||||
{
|
||||
it = m_balls.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
// Если шариков нет, то переходи в режим начала игры и уменьшаем кол-во жизней
|
||||
if (m_gameState == GameState::running && m_balls.size() == 0)
|
||||
{
|
||||
m_effects.clear();
|
||||
m_gameState = GameState::stuck;
|
||||
m_numLives--;
|
||||
}
|
||||
|
||||
// Если жизни кончились, то переходим в состояние конца игры (проигрыш)
|
||||
if (m_numLives < 0)
|
||||
{
|
||||
m_gameState = GameState::endLose;
|
||||
}
|
||||
|
||||
// Если блоки кончились, то переходим в состояние конца игры (победа)
|
||||
if (m_brickGrid.getNumActiveBricks() == 0)
|
||||
{
|
||||
m_gameState = GameState::endWin;
|
||||
}
|
||||
|
||||
// Обрабатываем бонусы
|
||||
for (auto it = m_bonuses.begin(); it != m_bonuses.end();)
|
||||
{
|
||||
(*it)->update(dt);
|
||||
if ((*it)->isColiding(m_paddle))
|
||||
{
|
||||
(*it)->activate(*this);
|
||||
delete *it;
|
||||
it = m_bonuses.erase(it);
|
||||
}
|
||||
else if ((*it)->m_position.y > m_border.top + m_border.height)
|
||||
{
|
||||
delete (*it);
|
||||
it = m_bonuses.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
|
||||
}
|
||||
/* Обработка эффектов */
|
||||
for (auto it = m_effects.begin(); it != m_effects.end();)
|
||||
{
|
||||
if ((*it)->isExpired(m_time))
|
||||
{
|
||||
(*it)->deactivate(*this);
|
||||
delete *it;
|
||||
it = m_effects.erase(it);
|
||||
}
|
||||
else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arkanoid::draw(sf::RenderWindow& window)
|
||||
{
|
||||
// Рисуем задний прямоугольник
|
||||
static sf::RectangleShape background {{m_border.width, m_border.height}};
|
||||
background.setPosition({m_border.left, m_border.top});
|
||||
background.setFillColor(kBackgroundColor);
|
||||
window.draw(background);
|
||||
|
||||
// Рисуем блоки
|
||||
m_brickGrid.draw(window);
|
||||
|
||||
// Рисуем шарики
|
||||
for (Ball& ball : m_balls)
|
||||
{
|
||||
ball.draw(window);
|
||||
}
|
||||
|
||||
// Рисуем ракетку
|
||||
m_paddle.draw(window);
|
||||
|
||||
// Если мы в режиме начала игры, то рисуем шарик на ракетке
|
||||
if (m_gameState == GameState::stuck)
|
||||
{
|
||||
m_initialBall.position = {m_paddle.position.x, m_paddle.position.y - m_paddle.size.y / 2 - m_initialBall.radius};
|
||||
m_initialBall.position = {m_paddle.position.x, m_paddle.position.y - m_paddle.size.y / 2 - m_initialBall.radius};
|
||||
m_initialBall.draw(window);
|
||||
}
|
||||
|
||||
// Рисуем кол-во жизней вверху слева
|
||||
for (int i = 0; i < m_numLives; i++)
|
||||
{
|
||||
m_initialBall.position = {m_initialBall.radius * (3 * i + 2), 2 * m_initialBall.radius};
|
||||
m_initialBall.draw(window);
|
||||
}
|
||||
|
||||
// Рисуем бонусы
|
||||
for (Bonus* pbonus : m_bonuses)
|
||||
{
|
||||
pbonus->draw(window);
|
||||
}
|
||||
|
||||
// При завершении игры рисуем надпись
|
||||
if (m_gameState == GameState::endWin)
|
||||
{
|
||||
m_endText.setString("You Win!");
|
||||
window.draw(m_endText);
|
||||
}
|
||||
|
||||
// При завершении игры рисуем надпись
|
||||
if (m_gameState == GameState::endLose)
|
||||
{
|
||||
m_endText.setString("You Lose!");
|
||||
window.draw(m_endText);
|
||||
}
|
||||
}
|
||||
|
||||
void Arkanoid::onMousePressed(sf::Event& event)
|
||||
{
|
||||
switch (m_gameState)
|
||||
{
|
||||
case GameState::stuck:
|
||||
if (event.mouseButton.button == sf::Mouse::Left)
|
||||
{
|
||||
m_gameState = GameState::running;
|
||||
float velocityAngle = (rand() % 100 + 40) * pi / 180;
|
||||
float velocityNorm = Ball::initialVelocity;
|
||||
sf::Vector2f newPosition = {m_paddle.position.x, m_paddle.position.y - m_paddle.size.y / 2.0f - m_initialBall.radius};
|
||||
sf::Vector2f newVelocity = {-velocityNorm * cosf(velocityAngle), -velocityNorm * sinf(velocityAngle)};
|
||||
addBall({m_initialBall.radius, newPosition, newVelocity});
|
||||
}
|
||||
break;
|
||||
|
||||
case GameState::running:
|
||||
break;
|
||||
case GameState::endLose:
|
||||
break;
|
||||
case GameState::endWin:
|
||||
break;
|
||||
}
|
||||
}
|
85
term1/seminar13_polymorphism/arkanoid/arkanoid.hpp
Normal file
85
term1/seminar13_polymorphism/arkanoid/arkanoid.hpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
#pragma once
|
||||
#include <list>
|
||||
|
||||
#include "ball.hpp"
|
||||
#include "brick_grid.hpp"
|
||||
#include "paddle.hpp"
|
||||
class Bonus;
|
||||
class Effect;
|
||||
|
||||
class Arkanoid
|
||||
{
|
||||
private:
|
||||
// Константы:
|
||||
// Цвет задника
|
||||
const sf::Color kBackgroundColor {12, 31, 47};
|
||||
// Максимально возможное количество шариков в один момент времени
|
||||
const unsigned kMaxNumBalls {250};
|
||||
// Максимально возможное количество бонусов в один момент времени
|
||||
const unsigned kMaxNumBonuses {10};
|
||||
|
||||
// Время, которое прошло с начала игры в секундах
|
||||
double m_time;
|
||||
// Границы игрового поля
|
||||
sf::FloatRect m_border;
|
||||
// Связный список всех шариков
|
||||
std::list<Ball> m_balls;
|
||||
// Объект, задающий состояние сетки блоков
|
||||
BrickGrid m_brickGrid;
|
||||
// Ракетка
|
||||
Paddle m_paddle;
|
||||
// Состояние игры
|
||||
enum class GameState {stuck, running, endLose, endWin};
|
||||
GameState m_gameState;
|
||||
|
||||
// Текущее число жизней
|
||||
int m_numLives;
|
||||
|
||||
// Связный список указателей на бонусы
|
||||
// Почему указатели - для реализации полиформизма
|
||||
// Так как в будущем мы хотим сделать несколько вариантов бонусов
|
||||
std::list<Bonus*> m_bonuses;
|
||||
std::list<Effect*> m_effects;
|
||||
|
||||
// Вероятность того, что при разрушении блока выпадет бонус
|
||||
float m_bonusProbability;
|
||||
|
||||
// Макет шарика, используемый для рисова
|
||||
Ball m_initialBall {6, {0, 0}, {0, 0}};
|
||||
|
||||
// Текст, который рисуется в конце игры
|
||||
sf::Text m_endText;
|
||||
|
||||
|
||||
void addRandomBonus(sf::Vector2f position);
|
||||
|
||||
// Функция, которая обрабатывает все столкновения шарика
|
||||
void handleBallCollisions(Ball& ball);
|
||||
|
||||
public:
|
||||
Arkanoid(sf::FloatRect border, sf::Font& font);
|
||||
|
||||
sf::FloatRect getBorder() const;
|
||||
|
||||
const Paddle& getPaddle() const;
|
||||
|
||||
const BrickGrid& getBrickGrid() const;
|
||||
|
||||
void addBall(const Ball& ball);
|
||||
|
||||
// Эта функция вызывается каждый кадр
|
||||
void update(const sf::RenderWindow& window, float dt);
|
||||
|
||||
void draw(sf::RenderWindow& window);
|
||||
void onMousePressed(sf::Event& event);
|
||||
bool isMaxBalls();
|
||||
|
||||
// Класс бонус должен быть дружественным, так как он может менять внутреннее состояние игры
|
||||
friend class Bonus;
|
||||
friend class TripleBallBonus;
|
||||
friend class EnlargePaddleBonus;
|
||||
friend class ShrinkPaddleBonus;
|
||||
friend class SlowingBonus;
|
||||
|
||||
friend class SlowingEffect;
|
||||
};
|
183
term1/seminar13_polymorphism/arkanoid/ball.cpp
Normal file
183
term1/seminar13_polymorphism/arkanoid/ball.cpp
Normal file
|
@ -0,0 +1,183 @@
|
|||
#include <cmath>
|
||||
#include "ball.hpp"
|
||||
#include "brick_grid.hpp"
|
||||
#include "paddle.hpp"
|
||||
|
||||
// Вспомагательные функции для работы с векторами типа sf::Vector2f
|
||||
float operator*(const sf::Vector2f& first, const sf::Vector2f& second)
|
||||
{
|
||||
return first.x * second.x + first.y * second.y;
|
||||
}
|
||||
|
||||
float norm(sf::Vector2f a)
|
||||
{
|
||||
return std::sqrt(a.x * a.x + a.y * a.y);
|
||||
}
|
||||
|
||||
float sqnorm(sf::Vector2f a)
|
||||
{
|
||||
return a.x * a.x + a.y * a.y;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Ball::Ball(float radius, sf::Vector2f position, sf::Vector2f velocity) :
|
||||
radius(radius), position(position), velocity(velocity) {}
|
||||
|
||||
void Ball::update(float dt)
|
||||
{
|
||||
position += velocity * dt;
|
||||
}
|
||||
|
||||
void Ball::draw(sf::RenderWindow& window)
|
||||
{
|
||||
static sf::CircleShape shape {};
|
||||
shape.setRadius(radius);
|
||||
shape.setOrigin(radius, radius);
|
||||
shape.setFillColor(color);
|
||||
shape.setPosition(position);
|
||||
window.draw(shape);
|
||||
}
|
||||
|
||||
std::pair<sf::Vector2f, bool> Ball::findClosestPoint(const sf::FloatRect& rect) const
|
||||
{
|
||||
float left = rect.left;
|
||||
float right = rect.left + rect.width;
|
||||
float bottom = rect.top + rect.height;
|
||||
float top = rect.top;
|
||||
|
||||
sf::Vector2f d;
|
||||
if (position.x < left)
|
||||
d.x = left;
|
||||
else if (position.x > right)
|
||||
d.x = right;
|
||||
else
|
||||
d.x = position.x;
|
||||
|
||||
if (position.y > bottom)
|
||||
d.y = bottom;
|
||||
else if (position.y < top)
|
||||
d.y = top;
|
||||
else
|
||||
d.y = position.y;
|
||||
|
||||
d -= position;
|
||||
bool isColiding = sqnorm(d) < radius * radius;
|
||||
return {d, isColiding};
|
||||
}
|
||||
|
||||
bool Ball::handleRectCollision(const sf::FloatRect& rect)
|
||||
{
|
||||
auto [d, isColiding] = findClosestPoint(rect);
|
||||
if (!isColiding)
|
||||
return false;
|
||||
|
||||
float closestPointNorm = norm(d);
|
||||
// Если расстояние == 0, то это значит, что шарик за 1 фрейм зашёл центром внутрь блока
|
||||
// Отражаем шарик от блока
|
||||
if (closestPointNorm < 1e-4)
|
||||
{
|
||||
if (std::fabs(velocity.x) > std::fabs(velocity.y))
|
||||
velocity.x *= -1;
|
||||
else
|
||||
velocity.y *= -1;
|
||||
}
|
||||
// Если расстояние != 0, но шарик касается блока, то мы можем просчитать отражение более точно
|
||||
// Отражение от углов и по касательной.
|
||||
else if (closestPointNorm < radius)
|
||||
{
|
||||
position -= d * ((radius - closestPointNorm) / closestPointNorm);
|
||||
velocity -= 2.0f * d * (d * velocity) / (closestPointNorm * closestPointNorm);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Ball::handleWallsCollision(sf::FloatRect boundary)
|
||||
{
|
||||
if (position.x < boundary.left + radius)
|
||||
{
|
||||
position.x = boundary.left + radius;
|
||||
velocity.x *= -1;
|
||||
}
|
||||
if (position.x > boundary.left + boundary.width - radius)
|
||||
{
|
||||
position.x = boundary.left + boundary.width - radius;
|
||||
velocity.x *= -1;
|
||||
}
|
||||
if (position.y < boundary.top + radius)
|
||||
{
|
||||
position.y = boundary.top + radius;
|
||||
velocity.y *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::pair<int, int> Ball::handleBrickGridCollision(const BrickGrid& brickGrid)
|
||||
{
|
||||
auto [gridColumns, gridRows] = brickGrid.getGridSizes();
|
||||
auto [brickWidth, brickHeight] = brickGrid.getBrickSizes();
|
||||
auto [left, top, width, height] = brickGrid.getBorder();
|
||||
|
||||
// Определяем координаты блоков с которыми шарик может пересечься
|
||||
int brickColumnStart = std::clamp(static_cast<int>((position.x - left - radius) / brickWidth), 0, gridColumns);
|
||||
int brickColumnFinish = std::clamp(static_cast<int>((position.x - left + radius) / brickWidth) + 1, 0, gridColumns);
|
||||
int brickRowStart = std::clamp(static_cast<int>((position.y - top - radius) / brickHeight), 0, gridRows);
|
||||
int brickRowFinish = std::clamp(static_cast<int>((position.y - top + radius) / brickHeight) + 1, 0, gridRows);
|
||||
|
||||
// Если шарик находится вне сетки блоков, то выходим
|
||||
if (brickColumnStart == brickColumnFinish || brickRowStart == brickRowFinish)
|
||||
return {-1, -1};
|
||||
|
||||
// Находим ближайший к центру шарика активный пересекаемый шариком блок
|
||||
float closestSqNorm = width * width + height * height;
|
||||
std::pair<int, int> closestBrickIndexes = {-1, -1};
|
||||
for (int i = brickColumnStart; i < brickColumnFinish; ++i)
|
||||
{
|
||||
for (int j = brickRowStart; j < brickRowFinish; ++j)
|
||||
{
|
||||
if (!brickGrid.isBrickActive({i, j}))
|
||||
continue;
|
||||
|
||||
sf::FloatRect rect {left + i * brickWidth, top + j * brickHeight, brickWidth, brickHeight};
|
||||
auto [d, isColiding] = findClosestPoint(rect);
|
||||
if (!isColiding)
|
||||
continue;
|
||||
|
||||
if (sqnorm(d) < closestSqNorm)
|
||||
{
|
||||
closestSqNorm = sqnorm(d);
|
||||
closestBrickIndexes = {i, j};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Если такого не нашли, то возвращаем {-1, -1}
|
||||
if (closestBrickIndexes.first == -1)
|
||||
return closestBrickIndexes;
|
||||
|
||||
// Упруго сталкиваем шарик с найденым блоком
|
||||
sf::FloatRect rect {left + closestBrickIndexes.first * brickWidth, top + closestBrickIndexes.second * brickHeight, brickWidth, brickHeight};
|
||||
handleRectCollision(rect);
|
||||
|
||||
// Возвращаем координаты блока в сетки блоков
|
||||
return closestBrickIndexes;
|
||||
}
|
||||
|
||||
// Обрабатываем столкновения шарика с ракеткой
|
||||
void Ball::handlePaddleCollision(const Paddle& paddle)
|
||||
{
|
||||
auto [d, isColiding] = findClosestPoint(paddle.getBorder());
|
||||
if (!isColiding)
|
||||
return;
|
||||
|
||||
// Столкновение не упругое
|
||||
// Угол отражения зависит от места на ракетке, куда стукнулся шарик
|
||||
// Если шарик стукнулся в левую часть ракетки, то он должен полететь влево.
|
||||
// Если в правую часть ракетки, то вправо.
|
||||
const float pi = 3.14159265;
|
||||
float velocityAngle = (position.x - paddle.position.x) / (paddle.size.x + 2 * radius) * (0.8 * pi) + pi / 2;
|
||||
float velocityNorm = norm(velocity);
|
||||
velocity.x = - velocityNorm * std::cos(velocityAngle);
|
||||
velocity.y = - velocityNorm * std::sin(velocityAngle);
|
||||
}
|
31
term1/seminar13_polymorphism/arkanoid/ball.hpp
Normal file
31
term1/seminar13_polymorphism/arkanoid/ball.hpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
class BrickGrid;
|
||||
class Paddle;
|
||||
|
||||
struct Ball
|
||||
{
|
||||
inline static const float initialVelocity = 700;
|
||||
inline static const sf::Color color {246, 213, 92};
|
||||
float radius;
|
||||
sf::Vector2f position;
|
||||
sf::Vector2f velocity;
|
||||
|
||||
Ball(float radius, sf::Vector2f position, sf::Vector2f velocity);
|
||||
|
||||
void update(float dt);
|
||||
|
||||
void draw(sf::RenderWindow& window);
|
||||
|
||||
std::pair<sf::Vector2f, bool> findClosestPoint(const sf::FloatRect& rect) const;
|
||||
|
||||
bool handleRectCollision(const sf::FloatRect& rect);
|
||||
|
||||
void handleWallsCollision(sf::FloatRect boundary);
|
||||
|
||||
std::pair<int, int> handleBrickGridCollision(const BrickGrid& brickGrid);
|
||||
|
||||
void handlePaddleCollision(const Paddle& paddle);
|
||||
};
|
221
term1/seminar13_polymorphism/arkanoid/bonus.cpp
Normal file
221
term1/seminar13_polymorphism/arkanoid/bonus.cpp
Normal file
|
@ -0,0 +1,221 @@
|
|||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include "bonus.hpp"
|
||||
#include "arkanoid.hpp"
|
||||
#include "ball.hpp"
|
||||
#include "paddle.hpp"
|
||||
|
||||
/* =============
|
||||
* ===Bonuses===
|
||||
* =============
|
||||
* */
|
||||
|
||||
Bonus::Bonus(sf::Vector2f position): m_position(position)
|
||||
{
|
||||
m_time = 0;
|
||||
}
|
||||
|
||||
void Bonus::update(float dt)
|
||||
{
|
||||
m_time += dt;
|
||||
m_position.y += speed * dt;
|
||||
}
|
||||
|
||||
bool Bonus::isColiding(const Paddle& paddle) const
|
||||
{
|
||||
bool result = paddle.getBorder().intersects({m_position.x - radius, m_position.y - radius, 2 * radius, 2 * radius});
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* TripleBallBonus
|
||||
* */
|
||||
void TripleBallBonus::draw(sf::RenderWindow& window) const
|
||||
{
|
||||
static sf::CircleShape shape(radius);
|
||||
shape.setOrigin(radius, radius);
|
||||
shape.setFillColor(sf::Color{100, 200, 100});
|
||||
shape.setPosition(m_position);
|
||||
window.draw(shape);
|
||||
|
||||
float angle = 0;
|
||||
|
||||
static Ball ball {5, {0, 0}, {0, 0}};
|
||||
float ballRotationRadius = 7;
|
||||
ball.position = m_position + ballRotationRadius * sf::Vector2f(std::cos(angle), std::sin(angle));
|
||||
ball.draw(window);
|
||||
angle += 2.0 * M_PI / 3.0;
|
||||
ball.position = m_position + ballRotationRadius * sf::Vector2f(std::cos(angle), std::sin(angle));
|
||||
ball.draw(window);
|
||||
angle += 2.0 * M_PI / 3.0;
|
||||
ball.position = m_position + ballRotationRadius * sf::Vector2f(std::cos(angle), std::sin(angle));
|
||||
ball.draw(window);
|
||||
}
|
||||
|
||||
void TripleBallBonus::activate(Arkanoid& game)
|
||||
{
|
||||
int numBalls = game.m_balls.size();
|
||||
std::list<Ball>::iterator it = game.m_balls.begin();
|
||||
|
||||
bool isSlowed = false;
|
||||
bool toApply = true;
|
||||
|
||||
Effect* slowing_effect = nullptr;
|
||||
for (auto it = game.m_effects.begin(); it != game.m_effects.end();) {
|
||||
if ((*it)->effectId == _EFFECT_SLOWING_ID) {
|
||||
isSlowed = true;
|
||||
slowing_effect = *it;
|
||||
break;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
for (int i = 0; i < numBalls; i++)
|
||||
{
|
||||
float angle, vx, vy;
|
||||
if (game.isMaxBalls()) {
|
||||
toApply = false;
|
||||
}
|
||||
|
||||
if (toApply) {
|
||||
angle = rand() % 1000 * (2 * M_PI / 1000);
|
||||
vx = Ball::initialVelocity * sin(angle);
|
||||
vy = Ball::initialVelocity * cos(angle);
|
||||
game.addBall({game.m_initialBall.radius, (*it).position, {vx, vy}});
|
||||
|
||||
if (isSlowed) {
|
||||
slowing_effect->activate(game.m_balls.back());
|
||||
}
|
||||
}
|
||||
|
||||
if (game.isMaxBalls()) {
|
||||
toApply = false;
|
||||
}
|
||||
|
||||
if (toApply) {
|
||||
angle = rand() % 1000 * (2 * M_PI / 1000);
|
||||
vx = Ball::initialVelocity * sin(angle);
|
||||
vy = Ball::initialVelocity * cos(angle);
|
||||
game.addBall({game.m_initialBall.radius, (*it).position, {vx, vy}});
|
||||
if (isSlowed) {
|
||||
slowing_effect->activate(game.m_balls.back());
|
||||
}
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* EnlargePaddleBonus
|
||||
* */
|
||||
void EnlargePaddleBonus::draw(sf::RenderWindow& window) const
|
||||
{
|
||||
static sf::CircleShape shape(radius);
|
||||
shape.setOrigin(radius, radius);
|
||||
shape.setFillColor(sf::Color{100, 200, 100});
|
||||
shape.setPosition(m_position);
|
||||
window.draw(shape);
|
||||
|
||||
static sf::RectangleShape rect(sf::Vector2f{radius, radius / 2});
|
||||
rect.setFillColor(sf::Color::Green);
|
||||
rect.setPosition(m_position - sf::Vector2f{radius /2, radius / 4});
|
||||
window.draw(rect);
|
||||
}
|
||||
|
||||
void EnlargePaddleBonus::activate(Arkanoid& game)
|
||||
{
|
||||
if (game.m_paddle.size.x < 300) {
|
||||
game.m_paddle.size.x *= 1.5;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ShrinkPaddleBonus
|
||||
* */
|
||||
void ShrinkPaddleBonus::draw(sf::RenderWindow& window) const
|
||||
{
|
||||
static sf::CircleShape shape(radius);
|
||||
shape.setOrigin(radius, radius);
|
||||
shape.setFillColor(sf::Color{100, 200, 100});
|
||||
shape.setPosition(m_position);
|
||||
window.draw(shape);
|
||||
|
||||
static sf::RectangleShape rect(sf::Vector2f{radius, radius / 2});
|
||||
rect.setFillColor(sf::Color::Red);
|
||||
rect.setPosition(m_position - sf::Vector2f{radius /2, radius / 4});
|
||||
window.draw(rect);
|
||||
}
|
||||
void ShrinkPaddleBonus::activate(Arkanoid& game)
|
||||
{
|
||||
if (game.m_paddle.size.x > 40) {
|
||||
game.m_paddle.size.x *= 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SlowingBonus
|
||||
* */
|
||||
|
||||
void SlowingBonus::draw(sf::RenderWindow& window) const
|
||||
{
|
||||
static sf::CircleShape shape(radius);
|
||||
shape.setOrigin(radius, radius);
|
||||
shape.setFillColor(sf::Color{100, 200, 100});
|
||||
shape.setPosition(m_position);
|
||||
window.draw(shape);
|
||||
|
||||
static sf::CircleShape clock(radius / 2);
|
||||
clock.setOutlineColor(sf::Color::Red);
|
||||
clock.setOutlineThickness(3);
|
||||
clock.setPosition(m_position - sf::Vector2f{radius /2, radius / 2});
|
||||
window.draw(clock);
|
||||
}
|
||||
|
||||
void SlowingBonus::activate(Arkanoid& game)
|
||||
{
|
||||
bool isAlreadySlowed = false;
|
||||
for (auto it = game.m_effects.begin(); it != game.m_effects.end();) {
|
||||
if ((*it)->effectId == _EFFECT_SLOWING_ID) {
|
||||
(*it)->mDuration += mDuration;
|
||||
isAlreadySlowed = true;
|
||||
break;
|
||||
}
|
||||
it++;
|
||||
}
|
||||
if (!isAlreadySlowed) {
|
||||
game.m_effects.push_back(new SlowingEffect(game.m_time, mDuration));
|
||||
game.m_effects.back()->activate(game);
|
||||
}
|
||||
}
|
||||
|
||||
/* =============
|
||||
* ===Effects===
|
||||
* =============
|
||||
* */
|
||||
|
||||
Effect::Effect(char id, double start_time, double duration) : effectId(id), mStartTime(start_time), mDuration(duration) {};
|
||||
|
||||
bool Effect::isExpired(double time) {
|
||||
if (mStartTime + mDuration > time)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
SlowingEffect::SlowingEffect(double start_time, double duration) : Effect(_EFFECT_SLOWING_ID, start_time, duration) {};
|
||||
|
||||
void SlowingEffect::activate(Arkanoid& game) {
|
||||
for (Ball& ball : game.m_balls) {
|
||||
ball.velocity = sf::Vector2f{ball.velocity.x * mSlowingFactor, ball.velocity.y * mSlowingFactor};
|
||||
}
|
||||
}
|
||||
void SlowingEffect::activate(Ball& ball) {
|
||||
ball.velocity = sf::Vector2f{ball.velocity.x * mSlowingFactor, ball.velocity.y * mSlowingFactor};
|
||||
}
|
||||
|
||||
void SlowingEffect::deactivate(Arkanoid& game) {
|
||||
for (Ball& ball : game.m_balls) {
|
||||
ball.velocity = sf::Vector2f{ball.velocity.x / mSlowingFactor, ball.velocity.y / mSlowingFactor};
|
||||
}
|
||||
}
|
||||
|
92
term1/seminar13_polymorphism/arkanoid/bonus.hpp
Normal file
92
term1/seminar13_polymorphism/arkanoid/bonus.hpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
#pragma once
|
||||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
class Paddle;
|
||||
class Ball;
|
||||
class Arkanoid;
|
||||
|
||||
class Bonus
|
||||
{
|
||||
protected:
|
||||
inline static const float speed = 120;
|
||||
inline static const float radius = 15;
|
||||
|
||||
sf::Vector2f m_position;
|
||||
float m_time;
|
||||
|
||||
public:
|
||||
Bonus(sf::Vector2f position);
|
||||
void update(float dt);
|
||||
virtual void draw(sf::RenderWindow& window) const = 0;
|
||||
virtual void activate(Arkanoid& game) = 0;
|
||||
virtual ~Bonus() = default;
|
||||
|
||||
bool isColiding(const Paddle& paddle) const;
|
||||
// Класс Arkanoid должен быть дружественным, так как он может менять внутреннее объекта-бонуса
|
||||
friend class Arkanoid;
|
||||
};
|
||||
|
||||
class TripleBallBonus : public Bonus {
|
||||
public:
|
||||
TripleBallBonus(sf::Vector2f position): Bonus(position) {};
|
||||
void draw(sf::RenderWindow& window) const;
|
||||
void activate(Arkanoid& game);
|
||||
};
|
||||
|
||||
class EnlargePaddleBonus : public Bonus {
|
||||
public:
|
||||
EnlargePaddleBonus(sf::Vector2f position): Bonus(position) {};
|
||||
void draw(sf::RenderWindow& window) const;
|
||||
void activate(Arkanoid& game);
|
||||
};
|
||||
|
||||
class ShrinkPaddleBonus : public Bonus {
|
||||
public:
|
||||
ShrinkPaddleBonus(sf::Vector2f position): Bonus(position) {};
|
||||
void draw(sf::RenderWindow& window) const;
|
||||
void activate(Arkanoid& game);
|
||||
};
|
||||
|
||||
class SlowingBonus : public Bonus {
|
||||
private:
|
||||
double mDuration = 10;
|
||||
public:
|
||||
SlowingBonus(sf::Vector2f position): Bonus(position) {};
|
||||
void draw(sf::RenderWindow& window) const;
|
||||
void activate(Arkanoid& game);
|
||||
};
|
||||
|
||||
/*
|
||||
* Effects
|
||||
* */
|
||||
#define _EFFECT_SLOWING_ID 0
|
||||
class Effect {
|
||||
protected:
|
||||
char effectId;
|
||||
double mStartTime;
|
||||
double mDuration;
|
||||
public:
|
||||
Effect(char id, double start_time, double duration);
|
||||
virtual ~Effect() = default;
|
||||
|
||||
virtual void activate(Arkanoid& game) = 0;
|
||||
virtual void activate(Ball& ball) = 0;
|
||||
virtual void deactivate(Arkanoid& game) = 0;
|
||||
bool isExpired(double time);
|
||||
|
||||
|
||||
friend class SlowingBonus;
|
||||
friend class TripleBallBonus;
|
||||
friend class Arkanoid;
|
||||
};
|
||||
|
||||
class SlowingEffect : public Effect {
|
||||
private:
|
||||
float mSlowingFactor = 0.1;
|
||||
char id = _EFFECT_SLOWING_ID;
|
||||
public:
|
||||
SlowingEffect(double start_time, double duration);
|
||||
void activate(Arkanoid& game);
|
||||
void activate(Ball& ball);
|
||||
void deactivate(Arkanoid& game);
|
||||
};
|
5
term1/seminar13_polymorphism/arkanoid/brick.hpp
Normal file
5
term1/seminar13_polymorphism/arkanoid/brick.hpp
Normal file
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
struct Brick
|
||||
{
|
||||
bool isActive;
|
||||
};
|
63
term1/seminar13_polymorphism/arkanoid/brick_grid.cpp
Normal file
63
term1/seminar13_polymorphism/arkanoid/brick_grid.cpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
#include <vector>
|
||||
#include "brick_grid.hpp"
|
||||
|
||||
BrickGrid::BrickGrid() {}
|
||||
BrickGrid::BrickGrid(sf::FloatRect borders, int numBrickColumns, int numBrickRows) :
|
||||
m_border(borders),
|
||||
m_numBrickColumns(numBrickColumns),
|
||||
m_numBrickRows(numBrickRows),
|
||||
m_numActiveBricks(numBrickColumns * numBrickRows)
|
||||
{
|
||||
m_bricks.resize(m_numBrickColumns * m_numBrickRows, Brick{true});
|
||||
m_brickShape.setSize(getBrickSizes());
|
||||
m_brickShape.setOutlineColor(sf::Color::Black);
|
||||
m_brickShape.setOutlineThickness(0.5);
|
||||
m_brickShape.setFillColor(color);
|
||||
}
|
||||
|
||||
sf::FloatRect BrickGrid::getBorder() const
|
||||
{
|
||||
return m_border;
|
||||
}
|
||||
|
||||
sf::Vector2i BrickGrid::getGridSizes() const
|
||||
{
|
||||
return {m_numBrickColumns, m_numBrickRows};
|
||||
}
|
||||
|
||||
sf::Vector2f BrickGrid::getBrickSizes() const
|
||||
{
|
||||
return {m_border.width / m_numBrickColumns, m_border.height / m_numBrickRows};
|
||||
}
|
||||
|
||||
bool BrickGrid::isBrickActive(std::pair<int, int> indexes) const
|
||||
{
|
||||
return m_bricks[indexes.first + indexes.second * m_numBrickColumns].isActive;
|
||||
}
|
||||
|
||||
void BrickGrid::deactivateBrick(std::pair<int, int> indexes)
|
||||
{
|
||||
m_bricks[indexes.first + indexes.second * m_numBrickColumns].isActive = false;
|
||||
m_numActiveBricks--;
|
||||
}
|
||||
|
||||
int BrickGrid::getNumActiveBricks() const
|
||||
{
|
||||
return m_numActiveBricks;
|
||||
}
|
||||
|
||||
void BrickGrid::draw(sf::RenderWindow& window)
|
||||
{
|
||||
auto [brickWidth, brickHeight] = getBrickSizes();
|
||||
|
||||
for (int j = 0; j < m_numBrickRows; ++j)
|
||||
{
|
||||
for (int i = 0; i < m_numBrickColumns; ++i)
|
||||
{
|
||||
if (!isBrickActive({i, j}))
|
||||
continue;
|
||||
m_brickShape.setPosition({m_border.left + i * brickWidth, m_border.top + j * brickHeight});
|
||||
window.draw(m_brickShape);
|
||||
}
|
||||
}
|
||||
}
|
37
term1/seminar13_polymorphism/arkanoid/brick_grid.hpp
Normal file
37
term1/seminar13_polymorphism/arkanoid/brick_grid.hpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
#include <SFML/Window.hpp>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "brick.hpp"
|
||||
|
||||
class BrickGrid
|
||||
{
|
||||
private:
|
||||
inline static const sf::Color color {100, 200, 250};
|
||||
|
||||
sf::FloatRect m_border;
|
||||
int m_numBrickColumns;
|
||||
int m_numBrickRows;
|
||||
|
||||
std::vector<Brick> m_bricks;
|
||||
sf::RectangleShape m_brickShape;
|
||||
|
||||
int m_numActiveBricks;
|
||||
|
||||
public:
|
||||
BrickGrid();
|
||||
BrickGrid(sf::FloatRect borders, int numBrickColumns, int numBrickRows);
|
||||
|
||||
sf::FloatRect getBorder() const;
|
||||
|
||||
sf::Vector2i getGridSizes() const;
|
||||
|
||||
sf::Vector2f getBrickSizes() const;
|
||||
|
||||
bool isBrickActive(std::pair<int, int> indexes) const;
|
||||
|
||||
void deactivateBrick(std::pair<int, int> indexes);
|
||||
|
||||
int getNumActiveBricks() const;
|
||||
|
||||
void draw(sf::RenderWindow& window);
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue