游戏数据的存入与读取

1.1二进制方式存入数据:
    private void SaveByBinary()
    {
        Save save = CreateSaveGO();
        //创建一个二进制格式化器
        BinaryFormatter bf = new BinaryFormatter();
        //创建一个文件流
        FileStream fileStream = File.Create(Application.dataPath + "/StreamingFile" + "/byBin.txt");
        //用二进制格式化器的序列化方法来序列化要Save对象
        bf.Serialize(fileStream, save);
        //关闭流
        fileStream.Close();
        //如果文件存在,则输出保存成功
        if (File.Exists(Application.dataPath + "/StreamingFile" + "/byBin.txt"))
        {
            Debug.LogError("保存成功");
        }
    }

1.2二进制方式读取数据:
    private void LoadByBinary()
    {
        if (File.Exists(Application.dataPath + "/StreamingFile" + "/byBin.txt"))
        {
            //创建一个二进制格式化程序
            BinaryFormatter bf = new BinaryFormatter();
            //打开一个文件流
            FileStream fileStream = File.Open(Application.dataPath + "/StreamingFile" + "/byBin.txt", FileMode.Open);
            //调用格式化程序的反序列化方法,将文件流转换为一个Save对象
            Save save = (Save)bf.Deserialize(fileStream);
            //关闭文件流
            fileStream.Close();
            SetGame(save);
            Debug.Log("读取成功");
        }
        else
        {
            Debug.LogError("读档失败,文件不存在");
        }
    }

2.1Json方式存入数据:
    private void SaveByJson()
    {
        Save save = CreateSaveGO();
        string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json";
        //利用JsonMapper将save对象转换为Json格式的字符串
        string saveJsonStr = JsonMapper.ToJson(save);
        //将这个字符串写入到文件中
        //创建一个StreamWriter,并将字符串写入文件中
        StreamWriter sw = new StreamWriter(filePath);
        sw.Write(saveJsonStr);
        //关闭StreamWriter
        sw.Close();
        Debug.Log("保存成功");
    }

2.2Json方式读取数据:
    private void LoadByJson()
    {
        string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json";
        if (File.Exists(filePath))
        {
            //创建一个StreamReader,用来读取流
            StreamReader sr = new StreamReader(filePath);
            //将读取到的流赋值给jsonStr
            string jsonStr = sr.ReadToEnd();
            //关闭
            sr.Close();
            //将字符串jsonStr转换为Save对象
            Save save = JsonMapper.ToObject<Save>(jsonStr);
            SetGame(save);
            Debug.Log("读取成功");
        }
        else
        {
           Debug.LogError("读取失败,文件不存在");
        }
    }

3.1XML方式存入数据:
    private void SaveByXml()
    {
        Save save = CreateSaveGO();
        //创建XML文件的存储路径
        string filePath = Application.dataPath + "/StreamingFile" + "/byXML.txt";
        //创建XML文档
        XmlDocument xmlDoc = new XmlDocument();
        //创建根节点,即最上层节点
        XmlElement root = xmlDoc.CreateElement("save");
        //设置根节点中的值
        root.SetAttribute("name", "saveFile1");
        XmlElement target;
        XmlElement targetPosition;
        XmlElement monsterType;
        //遍历save中存储的数据,将数据转换成XML格式
        for (int i = 0; i < save.livingTargetPositions.Count; i++)
        {
            target = xmlDoc.CreateElement("target");
            targetPosition = xmlDoc.CreateElement("targetPosition");
            //设置InnerText值
            targetPosition.InnerText = save.livingTargetPositions[i].ToString();
            monsterType = xmlDoc.CreateElement("monsterType");
            monsterType.InnerText = save.livingMonsterTypes[i].ToString();

            //设置节点间的层级关系
            target.AppendChild(targetPosition);
            target.AppendChild(monsterType);
            root.AppendChild(target);
        }
        XmlElement shootNum = xmlDoc.CreateElement("shootNum");
        shootNum.InnerText = save.shootNum.ToString();
        root.AppendChild(shootNum);

        XmlElement score = xmlDoc.CreateElement("score");
        score.InnerText = save.score.ToString();
        root.AppendChild(score);

        xmlDoc.AppendChild(root);
        xmlDoc.Save(filePath);

        if (File.Exists(Application.dataPath + "/StreamingFile" + "/byXML.txt"))
        {
            Debug.Log("保存成功");
        }
    }

3.2XML方式读取数据:
    private void LoadByXml()
    {
        string filePath = Application.dataPath + "/StreamingFile" + "/byXML.txt";
        if (File.Exists(filePath))
        {
            Save save = new Save();
            //加载XML文档
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(filePath);

            //通过节点名称来获取元素,结果为XmlNodeList类型
            XmlNodeList targets = xmlDoc.GetElementsByTagName("target");
            //遍历所有的target节点,并获得子节点和子节点的InnerText
            if (targets.Count != 0)
            {
                foreach (XmlNode target in targets)
                {
                    XmlNode targetPosition = target.ChildNodes[0];
                    int targetPositionIndex =     int.Parse(targetPosition.InnerText);
                    //把得到的值存储到save中
                    save.livingTargetPositions.Add(targetPositionIndex);

                    XmlNode monsterType = target.ChildNodes[1];
                    int monsterTypeIndex = int.Parse(monsterType.InnerText);
                    save.livingMonsterTypes.Add(monsterTypeIndex);
                }
            }
            XmlNodeList shootNum = xmlDoc.GetElementsByTagName("shootNum");
            int shootNumCount = int.Parse(shootNum[0].InnerText);
            save.shootNum = shootNumCount;

            XmlNodeList score = xmlDoc.GetElementsByTagName("score");
            int scoreCount = int.Parse(score[0].InnerText);
            save.score = scoreCount;

            SetGame(save);
            Debug.Log("读取成功");
        }
        else
        {
            Debug.LogError("读取失败,文件不存在");
        }
    }

<think>我们有一个结构体Game,其中有一个int类型的成员sorce(注意:原结构体中这个成员名是sorce,不是score,但原代码中在游戏结构体Game0中使用了score,在链表结构体Game中使用了sorce,这里需要统一)。用户要求将贪吃蛇游戏中的得分(原Game0结构体中的score)存入链表结构体Game的sorce成员中。分析:1.在贪吃蛇游戏结束时,我们会得到一个得分(game.score)。2.我们需要将这个得分存储到当前登录玩家的结构体Game的sorce字段中。3.当前登录玩家的信息存储在链表中,我们需要知道当前是哪个玩家在玩游戏。实现步骤:1.在游戏开始前,玩家需要登录(logon函数),登录成功后,我们记录当前登录的玩家(例如,用一个全局变量currentPlayer来指向登录的玩家节点)。2.在游戏结束后,将本次游戏的得分(game.score)赋值给currentPlayer->sorce。3.然后保存到文件(saveFile)中,以便下次启动时排行榜能显示最新的得分。具体修改:第一步:在程序中添加一个全局变量,用于记录当前登录的玩家。在文件开头,定义全局变量:Game* currentPlayer =NULL;第二步:修改登录函数(logon),在登录成功时,将currentPlayer指向登录的玩家节点。在logon函数中,当找到匹配的账号密码时,将p赋值给currentPlayer。第三步:在游戏结束后(gameOver为true时),将得分存入currentPlayer->sorce。注意:我们可能希望存储最高分,而不是每次的得分?但是题目要求是存储本次得分。我们可以根据需求决定是覆盖还是保留最高分。这里我们假设每次游戏后都更新为本次得分(如果要求是最高分,则比较后存储最大值)。第四步:保存到文件(saveFile),这样下次启动时数据还在。另外,在排行榜显示(charts函数)中,我们也要显示sorce(得分)字段。修改代码:1.定义当前玩家指针(全局变量):在head定义之后:Game* currentPlayer =NULL;2.修改logon函数,登录成功时设置currentPlayer:在logon函数中,找到玩家后,添加:currentPlayer= p;3.在游戏结束后(main函数中的游戏循环结束后),将得分存入currentPlayer:注意:在游戏结束后,我们有一个cleanupGame(&game)和system("pause"),之后我们可以将得分存入。在main函数中,游戏结束后的代码位置:printf("\n游戏结束!最终分数:%d\n",game.score);//如果当前有玩家登录,则更新该玩家的得分if (currentPlayer!= NULL) {currentPlayer->sorce= game.score;//将本次得分存入saveFile();//保存到文件}cleanupGame(&game);system("pause");4.修改charts函数,在显示排行榜时,显示sorce(得分)字段。原charts函数中,打印的是password,这显然不对。我们应该打印sorce。修改charts函数中的打印语句:printf("%-15s%-30s%-20s%-15s\n","排名","帐号","玩家名","玩家得分");然后循环中:printf("%-15d %-30s %-20s %-15d\n", i, p->num, p->name, p->sorce);//注意最后一个字段改为p->sorce,并且是整数%d5.注意:在结构体Game中,sorce原本是int类型,但原代码中在注册时没有初始化,在游戏结束后才赋值,所以一开始可能是随机值。在注册时我们可以将其初始化为0。在input函数中,当创建新用户时,添加:newaccount->sorce =0;//初始得分为06.另外,原结构体Game中,sorce的拼写是sorce,而Game0中是score,注意区分。7.在排行榜显示中,我们可能希望按得分从高到低排序?但原链表是无序的。我们可以先对链表按得分排序再显示。由于题目没有要求,我们可以先不做排序,但为了更好的用户体验,我们可以考虑在charts函数中按得分排序。排序方法:我们可以先将链表复制到一个数组中,然后对数组按得分排序,再显示。由于时间关系,我们这里先不实现排序,但要注意原charts函数中显示的顺序是注册顺序。8.修改后,记得在保存文件时,sorce字段也会被保存,加载时也会被加载。代码修改示例:步骤1:在全局变量定义处添加currentPlayer在head定义之后:Game* head= NULL;Game*currentPlayer= NULL;//新增步骤2:修改logon函数,成功登录后设置currentPlayer在logon函数中,找到玩家并密码正确后:currentPlayer =p;//新增步骤3:修改input函数,初始化sorce为0在input函数中,创建新用户后:newaccount->sorce =0;//初始得分0步骤4:在游戏结束后更新得分在main函数中的游戏循环结束后,添加更新得分的代码(如上所述)。步骤5:修改charts函数,显示得分字段(用sorce,并且是整数)注意:如果玩家没有登录就玩游戏(即选择3开始游戏),那么currentPlayer为NULL,此时我们不存储得分。所以需要提醒玩家先登录。因此,我们可以在游戏开始前检查是否登录:在main函数中,当选择3开始游戏时,先检查currentPlayer是否为NULL,如果为NULL,则提示先登录,然后break(不进入游戏)。修改main函数中case3的部分:case3:if (currentPlayer== NULL) {printf("请先登录!\n");system("pause");break;}//否则,开始游戏...原来的游戏代码另外,在登录选项(case4)中,登录成功后,我们并没有检查是否要进入游戏,而是提示“是否进入游戏”,如果用户选择是,我们直接gotogame。但是,这里我们也要注意,如果登录成功,currentPlayer已经被设置,所以可以直接开始游戏。但是,我们也可以不强制用户立即开始游戏,而是让用户回到菜单再选择3开始。所以,我们可以去掉case4中登录成功后询问是否进入游戏的代码,因为现在我们在case3中会检查登录状态。修改case4的代码:去掉询问是否进入游戏的部分,登录成功后直接break。这样,用户登录后,再选择3就可以开始游戏。总结修改点:1.添加全局变量currentPlayer。2.在logon函数中设置currentPlayer。3.在input函数中初始化新用户的sorce为0。4.修改charts函数,显示sorce字段(用%d)。5.在游戏开始前(case3)检查是否登录。6.在游戏结束后,将得分存入currentPlayer->sorce并保存文件。7.去掉case4中登录成功后的游戏进入询问。注意:由于原代码中Game结构体的sorce字段在注册时并没有输入,所以我们在注册时初始化为0。在游戏结束后更新。现在,我们按照上述修改点修改代码。</think>在C语言中将值存入结构体指定字段的步骤如下: ### 1. **定义包含目标字段的结构体** 首先确保结构体包含需要存储数据的字段: ```c typedef struct Game { char num[20]; // 帐号 char name[100]; // 昵称 char password[50];// 密码 int sorce; // 得分字段 ★ 关键字段 // ... 其他字段 } Game; ``` ### 2. **创建结构体实例** 声明结构体变量或指针: ```c Game player; // 栈上分配 Game *pPlayer = malloc(sizeof(Game)); // 堆上分配 ``` ### 3. **直接赋值给字段** 使用点运算符`.`(结构体变量)或箭头运算符`->`(结构体指针): ```c // 情况1:结构体变量 player.sorce = 100; // 直接赋值 // 情况2:结构体指针 pPlayer->sorce = 200; ``` ### 4. **通过函数赋值** 封装赋值函数提高可维护性: ```c void setScore(Game* player, int score) { if(player != NULL) { player->sorce = score; } } // 调用示例 setScore(&player, 150); setScore(pPlayer, 250); ``` ### 5. **文件读写操作** 使用`fwrite/fread`保存和加载结构体数据: ```c // 保存到文件 FILE* fp = fopen("data.dat", "wb"); fwrite(&player, sizeof(Game), 1, fp); fclose(fp); // 从文件加载 Game loadedPlayer; fp = fopen("data.dat", "rb"); fread(&loadedPlayer, sizeof(Game), 1, fp); printf("得分: %d\n", loadedPlayer.sorce); // 读取存储的值 ``` ### 在贪吃蛇游戏中的具体应用 在游戏结束位置添加得分存储代码: ```c // 游戏结束后 printf("\n游戏结束! 最终分数: %d\n", game.score); if(currentPlayer != NULL) { // 将得分存入结构体字段 currentPlayer->sorce = game.score; // 保存到文件系统 saveFile(); } ``` > **关键点说明**: > 1. 使用`.`或`->`运算符直接访问结构体字段 > 2. 字段名`sorce`需结构体定义严格一致 > 3. 指针操作前需检查`NULL`避免崩溃 > 4. 文件读写时使用二进制模式保证数据完整性[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值