diff --git a/.gitignore b/.gitignore index e511087..9f6f0b1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ source magic_square_module + +*.ilk +*.obj +*.pdb \ No newline at end of file diff --git a/README.md b/README.md index 120a27a..a66b07a 100644 --- a/README.md +++ b/README.md @@ -1 +1,50 @@ -

Some changes

+
+

⚠️Важное! Эта ветка предназначена для Windows и компилятора VS. Если у вас Linux и компилятор g++, используйте main ветку.⚠️

+
+ +
+ +
+

🧮 О проекте

+
+

Магический квадрат — это квадратная таблица размера n×n, заполненная различными числами таким образом, что сумма чисел в каждой строке, каждом столбце и на обеих диагоналях одинакова. Данный проект реализует генерацию магических квадратов нечётного порядка (n = 2k + 1) с использованием классического сиамского метода, также известного как метод де ла Лубера.

+ +
+ +
+

📊 Основные возможности

+
+
+

✅ Генерация магических квадратов любого нечётного порядка (3, 5, 7, ...)

+

✅ Проверка магических свойств (суммы строк, столбцов, диагоналей)

+

✅ Сохранение результатов в текстовый файл

+

✅ Визуально приятное форматирование вывода

+
+ +
+ + +
+

🚀 Установка(легкая)

+
+

Скачайте файл source.exe и откройте его

+ + +
+

🚀 Установка(сложная)

+
+ +

Предварительные требования

+

Windows

+

Компилятор C++11 или новее (Visual Studio)

+ +

Сборка из исходного кода

+ +

Клонировать репозиторий :

+

Откройте настроенный Vs code с помощью компилятора visual Studio и выполните запись в terminal :

+
git clone -b Windows_edition https://github.com/matb22/Magic-square.git
+

Откройте файл source.cpp и запустите процесс компиляции с помощью кнопки в vs code

+

Done!

+ + + diff --git a/magic_square.h b/magic_square.h index 9fd5aa6..eb2e211 100644 --- a/magic_square.h +++ b/magic_square.h @@ -1,10 +1,16 @@ #ifndef MAGIC_SQUARE_H #define MAGIC_SQUARE_H -void generateMagicSquare(int n) ; - #include "magic_square_module.cpp" +void DisplaySquareInfo() ; +void OutputSquareConsole(int n, const std::vector>& magic_square); +void OutputSquareFile(int n, const std::vector>& magic_square); +int CountDigits(int number); +bool IsMagicSquareValid(const std::vector>& square); +void GenerateMagicSquare(int square_size) ; + + #endif \ No newline at end of file diff --git a/magic_square_module.cpp b/magic_square_module.cpp index 6bfaf91..3ef588c 100644 --- a/magic_square_module.cpp +++ b/magic_square_module.cpp @@ -1,173 +1,140 @@ -#include -#include -#include -#include #include +#include +#include +#include +#include +void OutputSquareConsole(int n, const std::vector>& magic_square); +void OutputSquareFile(int n, const std::vector>& magic_square); +int CountDigits(int number); +bool IsMagicSquareValid(const std::vector>& square); - - -void Output_square_console(int n , std::vector> magicSquare) ; -void Output_square_file(int n , std::vector> magicSquare); -int countDigits(int n ) ; -bool isMagicSquareValid(const std::vector>& square) ; - -void generateMagicSquare(int n) { +void GenerateMagicSquare(int square_size) { + const int n = square_size; - - - std::vector> magicSquare(n, std::vector(n, 0)); + std::vector> magic_square(n, std::vector(n, 0)); int i = 0; int j = n / 2; - for (int num = 1; num <= n * n; num++) { - magicSquare[i][j] = num; + for (int num = 1; num <= n * n; ++num) { + magic_square[i][j] = num; - int next_i = (i - 1 + n) % n; - int next_j = (j + 1) % n; + const int next_i = (i - 1 + n) % n; + const int next_j = (j + 1) % n; - if (magicSquare[next_i][next_j] != 0) { + if (magic_square[next_i][next_j] != 0) { i = (i + 1) % n; - } - else { + } else { i = next_i; j = next_j; } } - if (isMagicSquareValid(magicSquare)) { - std::cout << "✓ Квадрат корректный!\n"; - } - else { - std::cout << "✗ Ошибка: квадрат некорректный!\n"; - } - - - - - + if (IsMagicSquareValid(magic_square)) { + std::cout << "✓ Квадрат корректный!\n"; + } else { + std::cout << "✗ Ошибка: квадрат некорректный!\n"; + } - Output_square_console(n , magicSquare) ; - Output_square_file( n , magicSquare) ; - + OutputSquareConsole(n, magic_square); + OutputSquareFile(n, magic_square); } - -void Output_square_console(int n , std::vector> magicSquare) { +void OutputSquareConsole(int n, const std::vector>& magic_square) { std::cout << "Магический квадрат порядка " << n << ":\n"; - std::cout << "Сумма в каждой строке, столбце и диагонали = " - << n * (n * n + 1) / 2 << "\n\n"; + std::cout << "Сумма в каждой строке, столбце и диагонали = " + << n * (n * n + 1) / 2 << "\n\n"; - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - std::cout << std::setw(countDigits(n*n) + 1) << magicSquare[i][j] << " "; + const int column_width = CountDigits(n * n) + 1; + + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + std::cout << std::setw(column_width) << magic_square[i][j] << " "; } - std::cout << std::endl; + std::cout << "\n"; } } +void OutputSquareFile(int n, const std::vector>& magic_square) { + std::ofstream output_file("magic_square.txt"); + if (!output_file.is_open()) { + std::cerr << "Ошибка: не удалось открыть файл для записи.\n"; + return; + } + output_file << "Магический квадрат порядка " << n << ":\n"; + output_file << "Сумма в каждой строке, столбце и диагонали = " + << n * (n * n + 1) / 2 << "\n\n"; -void Output_square_file(int n , std::vector> magicSquare) { - std::ofstream f2 ; - f2.open("magic_square.txt" , std::ios::out) ; + const int column_width = CountDigits(n * n) + 1; - f2 << "Магический квадрат порядка " << n << ":\n"; - f2 << "Сумма в каждой строке, столбце и диагонали = " - << n * (n * n + 1) / 2 << "\n\n"; - - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - f2 << std::setw(countDigits(n*n) + 1) << magicSquare[i][j] << " "; + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + output_file << std::setw(column_width) << magic_square[i][j] << " "; } - f2 << std::endl; + output_file << "\n"; } - - f2.close() ; -} - - - - - -int countDigits(int n ) { - - if (n == 0) return 1; - if (n < 0) n = -n; - - return static_cast(log10(n)) + 1; } - - - - - - -void Square_info() { - std::cout<<"\n\n Магический квадрат — это квадратная таблица размером n×n, заполненная разными\n" ; - std::cout<<" натуральными числами (обычно от 1 до n²) таким образом, что:\n" ; - std::cout<<"* Cумма чисел в каждой строке, каждом столбце и на обеих диагоналях — одинаковая.\n\n" ; - - +int CountDigits(int number) { + if (number == 0) return 1; + if (number < 0) number = -number; + return static_cast(std::log10(number)) + 1; } +void DisplaySquareInfo() { + std::cout << "\n\n Магический квадрат — это квадратная таблица размером n×n,\n" + << " заполненная разными натуральными числами (обычно от 1 до n²)\n" + << " таким образом, что сумма чисел в каждой строке, каждом столбце\n" + << " и на обеих диагоналях — одинаковая.\n\n"; +} - - - -bool isMagicSquareValid(const std::vector>& square) { - int n = square.size(); - if (n % 2 == 0) return false; - - // Проверяем, что все числа от 1 до n² присутствуют ровно один раз - std::vector found(n * n + 1, false); - for (int i = 0; i < n; i++) { - for (int j = 0; j < n; j++) { - int num = square[i][j]; - if (num < 1 || num > n * n || found[num]) { - return false; - } - found[num] = true; - } - } - - // Вычисляем магическую константу - int magicSum = n * (n * n + 1) / 2; - - // Проверяем суммы строк - for (int i = 0; i < n; i++) { - int rowSum = 0; - for (int j = 0; j < n; j++) { - rowSum += square[i][j]; - } - if (rowSum != magicSum) return false; - } - - // Проверяем суммы столбцов - for (int j = 0; j < n; j++) { - int colSum = 0; - for (int i = 0; i < n; i++) { - colSum += square[i][j]; - } - if (colSum != magicSum) return false; +bool IsMagicSquareValid(const std::vector>& square) { + const int n = square.size(); + if (n <= 0 || n % 2 == 0) return false; + + std::vector found(n * n + 1, false); + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + const int num = square[i][j]; + if (num < 1 || num > n * n || found[num]) { + return false; + } + found[num] = true; } - - // Проверяем главную диагональ - int diag1Sum = 0; - for (int i = 0; i < n; i++) { - diag1Sum += square[i][i]; + } + + const int magic_sum = n * (n * n + 1) / 2; + + for (int i = 0; i < n; ++i) { + int row_sum = 0; + for (int j = 0; j < n; ++j) { + row_sum += square[i][j]; } - if (diag1Sum != magicSum) return false; - - // Проверяем побочную диагональ - int diag2Sum = 0; - for (int i = 0; i < n; i++) { - diag2Sum += square[i][n - 1 - i]; + if (row_sum != magic_sum) return false; + } + + for (int j = 0; j < n; ++j) { + int col_sum = 0; + for (int i = 0; i < n; ++i) { + col_sum += square[i][j]; } - if (diag2Sum != magicSum) return false; - - return true; + if (col_sum != magic_sum) return false; + } + + int diag1_sum = 0; + for (int i = 0; i < n; ++i) { + diag1_sum += square[i][i]; + } + if (diag1_sum != magic_sum) return false; + + int diag2_sum = 0; + for (int i = 0; i < n; ++i) { + diag2_sum += square[i][n - 1 - i]; + } + if (diag2_sum != magic_sum) return false; + + return true; } \ No newline at end of file diff --git a/source.cpp b/source.cpp index 02e2ce0..bf7de89 100644 --- a/source.cpp +++ b/source.cpp @@ -1,95 +1,113 @@ #include #include #include "magic_square.h" +#include +constexpr int kMinMenuChoice = 1; +constexpr int kMaxMenuChoice = 3; +constexpr int kMinSquareSize = 1; -int main() { - int task_number; - int n; - bool exit_program = false; +void DisplayMenu() { + std::cout << " ========== Меню ==========\n"; + std::cout << " 1) Создать магический квадрат\n"; + std::cout << " 2) Что такое магический квадрат?\n"; + std::cout << " 3) Выход\n"; + std::cout << "Введите номер пункта:\n>> "; +} - while (!exit_program) { - std::cout << " ==========Menu==========\n"; - std::cout << " 1) Создать магический квадрат\n"; - std::cout << " 2) Что такое магический квадрат?\n"; - std::cout << " 3) Выход\n"; - std::cout << "Введите номер желаемого пункта: \n>> "; +int GetMagicSquareSize() { + int size = 0; + + std::cout << "Введите нечетный порядок квадрата:\n>> "; + + while (true) { + if (!(std::cin >> size)) { + std::cin.clear(); + std::cin.ignore((std::numeric_limits::max)(), '\n'); + std::cout << "Ошибка! Введите число от 3 до 2,147,483,646 :\n>> "; + continue; + } + + if (size <= kMinSquareSize) { + std::cout << "Порядок должен быть положительным! Попробуйте снова:\n>> "; + std::cin.ignore((std::numeric_limits::max)(), '\n'); + continue; + } + + if (size % 2 == 0) { + std::cout << "Порядок должен быть нечетным! Попробуйте снова:\n>> "; + std::cin.ignore((std::numeric_limits::max)(), '\n'); + continue; + } + + break; + } + + return size; +} - // Проверка ввода пункта меню - while (!(std::cin >> task_number) || task_number < 1 || task_number > 3) { - std::cin.clear(); - std::cin.ignore(std::numeric_limits::max(), '\n'); - std::cout << "Неверный ввод! Выберите пункт 1-3: \n>> "; - } +bool PromptToContinue() { + char choice = '\0'; + std::cout << "\nВыполнить еще одну операцию? (y/n): "; + std::cin >> choice; + std::cin.ignore((std::numeric_limits::max)(), '\n'); + + return !(choice == 'n' || choice == 'N'); +} - std::cin.ignore(std::numeric_limits::max(), '\n'); // Очистка буфера +void WaitForEnter() { + std::cout << "\nНажмите Enter для возврата в меню..."; + std::cin.get(); +} - switch (task_number) { - case 1: { - - std::cout << "Введите нечетный порядок магического квадрата: \n>> "; - - - while (true) { - // Пытаемся прочитать число - if (!(std::cin >> n)) { - // Ошибка ввода (не число) - std::cin.clear(); - std::cin.ignore(std::numeric_limits::max(), '\n'); - std::cout << "Ошибка! Введите число: \n>> "; - continue; - } - - // Проверяем на четность - if (n % 2 == 0) { - std::cout << "Порядок должен быть нечетным! Попробуйте снова: \n>> "; - std::cin.ignore(std::numeric_limits::max(), '\n'); - continue; - } - - // Проверяем, что число положительное - if (n <= 0) { - std::cout << "Порядок должен быть положительным! Попробуйте снова: \n>> "; - std::cin.ignore(std::numeric_limits::max(), '\n'); - continue; - } - - // Все проверки пройдены - break; - } - - std::cin.ignore(std::numeric_limits::max(), '\n'); // Очистка буфера - - // Генерация квадрата - generateMagicSquare(n); - - // Спросить, хочет ли пользователь продолжить - char choice; - std::cout << "\nХотите выполнить еще одну операцию? (y/n): "; - std::cin >> choice; - std::cin.ignore(std::numeric_limits::max(), '\n'); - - if (choice == 'n' || choice == 'N') { - exit_program = true; - } - break; - } +int main() { + SetConsoleOutputCP(CP_UTF8); + SetConsoleCP(CP_UTF8); + + int menu_choice = 0; + bool exit_program = false; + + while (!exit_program) { + DisplayMenu(); + + while (!(std::cin >> menu_choice) || + menu_choice < kMinMenuChoice || + menu_choice > kMaxMenuChoice) { + std::cin.clear(); + std::cin.ignore((std::numeric_limits::max)(), '\n'); + std::cout << "Неверный ввод! Выберите пункт 1-3:\n>> "; + } + + std::cin.ignore((std::numeric_limits::max)(), '\n'); + + switch (menu_choice) { + case 1: { + const int square_size = GetMagicSquareSize(); + std::cin.ignore((std::numeric_limits::max)(), '\n'); - case 2: - Square_info(); - - // Спросить, хочет ли пользователь продолжить - char choice; - std::cout << "\nНажмите Enter для возврата в меню..."; - std::cin.get(); - break; - - case 3: - exit_program = true; - break; + GenerateMagicSquare(square_size); + + if (!PromptToContinue()) { + exit_program = true; } + break; + } + + case 2: + DisplaySquareInfo(); + WaitForEnter(); + break; + + case 3: + exit_program = true; + break; + + default: + std::cerr << "Неожиданный выбор меню: " << menu_choice << "\n"; + break; } - - std::cout << "Программа завершена. До свидания!\n"; - return 0; + } + + std::cout << "Программа завершена. До свидания!\n"; + return 0; } \ No newline at end of file diff --git a/source.exe b/source.exe new file mode 100644 index 0000000..250727a Binary files /dev/null and b/source.exe differ