/
MrFish
/
CSharpGameProject
Обзор
Документация
Войти
/
MrFish
/
CSharpGameProject
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
MainGameProject/SaveData.cs
401 строка
17 KB
Yaroslav4444-bauer
Кодстайл - исправлены сообщения
20 дек 2025, 14:46
20 дек 2025, 14:46
5149f1a
Код
Авторство
О чём код?
using System; using System.IO; using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; namespace MainGameProject { // Класс сохранения текущего состояния игры [Serializable] public class SaveData { public Board? Board { get; set; } public Player? Player1 { get; set; } public Player? Player2 { get; set; } public bool IsPlayer1Turn { get; set; } public int GamePlayerIteration { get; set; } public int StartTurnTime { get; set; } public List<GameMove>? GameMoves { get; set; } public Stack<GameState>? GameHistoryForUndo { get; set; } public DateTime SaveTime { get; set; } public string? SaveName { get; set; } // Конструктор для десериализации JSON public SaveData() { IsPlayer1Turn = true; GamePlayerIteration = 0; StartTurnTime = 45000; SaveTime = DateTime.Now; } // Основной конструктор (получает текущее состояние игры) public SaveData( Board board, Player player1, Player player2, bool isPlayer1Turn, int gamePlayerIteration, int startTurnTime, List<GameMove> gameMoves, Stack<GameState> gameHistoryForUndo, string saveName ) { Board = board; Player1 = player1; Player2 = player2; IsPlayer1Turn = isPlayer1Turn; GamePlayerIteration = gamePlayerIteration; StartTurnTime = startTurnTime; GameMoves = gameMoves; GameHistoryForUndo = gameHistoryForUndo; SaveTime = DateTime.Now; SaveName = saveName; } } // Класс - файловый менеджер public static class SaveManager { // Определение директории для игровых файлов, а также пути к ней private static readonly string SaveDirectory = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ChroniclesOfMages", "Saves" ); // Определение опций для серилизации JSON (для загрузки и выгрузки состояния) private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true, // Makes saves human-readable IncludeFields = false, // Only serialize properties Converters = { new JsonStringEnumConverter() } // Serialize enums as strings }; static SaveManager() { // Если директории нет - создаём новую if (!Directory.Exists(SaveDirectory)) { Directory.CreateDirectory(SaveDirectory); } } // Функция сохранения игрового состояния в JSON public static void SaveGame(Game game, string saveName) { try { // Подготовка данных var saveData = new SaveData( game.Board, game.Player1, game.Player2, game.IsPlayer1Turn, game.GamePlayerIteration, game.TurnTime, HistoryGameMoves.GameMoves, game.gameHistory, saveName ); // Преобразовываем имя сохранения для filename string cleanSaveName = CleanFileName(saveName); string fileName = $"{cleanSaveName}_{DateTime.Now:yyyyMMdd_HHmmss}.json"; string filePath = Path.Combine(SaveDirectory, fileName); // Сериализация в JSON string json = JsonSerializer.Serialize(saveData, JsonOptions); File.WriteAllText(filePath, json); Console.WriteLine($"Game saved successfully as: {saveName}"); Console.WriteLine($"Location: {filePath}"); } catch (Exception ex) // В случае неудачи обрабатываем исключение { Console.WriteLine($"Error saving game: {ex.Message}"); } } // Функция выгрузки игрового состояния из JSON public static Game? LoadGame(string filePath) { try { // Если файл не обнаружен if (!File.Exists(filePath)) { Console.WriteLine("Save file not found!"); return null; } // Чтение и десериализация JSON string json = File.ReadAllText(filePath); var saveData = JsonSerializer.Deserialize<SaveData>(json, JsonOptions); if (saveData == null) // При неудачном извлечении { Console.WriteLine("Failed to parse save file."); return null; } // Создание игры в загруженными данными var game = new Game { Board = saveData.Board ?? throw new InvalidOperationException("Board is null in save data"), Player1 = saveData.Player1 ?? throw new InvalidOperationException("Player1 is null in save data"), Player2 = saveData.Player2 ?? throw new InvalidOperationException("Player2 is null in save data"), IsPlayer1Turn = saveData.IsPlayer1Turn, GamePlayerIteration = saveData.GamePlayerIteration, gameHistory = saveData.GameHistoryForUndo ?? new Stack<GameState>(), TurnTime = saveData.StartTurnTime }; HistoryGameMoves.GameMoves = saveData.GameMoves ?? []; Console.WriteLine($"Game loaded: {saveData.SaveName}"); Console.WriteLine($"Saved: {saveData.SaveTime}"); return game; } catch (JsonException ex) // В случае ошибки при извлечении обрабатываем исключение { Console.WriteLine($"Error parsing save file: {ex.Message}"); return null; } catch (Exception ex) // В случае возникновения других ошибок { Console.WriteLine($"Error loading game: {ex.Message}"); return null; } } // Функция для получения всех сохранённых игр public static List<SaveFileInfo> GetSaveFiles() { var saves = new List<SaveFileInfo>(); // Если директория не найдена, возвращаем пустой список if (!Directory.Exists(SaveDirectory)) return saves; // Добавляем только JSON-файлы var files = Directory.GetFiles(SaveDirectory, "*.json"); foreach (var filePath in files) { try { var fileInfo = new FileInfo(filePath); var saveInfo = new SaveFileInfo { FilePath = filePath, FileName = fileInfo.Name, Created = fileInfo.CreationTime, LastModified = fileInfo.LastWriteTime }; // Try to read save metadata without loading everything string json = File.ReadAllText(filePath); var saveData = JsonSerializer.Deserialize<SaveData>(json, JsonOptions); if (saveData != null) { saveInfo.SaveName = saveData.SaveName; saveInfo.SaveTime = saveData.SaveTime; } saves.Add(saveInfo); } catch { // Пропускаем невалидные файлы сохранений continue; } } // Сортировка по времени создания saves.Sort((a, b) => b.SaveTime.CompareTo(a.SaveTime)); return saves; } // Функция удаления сохранения public static void DeleteSave(string filePath) { try { if (File.Exists(filePath)) { File.Delete(filePath); // Удаляем файл Console.WriteLine("Save file deleted."); } } catch (Exception ex) // В случае неудачи удаления обрабатываем исключение { Console.WriteLine($"Error deleting save: {ex.Message}"); } } // Преобразование имени файла private static string CleanFileName(string fileName) { var invalidChars = Path.GetInvalidFileNameChars(); return string.Join("_", fileName.Split(invalidChars, StringSplitOptions.RemoveEmptyEntries)) .Replace(" ", "_") .Trim(); } public static JsonSerializerOptions GetOptions() { return new JsonSerializerOptions { WriteIndented = true }; } // Функция записи результата игры public static void RecordGameResult(string player1Name, string player2Name, int player1TotalScore, int player2TotalScore, JsonSerializerOptions options) { try { int p1GamePoints = player1TotalScore; int p2GamePoints = player2TotalScore; // Подготовка данных для записи var gameResults = new GameResults( player1Name, player2Name, p1GamePoints, p2GamePoints ); string fileName = "games_results.json"; string filePath = Path.Combine(SaveDirectory, fileName); // Создание списка для хранения всех результатов игр List<GameResults> games = []; if (File.Exists(filePath)) { try { string jsonContent = File.ReadAllText(filePath); //Представление JSON данных в виде списка игровых результатов games = JsonSerializer.Deserialize<List<GameResults>>(jsonContent) ?? []; if (games == null) // В случае неудачи представляем как 1 объект { var singleGame = JsonSerializer.Deserialize<GameResults>(jsonContent); if (singleGame != null) { games = [singleGame]; } } } catch (JsonException) { // Если файл повреждён возвращаем пустой список games = []; } } // Добавление новой игры if (games != null) games.Add(gameResults); else games = [gameResults]; // Обновляем JSON string updatedJson = JsonSerializer.Serialize(games, options); File.WriteAllText(filePath, updatedJson); Console.WriteLine("The game result was saved."); Console.WriteLine($"Location: {filePath}. Total games: {games.Count}"); } catch(Exception ex) // В случае неудачи сохранения результата обрабатываем исключение { Console.WriteLine($"Error saving game result: {ex.Message}"); } } // Функция сохранения истории ходов в текстовый файл public static void SaveHistoryGameMoves(string p1Name, string p2Name, int p1Score, int p2Score, Tuple<Tuple<TerrainType, TerrainType>, string> outGameParams) { // Вводим названия файла string saveHistoryName; while(true) { Console.Write("Enter save name: "); saveHistoryName = Console.ReadLine()?.Trim() ?? "default_save"; if (!string.IsNullOrWhiteSpace(saveHistoryName)) break; Console.WriteLine("Incorrect file name. Please, try again."); } try // Само сохранение { // Создание полного имени файла string fileName = $"{saveHistoryName}_{DateTime.Now:yyyyMMdd_HHmmss}.txt"; string filePath = Path.Combine(SaveDirectory, fileName); // Записываем информацию построчно using(var writer = new StreamWriter(filePath, true)) { // Краткая информация об игроках writer.WriteLine("=== History of game moves ==="); writer.WriteLine(); writer.WriteLine($"Magicians: {p1Name} & {p2Name}"); writer.WriteLine($"Start {p1Name}'s terrain: {outGameParams.Item1.Item1}"); writer.WriteLine($"Start {p2Name}'s terrain: {outGameParams.Item1.Item2} "); // Записываем историю ходов в виде таблицы writer.WriteLine(new string('=', 137)); writer.WriteLine("| {0,-2} | {1,-25} | {2,-4} | {3,-4} | {4,-12} | {5,-58} | {6,-10} |", "№", "Magician", "Mana", "Hand", "Action", "Additional Info", "Time/Limit"); writer.WriteLine(new string('=', 137)); int count = 0; foreach(var gameMove in HistoryGameMoves.GameMoves) { writer.WriteLine("| {0,-2} | {1,-25} | {2,-4} | {3,-4} | {4,-12} | {5,-58} | {6,-10} |", count % 2 == 0 ? gameMove.GameIteration : " ", gameMove.PlayerName, gameMove.Mana, gameMove.PlayerHand, gameMove.Action, gameMove.DetailInfo, $"{gameMove.MoveTime/60000}:{gameMove.MoveTime%60000/1000:00}/{gameMove.TurnTime/60000}:{gameMove.TurnTime%60000/1000:00}" ); count++; } writer.WriteLine(new string('=', 137)); // Информация в результате и победителе writer.WriteLine($"{p1Name} gets {p1Score} points"); writer.WriteLine($"{p2Name} gets {p2Score} points"); writer.WriteLine($"Winner: {outGameParams.Item2}"); } Console.WriteLine("The game history was saved."); Console.WriteLine($"Location: {filePath}."); } catch(Exception ex) // Обработка исключения в случае ошибки сохранения { Console.WriteLine($"Error saving history of game moves: {ex.Message}"); } } public static string GetFilePath(string fileName) { // Сохранение файла в директорию return Path.Combine(SaveDirectory, fileName); } } // Класс информации о файлах (для менеджера сохранений) public class SaveFileInfo { public string? FilePath { get; set; } public string? FileName { get; set; } public string? SaveName { get; set; } public DateTime SaveTime { get; set; } public DateTime Created { get; set; } public DateTime LastModified { get; set; } } }