using UnityEngine;
using System.Collections;
using System.Collections.Generic;//引入泛型集合的命名空间
using UnityEngine.UI;//UI
using UnityEngine.SceneManagement;//场景管理器
using UnityEngine.EventSystems;//引入事件系统namespace TowerDefenceTemplate
{[System.Serializable]//系统序列化public class Wave//敌方炮车波数{public Transform[] Waypoints;//路点数组public Transform SpawnPoint;//产生敌方炮车的位置 public GameObjectEnemyPrefab,//敌方炮车预制体 ArrowPoint;//进攻方向预制体public Sprite EnemiesIcon;//敌方炮车的图标public intSpeed,//速率Amount,//单波敌机总数Interval,//时间间隔Health,//血量Damage,//伤害值Award;//奖励金币[HideInInspector]public int Spawned;//已经产生的敌机数}public class GameManager : MonoBehaviour{private EventSystem _eventSystem;//实例化事件系统[HideInInspector]public UI_Controller _UI_Controller;//实例化UI_Controller[HideInInspector]public MainMenu mainMenu;[HideInInspector]public int CurrentWaveIndex;//定义当前波数的索引[HideInInspector]public List<GameObject>SpawnedEnemies,//声明敌方炮车游戏对象的集合BuiltTowers;//声明已建炮塔游戏对象的集合private GameObject[] TowerPoints;//定义所有炮塔的信息private float Timer;//计时器 private int BaseHealth = 100;//总血量private bool GameEnded;//定义游戏是否结束private Tower TowerToEdit;//实例化塔的对象[HideInInspector]public Dictionary<int, Bullet> BulletsPool;//定义炮弹池的键值对集合[HideInInspector]public Dictionary<int, Rocket> RocketsPool;//定义导弹池的键值对集合private GameObjectRocketsPoolParent,//父导弹池BulletsPoolParent,//父炮弹池TempTower,//临时塔TowerToBuild;//将要建造的塔//UI[HideInInspector]public RectTransform BaseHealthBar;//矩形血条[HideInInspector]public Text//文本 MoneyMessage, //金币信息WaveNumber,//当前波数 WaveUpperNumber,//总波数MoneyText,//钱币EnemiesLeftText,//没被摧毁的敌方炮车数量WaveTimer,//波次倒计时NameText,//名字DamageText,//伤害值RangeText,//检测范围LevelText,//等级UpgradeButtonText,//升级按钮SellButtonText;//卖掉按钮[HideInInspector]public Image //图像EnemiesIcon;//敌方炮车图标[HideInInspector]public Button ToMenuButton,//回到菜单RestartButton;//重新开始本关卡[HideInInspector]public GameObject//定义游戏对象RightPanel,//右侧小面板PauseMenu,//UpgradeButton;//升级按钮[Header("Camera boundaries")]//摄相机范围(组件中的小标题) public float X_Min;public float X_Max;public float Z_Min;public float Z_Max;public Wave[] Waves;//实例化波数public int Money;//定义玩家的金币[Header("Sounds")]//音效public AudioSource BuildSound;//建塔音效public AudioSource BaseDamageSound;//总血量减少时的音效public AudioSource ErrorSound;//错误提示音效public AudioSource ExplosionSound;//敌方炮车死亡时音效public AudioSource LevelUpSound;//等级提升音效public AudioSource LightGunShootSound;//光速炮射击音效public AudioSource RicochetSound1;//炮弹弹跳音1public AudioSource RicochetSound2;//炮弹弹跳音2public AudioSource RicochetSound3;//炮弹弹跳音3public AudioSource RocketLaunchSound;//导弹发射器射击音效public AudioSource RocketExplosionSound;//导弹爆炸音效public AudioSource FlameThrowerSound;//火焰喷射器射击音效public AudioSource JeepSound;//吉普车行进音效public AudioSource TankSound;//坦克行进音效public AudioSource PlaneSound;//飞机行进音效public AudioSource SellSound;//卖出炮塔音效[Header("Prefabs")]//预制体public GameObject RocketLauncherPrefab;//火箭发射器的预制体public GameObject LightGunPrefab;//光速炮的预制体public GameObject FlameThrowerPrefab;//火焰喷射器的预制体public GameObject HealthBarPrefab;//总血量预制体public GameObject BulletPrefab;//炮弹预制体public GameObject RocketPrefab;//导弹预制体private Camera main;void Start(){main = GameObject.Find("Main Camera").GetComponent<Camera>();if (Waves.Length > 0)//如果波数大于0{if (Waves[CurrentWaveIndex].ArrowPoint != null)//如果当前波次的进攻方向不为空{Waves[CurrentWaveIndex].ArrowPoint.SetActive(true);//显示当前波次的进攻入口}}else{Debug.LogError("Set up the GameManager waves!");//设定游戏管理器中的波数enabled = false;}if (_UI_Controller == null)//如果UI控制器为空{Debug.LogError("UI Canvas not found! GameManager is disabled.");//提示找不到画布enabled = false;return;}TowerPoints = GameObject.FindGameObjectsWithTag("TowerPoint");//找出所有炮台的位点物体_eventSystem = _UI_Controller._eventSystem;//为事件系统赋值CreateBulletsPool();CreateRocketsPool();Timer = 5;//计时器设置为5PauseMenu.SetActive(false);//MoneyText.text = Money.ToString() + "$";//改变当前的金币数WaveUpperNumber.text = "Wave " + (CurrentWaveIndex + 1).ToString() + "/" + Waves.Length.ToString();//改变上面的波数显示}void OnDrawGizmos()//画敌方炮车路线图,生命周期函数,只在编辑状态下被调用{foreach (var wave in Waves)//遍历所有波次{for (int i = 1; i < wave.Waypoints.Length; i++)//遍历所有路点{Gizmos.DrawLine(wave.Waypoints[i].position, wave.Waypoints[i - 1].position);//用直线连接路点}}}public void CreateBulletsPool()//创建炮弹池{BulletsPool = new Dictionary<int, Bullet>();//实例化新对象BulletsPoolParent = new GameObject("BulletsPool");//实例化父炮弹池并命名 for (int i = 0; i < 30 * TowerPoints.Length; i++)//遍历所有炮塔{GameObject _newbullet = Instantiate(BulletPrefab);//克隆炮弹预制体BulletsPool[i] = _newbullet.GetComponent<Bullet>();//获取克隆炮弹的Bullet脚本BulletsPool[i].gameObject.SetActive(false);//让炮弹池所在对象失活BulletsPool[i].transform.parent = BulletsPoolParent.transform;//把父炮弹池的位置信息赋值给炮弹池的父亲位置}}public void CreateRocketsPool()//创建导弹池{RocketsPool = new Dictionary<int, Rocket>();RocketsPoolParent = new GameObject("RocketsPool");for (int i = 0; i < 5 * TowerPoints.Length; i++){GameObject _newRocket = Instantiate(RocketPrefab);RocketsPool[i] = _newRocket.GetComponent<Rocket>();RocketsPool[i].gameObject.SetActive(false);RocketsPool[i].transform.parent = RocketsPoolParent.transform;}}public void SpendMoney(int moneyAmount)//花费金币{Money -= moneyAmount;//当前钱币减去花费的金币数赋值给当前金币数MoneyText.text = Money.ToString() + "$";//改变UGUI显示内容}public void AddMoney(int moneyAmount)//增加金币{Money += moneyAmount;//当前钱币加上奖励的金币数赋值给当前金币数MoneyText.text = Money.ToString() + "$";//改变UGUI显示内容}void Update(){if (GameEnded)//如果游戏结束{return;//结束当前方法}Timer = Mathf.MoveTowards(Timer, 0, Time.deltaTime);//倒计时DoNavigation();//地图拖动ControlMoneyMessageColor(false);//控制提示钱币信息的颜色CountEnemiesLeft();//计数每波敌人存活的个数CountTimeTillWaveStart();//下一波等待时间CountEnemiesSpawnerTimer();//计数敌方炮车总数PositioningTower();//给炮塔定位CreatingTower();//创建塔if (Input.GetKeyDown("mouse 0") && !_eventSystem.IsPointerOverGameObject() && TowerToEdit != null)//如果按下鼠标左键并且事件系统的对象的指针存在,并且实例化的塔对象不为空{DeactivateTowerControl();//使塔控制器失效}         }void DoNavigation()//地图拖动{if (_eventSystem.IsPointerOverGameObject())//事件系统的对象的指针不存在{return;//结束当前方法}if (Input.GetKey("mouse 0") && TempTower == null)//如果按着鼠标左键并且临时塔为空 {Camera.main.transform.position += new Vector3(-Input.GetAxis("Mouse X"), 0, -Input.GetAxis("Mouse Y"));//移动主摄像机的位置}Camera.main.transform.position = new Vector3(Mathf.Clamp(Camera.main.transform.position.x, X_Min, X_Max), Camera.main.transform.position.y, Mathf.Clamp(Camera.main.transform.position.z, Z_Min, Z_Max));//限制相机的移动范围float autoScale = Input.GetAxis("Mouse ScrollWheel");main.orthographicSize *= 1 - autoScale;main.orthographicSize = Mathf.Clamp(main.orthographicSize, 10, 55); }void CountEnemiesSpawnerTimer()//计数敌方炮车{if (Timer == 0)//如果本波次敌人产生完{WaveNumber.gameObject.SetActive(false);//当前波次设置失活if (Waves[CurrentWaveIndex].ArrowPoint != null)//如果当前波次的方向箭头不为空{Waves[CurrentWaveIndex].ArrowPoint.SetActive(false);//让它失活}Timer = Waves[CurrentWaveIndex].Interval;//等待一段时间EnemiesIcon.overrideSprite = Waves[CurrentWaveIndex].EnemiesIcon;//修改上面敌方炮车类型的图标为当前波次的敌方炮车图标int _spawned = Waves[CurrentWaveIndex].Spawned;//本波次当前的敌机数量int _amount = Waves[CurrentWaveIndex].Amount;//奔波次应产生的敌机总数if (_spawned < _amount)//没产够{SpawnEnemy();//生产敌方炮车}else if (SpawnedEnemies.Count == 0)//如果产完了本波次的所有炮车,但都已被摧毁{JeepSound.Stop();//停止音效TankSound.Stop();PlaneSound.Stop();Timer = 5;//重新赋值为5WaveNumber.gameObject.SetActive(true);//当前波次激活if (CurrentWaveIndex < (Waves.Length - 1))//如果当前波次不是最后一波{CurrentWaveIndex += 1;//已生产的波次索引+1WaveUpperNumber.text = "Wave " + (CurrentWaveIndex + 1).ToString() + "/" + Waves.Length.ToString();//改变面板提示信息Waves[CurrentWaveIndex].ArrowPoint.SetActive(true);//设置当前波次的行进箭头为激活状态WaveNumber.text = "Wave " + (CurrentWaveIndex + 1).ToString();//屏幕中间提示第几波}else{YouWon();//胜利}}}}void CountTimeTillWaveStart()//开始下一波次前的等待时间{if (SpawnedEnemies.Count == 0)//如果本波次的敌方炮车都已被摧毁{WaveTimer.text = "0:0" + ((int)Timer).ToString();//重置等待时间}}void CountEnemiesLeft()//计数存活的敌人{int Killed, EnemiesLeft;Killed = Waves[CurrentWaveIndex].Spawned - SpawnedEnemies.Count;//已经被摧毁的敌方炮车数量EnemiesLeft = Waves[CurrentWaveIndex].Amount - Killed;//没有被摧毁的炮车数量EnemiesLeftText.text = EnemiesLeft.ToString();//显示在画板上}void ControlMoneyMessageColor(bool ShowMessage)//控制钱币信息的颜色{Color _color = MoneyMessage.color;_color.a = Mathf.MoveTowards(_color.a, 0, Time.deltaTime);if (ShowMessage){_color.a = 1;}MoneyMessage.color = _color;}public void ThrowMoneyMessage()//抛出钱币信息{ControlMoneyMessageColor(true);//改变钱币数颜色ErrorSound.Play();//播放错误音效}public void UpgradeTower()//防御塔升级{if (TowerToEdit.UpgradeCost > Money)//如果当前金币不够升级的花销{ThrowMoneyMessage();//提示不够return;//结束当前方法}TowerToEdit.Upgrade();//调用实例对象自身的升级方法SpendMoney(TowerToEdit.UpgradeCost/2);//花费金币if (TowerToEdit.Level == TowerToEdit.Damage.Length - 1)//如果塔对象的等级等于最后的伤害值{UpgradeButton.SetActive(false);//设置升级按钮失活}else{UpgradeButton.SetActive(true);//一直可以升级}LevelUpSound.Play();//升级音效播放UpdateTowerInfo();//更新防御塔的信息}public void SellTower()//卖塔{AddMoney(TowerToEdit.UpgradeCost / 2);//加钱Destroy(TowerToEdit.gameObject);//摧毁这个塔SellSound.Play();//卖出音效播放DeactivateTowerControl();//这个塔的控制器失效}void UpdateTowerInfo()//更新塔的信息{UpgradeButtonText.text = "Upgrade " + TowerToEdit.UpgradeCost.ToString() + "$";//UGUI面板升级花费SellButtonText.text = "Sell " + (TowerToEdit.Cost / 2).ToString() + "$";//卖塔价钱NameText.text = TowerToEdit.TowerName;//塔的名字LevelText.text = "Level " + (TowerToEdit.Level + 1).ToString();//塔的等级DamageText.text = "Damage " + TowerToEdit.Damage[TowerToEdit.Level].ToString();//伤害值RangeText.text = "Range " + TowerToEdit.Range[TowerToEdit.Level].ToString();//检测范围}void YouLose()//游戏失败{ToMenuButton.gameObject.SetActive(true);//返回开始菜单按钮被激活RestartButton.gameObject.SetActive(true);//重新开始本关卡按钮被激活GameEnded = true;//游戏结束if (_UI_Controller != null)//如果UI控制器的对象不为空{_UI_Controller.GameEnd();//执行结束方法}WaveNumber.gameObject.SetActive(true);//当前波次对象被激活WaveNumber.text = "You lose!";//被激活的对象内容显示你失败了}void YouWon()//游戏胜利 {ToMenuButton.gameObject.SetActive(true);//返回开始菜单按钮被激活RestartButton.gameObject.SetActive(true);//重新开始本关卡按钮被激活GameEnded = true;//游戏结束if (_UI_Controller != null)//如果UI控制器的对象不为空{_UI_Controller.GameEnd();//执行结束方法}WaveNumber.gameObject.SetActive(true);//当前波次对象被激活WaveTimer.gameObject.SetActive(false);//波次倒计时器设置失活WaveNumber.text = "You won!";//被激活的对象内容显示你胜利了}public void ActivateTowerControl(Tower tower)//激活炮塔控制器{RightPanel.SetActive(true);//右侧菜单激活TowerToEdit = tower;//控制塔的实例化对象if (TowerToEdit.Level == TowerToEdit.Damage.Length - 1){UpgradeButton.SetActive(false);}else{UpgradeButton.SetActive(true);}UpdateTowerInfo();}public void DeactivateTowerControl()//失活炮塔控制器{RightPanel.SetActive(false);//右侧菜单失活if (TowerToEdit != null)//如果防御塔对象不为空{TowerToEdit.DetectCircle.gameObject.SetActive(false);//设置防御塔的侦测圆失活}TowerToEdit = null;//让对象为空}public void DamageBase()//玩家血量的伤害{BaseHealth -= Waves[CurrentWaveIndex].Damage;//血量减少BaseDamageSound.Play();//血量受到伤害的音效BaseHealthBar.localScale = new Vector3(BaseHealth / 100f, 1, 1);//对血条预制体实行x方向的缩放if (BaseHealth <= 0)//如果血量非正{YouLose();//失败方法BaseHealth = 100;//重新赋值为100}}public void BackToMenu()//返回主菜单{SceneManager.LoadScene("Menu");//加载场景Menu}public void RestartLevel()//重新开始本关卡{SceneManager.LoadScene(SceneManager.GetActiveScene().name);//按当前场景名字加载当前场景}public void BuildingModeOn(string type)//建造模型{if (type == "lightgun")//如果类型为ligthgun,并且按钮可按{TowerToBuild = LightGunPrefab;//将要建造的塔的游戏对象赋值为光速炮的预制体}if (type == "rocketlauncher"){TowerToBuild = RocketLauncherPrefab;}if (type == "flamethrower"){TowerToBuild = FlameThrowerPrefab;}TempTower = Instantiate(TowerToBuild);//克隆即将要建的塔赋值给临时塔}void PositioningTower()//确定新建塔的位置{if (TempTower == null)//如果临时塔为空{return;}RaycastHit hit;//射线碰撞体Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//鼠标位置发射一条射线if (Physics.Raycast(ray, out hit))//射线检测{TempTower.transform.position = hit.point;//临时炮塔放在鼠标位置}}void CreatingTower()//创建塔{if (TempTower == null || TowerPoints.Length == 0)//如果临时塔为空或者没有地方放置塔{return;}GameObject ClosestTowerPoint = TowerPoints[0];//设置第一个塔点为最靠近的鼠标位置的塔点Vector3 ClosestTowerPointPosition = TowerPoints[0].transform.position;//它的位置为第一个塔点的位置foreach (var towerpoint in TowerPoints)//遍历所有的塔点{if (Vector3.Distance(TempTower.transform.position, towerpoint.transform.position) < Vector3.Distance(ClosestTowerPointPosition, TempTower.transform.position))//当临时塔的位置与塔点位置的距离小于最近塔与临时塔的距离{ClosestTowerPoint = towerpoint;//把这个塔点赋值给最近的塔点ClosestTowerPointPosition = towerpoint.transform.position;//赋值相应的位置信息}}if (Input.GetKeyUp("mouse 0"))//当抬起鼠标左键时{if (Money < TempTower.GetComponent<Tower>().Cost)//如果当前的金币数小于建塔要花费的金币{ThrowMoneyMessage();//提示钱不够Destroy(TempTower);//销毁临时塔return;//结束当前方法}if (Vector3.Distance(TempTower.transform.position, ClosestTowerPointPosition) > 5|| ClosestTowerPoint.transform.childCount > 0)//如果临时塔和最塔点的距离大于5或者最近塔点没有子塔点{Destroy(TempTower);//销毁临时塔ErrorSound.Play();//错误音效return;//结束当前方法}SpendMoney(TempTower.GetComponent<Tower>().Cost);//建塔花费金币BuiltTowers.Add(TempTower);//添加到已建造的集合float _verticalOffset = ClosestTowerPoint.AddComponent<BoxCollider>().bounds.size.y;//获取最近塔点的盒子碰撞器的长度,作为炮台高Destroy(ClosestTowerPoint.GetComponent<BoxCollider>());//销毁盒子碰撞器SphereCollider _tempCollider = TempTower.AddComponent<SphereCollider>();//给临时塔添加球形碰撞体_tempCollider.radius = 5;//半径为5TempTower.transform.position = ClosestTowerPointPosition + new Vector3(0, _verticalOffset, 0);//把临时塔放在最近塔点位置,并以炮台的高度作为底面高TempTower.transform.parent = ClosestTowerPoint.transform;//把最近塔点的位置赋值给临时塔的父物体位置TempTower = null;//临时塔设置为空BuildSound.Play();//建塔音效播放}}public void Pause()//暂停{Time.timeScale = 0;}public void UnPause()//播放{Time.timeScale = 1;}public void Fast()//加快{Time.timeScale = 3;}void SpawnEnemy()//生产敌方炮车{Waves[CurrentWaveIndex].Spawned += 1;//已造出的炮车数量增加1GameObject _newEnemy = Instantiate(Waves[CurrentWaveIndex].EnemyPrefab, Waves[CurrentWaveIndex].SpawnPoint.position, Waves[CurrentWaveIndex].SpawnPoint.rotation) as GameObject;//克隆新的敌方炮车GameObject _healthBar = _newEnemy.GetComponent<Enemy>().HealthBar = Instantiate(HealthBarPrefab) as GameObject;//克隆炮车的血条_healthBar.transform.parent = _UI_Controller.transform;//定义血条的父物体为_UI_ControllerSpawnedEnemies.Add(_newEnemy);//把新炮车添加到敌方炮车集合中}}
}

Unity3D-塔防游戏项目主要源码(游戏主控器脚本)相关推荐

  1. 基于Java毕业设计校园疫情防控管理系统源码+系统+mysql+lw文档+部署软件

    基于Java毕业设计校园疫情防控管理系统源码+系统+mysql+lw文档+部署软件 基于Java毕业设计校园疫情防控管理系统源码+系统+mysql+lw文档+部署软件 本源码技术栈: 项目架构:B/S ...

  2. java计算机毕业设计-酒店疫情防控系统-源码+数据库+lw文档+系统

    java计算机毕业设计-酒店疫情防控系统-源码+数据库+lw文档+系统 java计算机毕业设计-酒店疫情防控系统-源码+数据库+lw文档+系统 本源码技术栈: 项目架构:B/S架构 开发语言:Java ...

  3. 计算机毕业设计JavaH5乡镇疫情防控系统(源码+系统+mysql数据库+lw文档)

    计算机毕业设计JavaH5乡镇疫情防控系统(源码+系统+mysql数据库+lw文档) 计算机毕业设计JavaH5乡镇疫情防控系统(源码+系统+mysql数据库+lw文档) 本源码技术栈: 项目架构:B ...

  4. java计算机毕业设计小区疫情防控管理系统源码+系统+mysql数据库+lw文档+部署

    java计算机毕业设计小区疫情防控管理系统源码+系统+mysql数据库+lw文档+部署 java计算机毕业设计小区疫情防控管理系统源码+系统+mysql数据库+lw文档+部署 本源码技术栈: 项目架构 ...

  5. 最新好看的自适应手机版软件APP下载类网站源码,游戏软件应用网站源码,自适应手机端Pbootcms模板

    自适应手机软件APP下载类网站源码/游戏软件应用网站源码/自适应手机端 Pbootcms模板 测试环境:Linux  nginx1.18  PHP7.3 下载地址:自适应手机端软件APP下载网站源码 ...

  6. 2022新版域名防红系统源码

    介绍: 2022新版域名防红系统源码,管理会员制度渠道,掌管多种服务,黑白名单管理邮箱配置生成提醒发送对接易支付进行交易,订单列表,带有各种短网址功能提供接口对接,实现短网址+防红两不误,可自定义多中 ...

  7. 2022新JI卫云域名防红/防封程序源码+已去除授权

    正文: 2022新JI卫云域名防红/防封程序源码+已去除授权,JI卫云防红系统,双重跳转,程序非常稳定,生成短链接均支持在QQ_微信内部直接强行打开,也是支持iOS端的. 功能: 程序: wwau.l ...

  8. 最新域名防红系统源码+实战搭建视频教程

    介绍: 今天分享一个防红系统源码+搭建教程 服务器系统:Linux+Centos7.0以上+宝塔,也可以选择EP主机! 我用的就是EP主机搭建 先简单的打开面板 上传源码-解压源码 打开域名,开始安装 ...

  9. 微信QQ域名防封防红防屏蔽系统源码

    介绍: php微信QQ域名防封防红防屏蔽系统源码 已红的域名也可以在微信内直接打开,这类源码的时效性不明确. 网盘下载地址: https://zijiewangpan.com/Z9BiSsLkTsy ...

最新文章

  1. Redis 高级特性(4)— 单线程架构
  2. JVM调优:-Xms40M -Xmx60M 指定堆的最小、最大大小
  3. python每隔半个小时执行一次_一篇文章教你用Python抓取微博评论
  4. ZT Web Control 开发系列(一) 页面的生命周期
  5. ibatis--百度百科
  6. Kerberos与Sniffer,矛与盾永远的对立
  7. linux shell 特殊符号的表示
  8. 2021年的电商,要怎么做,才能赚钱呢?
  9. 交换机通过port-channel互联
  10. QQ2006 界面编程
  11. 编译原理三大经典龙书 虎书 鲸书 编译原理第三版清华pdf 清华北大
  12. yolo算法部分简单理解
  13. 晶体管放大电路之应用
  14. 婚礼邀请函微信小程序
  15. atomic 内存序_C++11的原子量与内存序浅析
  16. 图的遍历:BFS算法学习
  17. WS小世界网络python快速实现——调用networkx包
  18. 小巫随笔12(致小巫逝去的童年)
  19. 云计算与云原生 — OpenShift 部署实践
  20. 利用kNN算法对iris数据集进行分类,本人也做了修改使得代码可实现

热门文章

  1. 【前端-CSS】盒子模型-水平方向、垂直方向的布局
  2. 2019世界地球日,美厦三恒系统与您一起守护我们的地球母亲
  3. python的unicode编码表_python中Unicode编码初探
  4. 浦东机场IT基础架构现代化启示录
  5. java 自动过期缓存_Java自动过期本地缓存简单实现
  6. centos8mysql配置文件在哪里_Centos7 查看Mysql配置文件
  7. C++实现单例模式,保证线程安全
  8. NoSQL代表: Mongo DB(芒果数据库)
  9. 2023年度上海市促进文化创意产业发展财政扶持资金项目申报指南
  10. Matlab中字符串表示、字符串矩阵、字符串中的常用函数