Exemple #1
0
        public void matrixMenu()
        {
            ConsoleKey action;       // Переменная, в которую будет считываться нажатие клавиши
            int        currItem = 1; // Текущий пункт меню


            do                  // Считываем нажатия, пока не будет ESC
            {
                windowM.newWindow(winWidth, winHeight);
                Console.CursorVisible = false;  // Делаем курсор невидимым
                windowM.HeaderCenter("ОПЕРАЦИИ С МАТРИЦАМИ", winWidth, 2, ConsoleColor.Yellow);
                action = windowM.MenuSelect(menuItems, currItem, winWidth, 4);

                switch (action)
                {
                case ConsoleKey.D1:
                    multiplyMatrixByNumber();
                    currItem = 1;
                    break;

                case ConsoleKey.D2:
                    addMatrixes();
                    currItem = 2;
                    break;

                case ConsoleKey.D3:
                    subtractMatrixes();
                    currItem = 3;
                    break;

                case ConsoleKey.D4:
                    multiplyMatrixes();
                    currItem = 4;
                    break;

                case ConsoleKey.Escape:
                    Console.WriteLine("ДО СВИДАНИЯ!");
                    break;

                default:
                    break;       // нажата любая другая клавиша - ничего не происходит
                }
            } while (action != ConsoleKey.Escape);
        }   // public void matrixMenu()
        public void printPascalTriangle()
        {
            int  i, j;                 // вспомогательная переменная
            bool cursorVisibility;

            windowPT.newWindow(winWidth, winHeight);
            windowPT.HeaderCenter("ТРЕУГОЛЬНИК ПАСКАЛЯ", winWidth, 2, ConsoleColor.Yellow);
            Console.WriteLine();
            cursorVisibility      = Console.CursorVisible;
            Console.CursorVisible = true;

            level = correctInput.Parse("Введите количество уровней треугольника Паскаля", "Введите число", 1, 25, 0, 4);
            Console.WriteLine();
            Console.CursorVisible = cursorVisibility;

            // Создаём зубчатый массив для ТП
            // Создаём массив уровней. Каждый элемент - это массив
            // для экономии памяти сделаем
            // количество элементов в каждом уровне ТП
            // в два раза меньше, чем номер уровня (если считать с 1)

            pT       = new int[level][];
            pTstring = new string[level];

            #region заполнение треугольника Паскаля

            pT[0]    = new int[1];
            pT[0][0] = 1;               // инициализируем элемент на 1-м уровне

            if (level >= 2)
            {
                pT[1]    = new int[1];
                pT[1][0] = 1;           // инициализируем элемент на 2-м уровне
            }

            j = 0;                      // потребуется дальше, если не войдём по условию ниже.

            if (level > 2)
            {
                for (i = 2; i < level; i++)
                {
                    // Создаём уровень
                    // количество элементов в каждом уровне ТП
                    // в два раза меньше, чем номер уровня (если считать с 1)

                    // pos равен количеству элементов в массиве для очередного уровня
                    // причём pos одинаковое для нечётного (если считать с 1)
                    // и для следующего чётного уровня.
                    // Выделяем соответствующий объём памяти
                    pos      = ((i + 1) / 2 + (i + 1) % 2);
                    pT[i]    = new int[pos];
                    pT[i][0] = 1;                   // инициализируем первый элемент уровня

                    // Теперь надо инициализировать все остальные элементы, начиная со 2-ого по счёту
                    // если уровень нечётный, то pos указывает на средний элемент (если считать с 1)
                    // если чётный, то на первый самый большой элемент.
                    // Поэтому мы не можем делать цикл ниже до pos, надо до предпоследнего элемента
                    //

                    for (j = 1; j < (pos - 1); j++)
                    {
                        pT[i][j] = pT[i - 1][j - 1] + pT[i - 1][j];
                    }
                    // окончили цикл j == pos - 1
                    // это либо средний элемент (если в уровне нечётное кол-во элементов)
                    // либо последний элемен, а следующий такой же (если в уровне чётное кол-во элементов)
                    // но для 3 и 4 уровней цикл выше не работает, когда всего два элемента в массиве,
                    // т.к. pos равен 2, pos - 1 равен 1, а j уже 1.

                    if ((i + 1) % 2 == 1)    // если нечётный уровень, когда считаем уровни с 1,
                    {                        // то элемента  pT[i - 1][pos] не существует
                        pT[i][j] = pT[i - 1][j - 1] * 2;
                    }
                    else // если чётная, когда считаем уровни с 1, то существует,
                    {    // и мы как бы делаем последнюю итерацию цикла выше, но уже с j равным pos - 1
                        pT[i][j] = pT[i - 1][j - 1] + pT[i - 1][j];
                    }
                }   // создание и заполнение массива for (i = 0; i < level; i++)
            }
            #endregion заполнение треугольника Паскаля

            #region вывод массива на экран

            // Чтобы вывести ТП, найдём длину самого длинного числа в ТП.
            // Это самое большое число, оно же самое последнее.
            longest = $"{pT[level - 1][j]}".Length;

            // если длина самого большого числа чётная, тогда добавляем 1
            longest = ((longest % 2) == 0) ? ++longest : longest;

            int    spaceLeft;       // количество пробелов слева, чтобы число выводилось по центру поля
            string currString;      // строковое представление текущего числа

            int half = longest / 2; // половина longest
            int s    = 1;           // расстояние между полями для вывода чисел

            int first;              // координата первого числа уровня
            int next;               // координаты начала поля следующего числа
            int offset;             // сдвиг, чтобы ТП показывался по центру экрана
            int Y = 7;              // координата первой строки

            // Сделаем количество символов в самом большом числе длиной поля
            // для вывод всех остальных чисел, кроме кайних 1.
            // Если longest чётное, то длина поля на 1 больше.
            // Будем помещать каждое число в центр такого поля.
            // Например, поле длиной 5 символов. Число 3 символа    ".YYY."
            // Поле длиной 5 символов, число 2 символа ".YY..", если стоит слева от центральной вертикальной линии
            // или центральное число. И  "..YY." если справа от центальной линии.
            // Ширина поля равна (half + 1 + half)

            // Расстояние между полями S сделаем 1 символ. Допустим, длина half это 3 символа.
            // Обозначим half как ... . Тогда формат вывода ТП будет таким
            // Не крайние единицы '1' - это центры полей для вывода соответствующих чисел ТП
            // 0                 1
            // 1             1...S...1
            // 2         1...S...1...S...1
            // 3     1...S...1...S...1...S...1
            // 4 1...S...1...S...1...S...1...S...1

            // тогда координата First на экране первого символа в N-ой строке (N считаемт от 0)
            // равна (1+half)*(level - N - 1)
            // координата единицы в 0-й строке равна (1+half)*(level - 1)
            // координата единицы в последней строке (1+half)* 0 = 0
            // Найдём длину половинок слева и справа от центр

            // тогда координаты начала поля вывода любого следующих j-ого числа
            // Frist + (1 + half +S) + ((half + 1 + half) + S)* (j-1)
            // Формула учитывает, что координаты Х первого символа равны 0 (ноль)
            // Что индекс j начинается с 0, т.е. pT[...][0] = 1

            offset = (((half + 1 + half + s) * (level - 1) + 1) < winWidth)
                     ? (winWidth - ((half + 1 + half + s) * (level - 1) + 1)) / 2
                     : 5;

            if (level == 1)
            {
                Console.SetCursorPosition(offset, Y);
                Console.Write(pT[0][0]);
            }

            if (level >= 2)
            {
                i     = 0;  j = 0;
                first = (1 + half) * (level - i - 1);
                Console.SetCursorPosition(offset + first, Y + i);
                Console.Write(pT[i][j]);


                i     = 1; j = 0;
                first = (1 + half) * (level - i - 1);
                Console.SetCursorPosition(offset + first, Y + i);
                Console.Write(pT[i][j]);
                j    = 1;
                next = offset + first + (1 + half + s) + ((half + 1 + half) + s) * (j - 1);

                currString = $"{pT[i][j-1]}";
                spaceLeft  = (longest - currString.Length) / 2;
                Console.SetCursorPosition(next + spaceLeft, Y + i);
                Console.Write(pT[i][j - 1]);
            }

            if (level > 2)
            {
                for (i = 2; i < level; i++)
                {
                    j     = 0;
                    first = (1 + half) * (level - i - 1);
                    Console.SetCursorPosition(offset + first, Y + i);
                    Console.Write(pT[i][j]);

                    pos = ((i + 1) / 2 + (i + 1) % 2);

                    for (j = 1; j < (pos - 1); j++)
                    {
                        next = offset + first + (1 + half + s) + ((half + 1 + half) + s) * (j - 1);

                        currString = $"{pT[i][j]}";
                        spaceLeft  = (longest - currString.Length) / 2;

                        Console.SetCursorPosition(next + spaceLeft, Y + i);
                        Console.Write(pT[i][j]);
                    }

                    // окончили цикл j == pos - 1
                    // это либо средний элемент (если в уровне нечётное кол-во элементов)
                    // либо последний элемен, а следующий такой же (если в уровне чётное кол-во элементов)
                    // но для 3 и 4 уровней цикл выше не работает, когда всего два элемента в массиве,
                    // т.к. pos равен 2, pos - 1 равен 1, а j уже 1.

                    // выводим центральный элемент (если уровень нечётный)
                    // или 2 однаковых центральных элемента (если уровнь чётный)

                    if ((i + 1) % 2 == 1)    // если нечётный уровень, когда считаем уровни с 1,
                    {                        // то элемента  pT[i - 1][pos] не существует
                        next       = offset + first + (1 + half + s) + ((half + 1 + half) + s) * (j - 1);
                        currString = $"{pT[i][j]}";
                        spaceLeft  = (longest - currString.Length) / 2;

                        Console.SetCursorPosition(next + spaceLeft, Y + i);
                        Console.Write(pT[i][j]);
                    }
                    else // если чётная, когда считаем уровни с 1, то существует,
                    {    // и мы как бы делаем последнюю итерацию цикла выше, но уже с j равным pos - 1
                        next       = offset + first + (1 + half + s) + ((half + 1 + half) + s) * (j - 1);
                        currString = $"{pT[i][j]}";
                        spaceLeft  = (longest - currString.Length) / 2;

                        Console.SetCursorPosition(next + spaceLeft, Y + i);
                        Console.Write(pT[i][j]);

                        j++;

                        next       = offset + first + (1 + half + s) + ((half + 1 + half) + s) * (j - 1);
                        currString = $"{pT[i][j-1]}";
                        spaceLeft  = (longest - currString.Length) / 2;
                        spaceLeft += (currString.Length % 2 == 0) ? 1 : 0;

                        Console.SetCursorPosition(next + spaceLeft, Y + i);
                        Console.Write(pT[i][j - 1]);
                    }
                    j++;

                    for (int k = (pos - 1 - 1); k >= 0; k--)
                    {
                        next       = offset + first + (1 + half + s) + ((half + 1 + half) + s) * (j - 1);
                        currString = $"{pT[i][k]}";
                        spaceLeft  = (longest - currString.Length) / 2;
                        spaceLeft += (currString.Length % 2 == 0) ? 1: 0;

                        Console.SetCursorPosition(next + spaceLeft, Y + i);
                        Console.Write(pT[i][k]);
                        j++;
                    } // выводим правое крыло
                }     // for i
            }
            Console.WriteLine();

            #endregion вывод массива на экран

            Console.WriteLine();
            Console.WriteLine("Нажмите любую клавишу");
            Console.ReadKey();
        }
        static void Main(string[] args)
        {
            #region Задание 1.
            // Заказчик просит вас написать приложение по учёту финансов
            // и продемонстрировать его работу.
            // Суть задачи в следующем:
            // Руководство фирмы по 12 месяцам ведет учет расходов и поступлений средств.
            // За год получены два массива – расходов и поступлений.
            // Определить прибыли по месяцам
            // Количество месяцев с положительной прибылью.
            // Добавить возможность вывода трех худших показателей по месяцам, с худшей прибылью,
            // если есть несколько месяцев, в которых худшая прибыль совпала - вывести их все.
            // Организовать дружелюбный интерфейс взаимодействия и вывода данных на экран

            // Пример
            //
            // Месяц      Доход, тыс. руб.  Расход, тыс. руб.     Прибыль, тыс. руб.
            //     1              100 000             80 000                 20 000
            //     2              120 000             90 000                 30 000
            //     3               80 000             70 000                 10 000
            //     4               70 000             70 000                      0
            //     5              100 000             80 000                 20 000
            //     6              200 000            120 000                 80 000
            //     7              130 000            140 000                -10 000
            //     8              150 000             65 000                 85 000
            //     9              190 000             90 000                100 000
            //    10              110 000             70 000                 40 000
            //    11              150 000            120 000                 30 000
            //    12              100 000             80 000                 20 000
            //
            // Худшая прибыль в месяцах: 7, 4, 1, 5, 12
            // Месяцев с положительной прибылью: 10
            #endregion

            #region * Задание 2
            // Заказчику требуется приложение строящее первых N строк треугольника паскаля. N < 25
            //
            // При N = 9. Треугольник выглядит следующим образом:
            //                                 1
            //                             1       1
            //                         1       2       1
            //                     1       3       3       1
            //                 1       4       6       4       1
            //             1       5      10      10       5       1
            //         1       6      15      20      15       6       1
            //     1       7      21      35      35       21      7       1
            //
            //
            // Простое решение:
            // 1
            // 1
            // 1       2
            // 1       3
            // 1       4       6
            // 1       5      10
            // 1       6      15      20      15       6       1
            // 1       7      21      35      35       21      7       1
            //
            // Справка: https://ru.wikipedia.org/wiki/Треугольник_Паскаля
            #endregion

            #region * Задание 3.1
            // Заказчику требуется приложение позволяющщее умножать математическую матрицу на число
            // Справка https://ru.wikipedia.org/wiki/Матрица_(математика)
            // Справка https://ru.wikipedia.org/wiki/Матрица_(математика)#Умножение_матрицы_на_число
            // Добавить возможность ввода количество строк и столцов матрицы и число,
            // на которое будет производиться умножение.
            // Матрицы заполняются автоматически.
            // Если по введённым пользователем данным действие произвести невозможно - сообщить об этом
            //
            // Пример
            //
            //      |  1  3  5  |   |  5  15  25  |
            //  5 х |  4  5  7  | = | 20  25  35  |
            //      |  5  3  1  |   | 25  15   5  |
            //
            //
            // ** Задание 3.2
            // Заказчику требуется приложение позволяющщее складывать и вычитать математические матрицы
            // Справка https://ru.wikipedia.org/wiki/Матрица_(математика)
            // Справка https://ru.wikipedia.org/wiki/Матрица_(математика)#Сложение_матриц
            // Добавить возможность ввода количество строк и столцов матрицы.
            // Матрицы заполняются автоматически
            // Если по введённым пользователем данным действие произвести невозможно - сообщить об этом
            //
            // Пример
            //  |  1  3  5  |   |  1  3  4  |   |  2   6   9  |
            //  |  4  5  7  | + |  2  5  6  | = |  6  10  13  |
            //  |  5  3  1  |   |  3  6  7  |   |  8   9   8  |
            //
            //
            //  |  1  3  5  |   |  1  3  4  |   |  0   0   1  |
            //  |  4  5  7  | - |  2  5  6  | = |  2   0   1  |
            //  |  5  3  1  |   |  3  6  7  |   |  2  -3  -6  |
            //
            // *** Задание 3.3
            // Заказчику требуется приложение позволяющщее перемножать математические матрицы
            // Справка https://ru.wikipedia.org/wiki/Матрица_(математика)
            // Справка https://ru.wikipedia.org/wiki/Матрица_(математика)#Умножение_матриц
            // Добавить возможность ввода количество строк и столцов матрицы.
            // Матрицы заполняются автоматически
            // Если по введённым пользователем данным действие произвести нельзя - сообщить об этом
            //
            //  |  1  3  5  |   |  1  3  4  |   | 22  48  57  |
            //  |  4  5  7  | х |  2  5  6  | = | 35  79  95  |
            //  |  5  3  1  |   |  3  6  7  |   | 14  36  45  |
            //
            //
            //                  | 4 |
            //  |  1  2  3  | х | 5 | = | 32 |
            //                  | 6 |
            #endregion

            ConsoleKey action;       // Переменная, в которую будет считываться нажатие клавиши
            #region example of key reading
            //do
            //{
            //    Console.WriteLine("Press a key, together with Alt, Ctrl, or Shift.");
            //    Console.WriteLine("Press Esc to exit.");
            //    action = Console.ReadKey(true);

            //    StringBuilder output = new StringBuilder(
            //                  String.Format("You pressed {0}", action.Key.ToString()));
            //    bool modifiers = false;

            //    if ((action.Modifiers & ConsoleModifiers.Alt) == ConsoleModifiers.Alt)
            //    {
            //        output.Append(", together with " + ConsoleModifiers.Alt.ToString());
            //        modifiers = true;
            //    }
            //    if ((action.Modifiers & ConsoleModifiers.Control) == ConsoleModifiers.Control)
            //    {
            //        if (modifiers)
            //        {
            //            output.Append(" and ");
            //        }
            //        else
            //        {
            //            output.Append(", together with ");
            //            modifiers = true;
            //        }
            //        output.Append(ConsoleModifiers.Control.ToString());
            //    }
            //    if ((action.Modifiers & ConsoleModifiers.Shift) == ConsoleModifiers.Shift)
            //    {
            //        if (modifiers)
            //        {
            //            output.Append(" and ");
            //        }
            //        else
            //        {
            //            output.Append(", together with ");
            //            modifiers = true;
            //        }
            //        output.Append(ConsoleModifiers.Shift.ToString());
            //    }
            //    output.Append(".");
            //    Console.WriteLine(output.ToString());
            //    Console.WriteLine();
            //} while (action.Key != ConsoleKey.Escape);
            #endregion example of key reading

            Console.CursorVisible = false;  // Делаем курсор невидимым
            var winHeight = 20;             // Высота экрана (для меню) 20 строк
            var winWidth  = 80;             // Ширина экрана (для меню) 80 строк
            int currItem  = 1;              // текущая позиция меню

            WindowOutput    window;
            FinancialReport financialReport;
            PascalTriangle  pascalTriangle;
            Matrix          matrix;

            MenuItem[] menuItems =          // Пункты меню для вывода на экран
            { new MenuItem            {
                  itemKey = ConsoleKey.D1, itemName = "1.   ФИНАНСОВЫЙ УЧЁТ В КОМПАНИИ"
              },
              new MenuItem {
                  itemKey = ConsoleKey.D2, itemName = "2.   ТРЕУГОЛЬНИК ПАСКАЛЯ"
              },
              new MenuItem {
                  itemKey = ConsoleKey.D3, itemName = "3.   ОПЕРАЦИИ С МАТРИЦАМИ"
              },
              new MenuItem {
                  itemKey = ConsoleKey.Escape, itemName = "ESC  ВЫХОД"
              } };

            window          = new WindowOutput(winWidth, winHeight);
            financialReport = new FinancialReport();
            pascalTriangle  = new PascalTriangle();
            matrix          = new Matrix();

            do                  // Считываем нажатия, пока не будет ESC
            {
                window.newWindow(winWidth, winHeight);
                window.HeaderCenter("Домашняя работа  №4", winWidth, 2, ConsoleColor.Yellow);
                window.HeaderCenter("Дмитрий Мельников", winWidth, 3, ConsoleColor.Yellow);

                action = window.MenuSelect(menuItems, currItem, winWidth, 5);

                switch (action)
                {
                case ConsoleKey.D1:
                    financialReport.financialReportMenu();
                    currItem = 1;
                    break;

                case ConsoleKey.D2:
                    pascalTriangle.printPascalTriangle();
                    currItem = 2;
                    break;

                case ConsoleKey.D3:
                    matrix.matrixMenu();
                    currItem = 3;
                    break;

                case ConsoleKey.Escape:
                    break;

                default:
                    break;       // нажата любая другая клавиша - ничего не происходит
                }
            } while (action != ConsoleKey.Escape);
        }