Кликер: игра с сохранением

Текстовая игра, которая помнит прогресс между запусками.

Код

// Кликер — текстовая игра на языке Сфера. Сохраняет прогресс между
// запусками в файл "кликер_сохранение.txt" — простой текстовый формат:
// "очки\nочков_за_клик" (два числа, разделённые переводом строки).

структура Улучшение
    текст название;
    целое цена;
    целое бонус;
конец

структура СостояниеИгры
    целое очки;
    целое очков_за_клик;
конец

функция сохранить_игру(целое очки, целое очков_за_клик): результат из верного
    текст данные = целое_в_текст(очки) + "\n" + целое_в_текст(очков_за_клик);
    вернуть записать_файл("кликер_сохранение.txt", данные);
конец

функция загрузить_игру(): результат из СостояниеИгры
    результат из текста файл_результат = прочитать_файл("кликер_сохранение.txt");
    если ( не файл_результат.успешно)
        вернуть ошибка(файл_результат.сообщение);
    конец
    текст данные = файл_результат.значение;

    результат из целого позиция_результат = найти(данные, "\n");
    если ( не позиция_результат.успешно)
        вернуть ошибка("повреждённый файл сохранения (нет разделителя)");
    конец
    целое инд = позиция_результат.значение;

    результат из текста текст_очков = подстрока(данные, 0, инд);
    если ( не текст_очков.успешно)
        вернуть ошибка("повреждённый файл сохранения");
    конец

    целое остаток_начало = инд + 1;
    целое остаток_длина = длина(данные) - остаток_начало;
    результат из текста текст_бонуса = подстрока(данные, остаток_начало, остаток_длина);
    если ( не текст_бонуса.успешно)
        вернуть ошибка("повреждённый файл сохранения");
    конец

    результат из целого очки_результат = текст_в_целое(текст_очков.значение);
    если ( не очки_результат.успешно)
        вернуть ошибка("повреждённый файл сохранения (очки не число)");
    конец
    результат из целого бонус_результат = текст_в_целое(текст_бонуса.значение);
    если ( не бонус_результат.успешно)
        вернуть ошибка("повреждённый файл сохранения (бонус не число)");
    конец

    вернуть успех(СостояниеИгры(очки_результат.значение, бонус_результат.значение));
конец

функция главная(): целое
    целое очки = 0;
    целое очков_за_клик = 1;

    результат из СостояниеИгры загрузка = загрузить_игру();
    если (загрузка.успешно)
        очки = загрузка.значение.очки;
        очков_за_клик = загрузка.значение.очков_за_клик;
        вывести("Прогресс загружен. Очки:");
        вывести(очки);
    конец

    Список из Улучшение магазин = Список из Улучшение();
    магазин.добавить(Улучшение("Быстрые пальцы", 10, 1));
    магазин.добавить(Улучшение("Механическая клавиатура", 50, 3));
    магазин.добавить(Улучшение("Автокликер", 200, 10));

    вывести("=== Кликер ===");
    вывести("Команды: к (клик), м (магазин), с (статистика), 1/2/3 (купить улучшение), сх (сохранить), в (выход)");

    верно продолжать = да;
    пока (продолжать)
        результат из текста ввод = прочитать_строку();
        если ( не ввод.успешно)
            продолжать = нет;
        иначе
            текст команда = ввод.значение;

            если (команда == "к")
                очки = очки + очков_за_клик;
                вывести(очки);
            иначе если (команда == "с")
                вывести("Очки:");
                вывести(очки);
                вывести("Очков за клик:");
                вывести(очков_за_клик);
            иначе если (команда == "м")
                вывести("=== Магазин ===");
                целое индекс = 0;
                пока (индекс меньше магазин.размер())
                    Улучшение у = магазин.получить(индекс);
                    вывести(у.название);
                    вывести(у.цена);
                    индекс = индекс + 1;
                конец
            иначе если (команда == "1" или команда == "2" или команда == "3")
                результат из целого номер_результат = текст_в_целое(команда);
                если (номер_результат.успешно)
                    целое номер = номер_результат.значение - 1;
                    если (номер не меньше 0 и номер меньше магазин.размер())
                        Улучшение выбранное = магазин.получить(номер);
                        если (очки не меньше выбранное.цена)
                            очки = очки - выбранное.цена;
                            очков_за_клик = очков_за_клик + выбранное.бонус;
                            вывести("Куплено:");
                            вывести(выбранное.название);
                        иначе
                            вывести("Не хватает очков");
                        конец
                    конец
                конец
            иначе если (команда == "сх")
                результат из верного сохранение = сохранить_игру(очки, очков_за_клик);
                если (сохранение.успешно)
                    вывести("Прогресс сохранён");
                иначе
                    вывести("Не удалось сохранить прогресс:");
                    вывести(сохранение.сообщение);
                конец
            иначе если (команда == "в")
                сохранить_игру(очки, очков_за_клик);
                продолжать = нет;
            иначе
                вывести("Неизвестная команда");
            конец
        конец
    конец

    вывести("Игра окончена. Итоговые очки:");
    вывести(очки);

    вернуть 0;
конец

Как запустить

Сохраните код в файл, например кликер.код, и выполните:

запустить кликер.код

Как это работает

  • Состояние игры хранится в структуре СостояниеИгры.
  • Сохранение и загрузка идут через файл. Функции возвращают результат из ..., чтобы обработать повреждённый файл.
  • Пример показывает, как разбить небольшую программу на функции.

Исходник лежит в репозитории: examples/кликер.код.