Изучение C#. Урок 2. Работа с реестром

Олдфаг
Статус
Оффлайн
Регистрация
18 Фев 2019
Сообщения
2,825
Реакции[?]
1,852
Поинты[?]
24K
Всем привет! Моя недавняя тема по созданию простейшей игры на C# получила относительную для этого раздела популярность. Я давно хотел ее продолжить, но что-то никак не доходили руки :kappa:. Во второй части создания этого "чудо" проекта я покажу, как сохранять всю информацию в реестр и воспроизводить ее от-туда (до этого хотел показать создание многопользовательской игры, посредствам передачи сокетов, но подумал отложить это идею до лучших времен).

Показывать, как размещать элементы на форме (как передвинуть кнопки и добавить menuStrip), я не буду, так как эта информация не пригодится почти никому (я полагаю, что большая часть, читающая данную тему понимает, как добавить элемент на форму) и займет достаточно много места в самой статье.

Первым делом создадим переменную, в которой будет храниться история побед. Формат записи: 0/1/2, где 0 - ничья, 1 - победа Х, а 2 - победа 0, / - разделитель
string WinsReg = "";
Далее, будем добавлять один символ в WinsReg после победы одной из сторон или ничьи
WinsReg += "/2";
Добавим сразу после
1570125053657.png
Аналогично делаем с крестиками (+="/1") и ничьей (+="/0").

Отлично, теперь нужно создать класс для работы с реестром и начинать работу с ним. Я назвал класс Memory, вы можете придумать что-то более оригинальное.
Для начала, подключим класс для работы с самим реестром системы using Microsoft.Win32; и напишем нужные для нас функции.
Код:
static string regKeyName = "Software\\Yougame.biz\\TicTacToe";
public static string WinsKey = "";
Чтобы было меньше кода, я создал переменную regKeyName, в которой будет храниться "путь" к нашему ключу в реестре.
WinsKey нужен для загрузки побед в WinsReg из нашей первой формы. Были и другие идеи, но эта оказалась наиболее простой и красивой (но это не точно :roflanEbalo:).
Теперь, создадим функцию записи значений в реестр (также она создает ключ по нашему "пути")
Код:
public static void WriteMemory(string Wins) // Публичная функция записи переменных в реестр
        {
            // Wins - переменная со статистикой побед. Записывать их мы будем в формате 1/2/1/1/2/0, где 0 - ничья, 1 - крестики, 2 - нолики, а / - разделитель

            RegistryKey rk = null; // Создаем переменную класса RegistryKey для работы с ключами реестра

            try // try (с англ. "пытаться") - пробуем занести переменные в реестр
            {
                rk = Registry.CurrentUser.CreateSubKey(regKeyName); // Создаем ключ в реестре по пути, указанном в regKeyName
                if (rk == null) return; // Если создание ключа не удалось (по каким-либо причинам закрыт доступ к реестру), то rk остается равным null (нулю)
                rk.SetValue("Wins", Wins); // Создаем еще один ключ из переменной Wins
            }

            finally // Цикл, выполняющийся при ошибке/при успешном выполнении try(), т.е. всегда
            {
                if (rk != null) rk.Close(); // Если программа создала новый ключ (rk получит доступ к реестру и создаст коюч из regKeyName), закрываем поток
            }
        }
Теперь, написав Memory.WriteMemory("Irval") в любой (почти) части кода из Form1.cs, мы получим это (
Пожалуйста, авторизуйтесь для просмотра ссылки.
), но то, что мы получили никак не касается "Крестиков-ноликов", поэтому нужно это удалить :roflanEbalo:.
После создания функции записи в реестр, нужно также создать функцию чтения реестра
Код:
public static void ReadMemory() // Функция чтение реестра
        {
            RegistryKey rk = null; // Повторно создаем переменную класса для работы с ключами

            try
            {
                rk = Registry.CurrentUser.CreateSubKey(regKeyName); // Создаем новый ключ

                if (rk != null) // Если создание ключа удалось, то выполняем следующие действия
                {
                    WinsKey = (string)rk.GetValue("Wins"); // Записываем информацию в переменную Wins
                }
            }
            finally
            {
                if (rk != null) rk.Close(); // Закрываем поток
            }
        }
Теперь, написав Memory.ReadMemory() там же, где мы писали вызов функции WriteMemory(), мы изменим значения переменной WinsKey на "Irval", так как программа считала значение с реестра. Поздравляю, этот код тоже нужно стирать :roflanEbalo:.
Осталось только использовать наши функции из класса Memory в главном файле - Form1.cs
Запихиваем это в обработчик загрузки формы (Form1_Load())
Код:
// Обновляем  Wins
            Memory.ReadMemory();
            WinsReg = Memory.WinsKey;

            if (WinsReg == null)
                Memory.WriteMemory(""); // Создаем ключ в реестре с победами, если его нет или он был удален

            Memory.ReadMemory();
            WinsReg = Memory.WinsKey; // Повторно задаем значения WinsReg. Можно было сделать иначе, например создать функцию обновления, но я посчитал это лишним
Дальнейший код я хотел расписать более подробно в самой статье, но из-за ограничения на повторяющиеся BB-коды, я запихну все в один элемент
Код:
private void Form1_FormClosing(object sender, FormClosingEventArgs e) // Обработчик события выхода из формы. Возникает до того, как форма была закрыта
        {
            Memory.WriteMemory(WinsReg); // Записываем значение WinsReg в реестр
        }

        private void ВыходToolStripMenuItem_Click(object sender, EventArgs e) // Событие нажатия на "Выход" из нашего ToolStrip
        {
            this.Close(); // Закрываем форму
        }

        private void СтатистикаToolStripMenuItem_Click(object sender, EventArgs e) // Событие нажатия на "Статистику" из ToolStrip на форме
        {
            String[] AllWins = WinsReg.Split(new char[] { '/' }, StringSplitOptions.None); // Массив с победами. Он понадобится для подсчета выигрышей каждой стороны
            int[] EachWins = { 0, 0, 0 }; // Итоговый массив побед
            for (int i = 0; i < AllWins.Length; i++) // Перебираем все элементы массива AllWins. Можно было использовать foreach
            {
                switch(AllWins[i]) // switch для каждого из трех значений элемента из AllWins
                {
                    case "0": // 0 значение - ничья
                        {
                            EachWins[0]++; // Прибавляем 1 к ничьим
                            break; // Выход из switch
                        }
                    case "1": // 1 значение - победа крестиков
                        {
                            EachWins[1]++; // Прибавляем 1 к крестикам
                            break;
                        }
                    case "2": // 2 значение - победа ноликов
                        {
                            EachWins[2]++; // Прибавляем 1 к ноликам
                            break;
                        }
                }
            }
          
            // Объявление переменных с процентом побед
            decimal Wx = 0;
            decimal Wo = 0;
            decimal Draw = 0;

            if (EachWins[0] + EachWins[1] + EachWins[2] != 0)  // Если произойдет попытка деления на ноль
            {
                //Подсчет процентов побед
                Wx = (Int32)(EachWins[1] / ((EachWins[0] + EachWins[1] + EachWins[2]) / 100M));
                Wo = (Int32)(EachWins[2] / ((EachWins[0] + EachWins[1] + EachWins[2]) / 100M));
                Draw = (Int32)(EachWins[0] / ((EachWins[0] + EachWins[1] + EachWins[2]) / 100M));
            }

            MessageBox.Show("Побед крестиков: " + EachWins[1] + " (" + Wx + "%)" + "\n" + "Побед ноликов: " + EachWins[2] + " (" + Wo + "%)" + "\n" + "Ничьих: " + EachWins[0] + " (" + Draw + "%)", "Статистика", MessageBoxButtons.OK); // Выводим MessageBox со статистикой побед


        private void СбросToolStripMenuItem_Click(object sender, EventArgs e) // Событие нажатия на кнопку сброса из ToolStrip
        {
            WinsReg = ""; // Сбрасываем переменную WinReg. При закрытии формы, ее значение занесется в реестр
            MessageBox.Show("Статистика была обнулена!", "Статистика", MessageBoxButtons.OK); // Вывод сообщения о сбросе статистики
        }
Обработчики событий этих элементов вы найдете сами, надеюсь, что не глупые :roflanBuldiga:

А вот и итоговый скриншот нашей игры:
1570126215482.png

Также можно добавить запрос на запуск с правами администратора. Для этого, добавьте в Program.cs следующий код:
Пожалуйста, авторизуйтесь для просмотра ссылки.


Если же у вас есть пожелания к новым урокам или я допустил ошибку в коде/в оформлении гайда, прошу отписать мне в лс или же в саму тему.

Готовый исходник игры с дополнительными пояснениями:
Пожалуйста, авторизуйтесь для просмотра ссылки.

Готовая игра:
Пожалуйста, авторизуйтесь для просмотра ссылки.

VT на игру:
Пожалуйста, авторизуйтесь для просмотра ссылки.
 
Последнее редактирование:
HvH BoY
Начинающий
Статус
Оффлайн
Регистрация
20 Июн 2019
Сообщения
201
Реакции[?]
26
Поинты[?]
1K
Всем привет! Моя недавняя тема по созданию простейшей игры на C# получила относительную для этого раздела популярность. Я давно хотел ее продолжить, но что-то никак не доходили руки :kappa:. Во второй части создания этого "чудо" проекта я покажу, как сохранять всю информацию в реестр и воспроизводить ее от-туда (до этого хотел показать создание многопользовательской игры, посредствам передачи сокетов, но подумал отложить это идею до лучших времен).

Показывать, как размещать элементы на форме (как передвинуть кнопки и добавить menuStrip), я не буду, так как эта информация не пригодится почти никому (я полагаю, что большая часть, читающая данную тему понимает, как добавить элемент на форму) и займет достаточно много места в самой статье.

Первым делом создадим переменную, в которой будет храниться история побед. Формат записи: 0/1/2, где 0 - ничья, 1 - победа Х, а 2 - победа 0, / - разделитель
string WinsReg = "";
Далее, будем добавлять один символ в WinsReg после победы одной из сторон или ничьи
WinsReg += "/2";
Добавим сразу после
Посмотреть вложение 44028
Аналогично делаем с крестиками (+="/1") и ничьей (+="/0").

Отлично, теперь нужно создать класс для работы с реестром и начинать работу с ним. Я назвал класс Memory, вы можете придумать что-то более оригинальное.
Для начала, подключим класс для работы с самим реестром системы using Microsoft.Win32; и напишем нужные для нас функции.
Код:
static string regKeyName = "Software\\Yougame.biz\\TicTacToe";
public static string WinsKey = "";
Чтобы было меньше кода, я создал переменную regKeyName, в которой будет храниться "путь" к нашему ключу в реестре.
WinsKey нужен для загрузки побед в WinsReg из нашей первой формы. Были и другие идеи, но эта оказалась наиболее простой и красивой (но это не точно :roflanEbalo:).
Теперь, создадим функцию записи значений в реестр (также она создает ключ по нашему "пути")
Код:
public static void WriteMemory(string Wins) // Публичная функция записи переменных в реестр
        {
            // Wins - переменная со статистикой побед. Записывать их мы будем в формате 1/2/1/1/2/0, где 0 - ничья, 1 - крестики, 2 - нолики, а / - разделитель

            RegistryKey rk = null; // Создаем переменную класса RegistryKey для работы с ключами реестра

            try // try (с англ. "пытаться") - пробуем занести переменные в реестр
            {
                rk = Registry.CurrentUser.CreateSubKey(regKeyName); // Создаем ключ в реестре по пути, указанном в regKeyName
                if (rk == null) return; // Если создание ключа не удалось (по каким-либо причинам закрыт доступ к реестру), то rk остается равным null (нулю)
                rk.SetValue("Wins", Wins); // Создаем еще один ключ из переменной Wins
            }

            finally // Цикл, выполняющийся при ошибке/при успешном выполнении try(), т.е. всегда
            {
                if (rk != null) rk.Close(); // Если программа создала новый ключ (rk получит доступ к реестру и создаст коюч из regKeyName), закрываем поток
            }
        }
Теперь, написав Memory.WriteMemory("Irval") в любой (почти) части кода из Form1.cs, мы получим это (
Пожалуйста, авторизуйтесь для просмотра ссылки.
), но то, что мы получили никак не касается "Крестиков-ноликов", поэтому нужно это удалить :roflanEbalo:.
После создания функции записи в реестр, нужно также создать функцию чтения реестра
Код:
public static void ReadMemory() // Функция чтение реестра
        {
            RegistryKey rk = null; // Повторно создаем переменную класса для работы с ключами

            try
            {
                rk = Registry.CurrentUser.CreateSubKey(regKeyName); // Создаем новый ключ

                if (rk != null) // Если создание ключа удалось, то выполняем следующие действия
                {
                    WinsKey = (string)rk.GetValue("Wins"); // Записываем информацию в переменную Wins
                }
            }
            finally
            {
                if (rk != null) rk.Close(); // Закрываем поток
            }
        }
Теперь, написав Memory.ReadMemory() там же, где мы писали вызов функции WriteMemory(), мы изменим значения переменной WinsKey на "Irval", так как программа считала значение с реестра. Поздравляю, этот код тоже нужно стирать :roflanEbalo:.
Осталось только использовать наши функции из класса Memory в главном файле - Form1.cs
Запихиваем это в обработчик загрузки формы (Form1_Load())
Код:
// Обновляем  Wins
            Memory.ReadMemory();
            WinsReg = Memory.WinsKey;

            if (WinsReg == null)
                Memory.WriteMemory(""); // Создаем ключ в реестре с победами, если его нет или он был удален

            Memory.ReadMemory();
            WinsReg = Memory.WinsKey; // Повторно задаем значения WinsReg. Можно было сделать иначе, например создать функцию обновления, но я посчитал это лишним
Дальнейший код я хотел расписать более подробно в самой статье, но из-за ограничения на повторяющиеся BB-коды, я запихну все в один элемент
Код:
private void Form1_FormClosing(object sender, FormClosingEventArgs e) // Обработчик события выхода из формы. Возникает до того, как форма была закрыта
        {
            Memory.WriteMemory(WinsReg); // Записываем значение WinsReg в реестр
        }

        private void ВыходToolStripMenuItem_Click(object sender, EventArgs e) // Событие нажатия на "Выход" из нашего ToolStrip
        {
            this.Close(); // Закрываем форму
        }

        private void СтатистикаToolStripMenuItem_Click(object sender, EventArgs e) // Событие нажатия на "Статистику" из ToolStrip на форме
        {
            String[] AllWins = WinsReg.Split(new char[] { '/' }, StringSplitOptions.None); // Массив с победами. Он понадобится для подсчета выигрышей каждой стороны
            int[] EachWins = { 0, 0, 0 }; // Итоговый массив побед
            for (int i = 0; i < AllWins.Length; i++) // Перебираем все элементы массива AllWins. Можно было использовать foreach
            {
                switch(AllWins[i]) // switch для каждого из трех значений элемента из AllWins
                {
                    case "0": // 0 значение - ничья
                        {
                            EachWins[0]++; // Прибавляем 1 к ничьим
                            break; // Выход из switch
                        }
                    case "1": // 1 значение - победа крестиков
                        {
                            EachWins[1]++; // Прибавляем 1 к крестикам
                            break;
                        }
                    case "2": // 2 значение - победа ноликов
                        {
                            EachWins[2]++; // Прибавляем 1 к ноликам
                            break;
                        }
                }
            }
         
            // Объявление переменных с процентом побед
            decimal Wx = 0;
            decimal Wo = 0;
            decimal Draw = 0;

            if (EachWins[0] + EachWins[1] + EachWins[2] != 0)  // Если произойдет попытка деления на ноль
            {
                //Подсчет процентов побед
                Wx = (Int32)(EachWins[1] / ((EachWins[0] + EachWins[1] + EachWins[2]) / 100M));
                Wo = (Int32)(EachWins[2] / ((EachWins[0] + EachWins[1] + EachWins[2]) / 100M));
                Draw = (Int32)(EachWins[0] / ((EachWins[0] + EachWins[1] + EachWins[2]) / 100M));
            }

            MessageBox.Show("Побед крестиков: " + EachWins[1] + " (" + Wx + "%)" + "\n" + "Побед ноликов: " + EachWins[2] + " (" + Wo + "%)" + "\n" + "Ничьих: " + EachWins[0] + " (" + Draw + "%)", "Статистика", MessageBoxButtons.OK); // Выводим MessageBox со статистикой побед


        private void СбросToolStripMenuItem_Click(object sender, EventArgs e) // Событие нажатия на кнопку сброса из ToolStrip
        {
            WinsReg = ""; // Сбрасываем переменную WinReg. При закрытии формы, ее значение занесется в реестр
            MessageBox.Show("Статистика была обнулена!", "Статистика", MessageBoxButtons.OK); // Вывод сообщения о сбросе статистики
        }
Обработчики событий этих элементов вы найдете сами, надеюсь, что вы не глупые :roflanBuldiga:

А вот и итоговый скриншот нашей игры:
Посмотреть вложение 44030

Также можно добавить запрос на запуск с правами администратора. Для этого, добавьте в Program.cs следующий код:
Пожалуйста, авторизуйтесь для просмотра ссылки.


Если же у вас есть пожелания к новым урокам или я допустил ошибку в коде/в оформлении гайда, прошу отписать мне в лс или же в саму тему.

Готовый исходник игры с дополнительными пояснениями:
Пожалуйста, авторизуйтесь для просмотра ссылки.

Готовая игра:
Пожалуйста, авторизуйтесь для просмотра ссылки.

VT на игру:
Пожалуйста, авторизуйтесь для просмотра ссылки.
Ля но почиму так сложно ?
 
Пользователь
Статус
Оффлайн
Регистрация
29 Дек 2018
Сообщения
416
Реакции[?]
109
Поинты[?]
2K
Олдфаг
Статус
Оффлайн
Регистрация
18 Фев 2019
Сообщения
2,825
Реакции[?]
1,852
Поинты[?]
24K
Я оставил ссылку на скачивание сурса с пояснением почти каждой строчки. Там все более, чем понятно. Я не смог все разъяснить из-за ограничения по bb-кодам
 
Сверху Снизу