LevelGenerate.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. //
  2. // LevelGenerate.hpp
  3. // auto_fill_jewel_v3
  4. //
  5. // Created by Red on 2024/11/23.
  6. // 关卡生成类,包含生成盘子组合,然后填充宝石。
  7. #ifndef LevelGenerate_hpp
  8. #define LevelGenerate_hpp
  9. #include <stdio.h>
  10. #include <string>
  11. using std::string;
  12. #include "contourdata.h"
  13. #include "FillGlobalConfig.hpp"
  14. #include "FillResult.hpp"
  15. #include "RandomGridFiller.hpp"
  16. #include <tuple>
  17. using std::tuple;
  18. #include "levelinputdata.h"
  19. #include "levelextinputdata.h"
  20. struct LevelGenerate {
  21. public:
  22. //盘子ID和层数
  23. struct PlateIdAndLayerCnt {
  24. PlateIdAndLayerCnt():_plateId(-1),_layerCnt(0),_moveId(0){}
  25. int _plateId ;
  26. int _layerCnt ;
  27. int _moveId ;//0-静态盘子 1-第一行移动盘子 2-第二行移动盘子
  28. } ;
  29. public:
  30. LevelGenerate():_seed(11231627){}
  31. void setSeed(int s) { _seed = s ;}
  32. int getSeed() { return _seed ; }
  33. void generateAll(FillGlobalConfig::LevelData levelData, string outname) ;
  34. //盘子和宝石的组合有解返回true,反之返回false
  35. bool generate( FillGlobalConfig::LevelData levelData,
  36. const bool isMovable,
  37. const FillGlobalConfig::MultiMoveConfig* mulMoveConfig , //移动盘子配置,如果isMovable为false,这个参数忽略,可以传入nullptr
  38. vector<PlateFillResult>& resultPlateFillResults,
  39. vector<ContourData::Point>& resultPlateCenterPointArr
  40. ) ;
  41. //将输入数据拆分成基本输入参数和扩展输入参数作为输入
  42. bool generate_v2(
  43. const LevelInputData& indata,
  44. const LevelExtInputData& extdata,
  45. vector<PlateFillResult>& resultPlateFillResults,
  46. vector<ContourData::Point>& resultPlateCenterPointArr,
  47. string& error) ;
  48. private:
  49. int _seed ;
  50. //根据难度数据和宝石总数计算需要使用的每个盘子的个数
  51. /// @param difficulty 难度:0-普通,1-难,2-极难
  52. /// @param totEquvSmallJewelCnt 全部等效小盘子数量
  53. /// @return 返回盘子和层数的组合
  54. vector<PlateIdAndLayerCnt> generatePlateTypeAndLayerCnts(const int difficulty,const int totEquvSmallJewelCnt);
  55. //根据难度数据和宝石总数计算需要使用的每个盘子的个数
  56. //考虑可移动关卡的条件
  57. vector<PlateIdAndLayerCnt> generatePlateTypeAndLayerCnts2(const bool isMovable,const FillGlobalConfig::MultiMoveConfig* mulMoveConfig,const int difficulty,const int totEquvSmallJewelCnt);
  58. //相对于generatePlateTypeAndLayerCnts2通过随机数计算盘子数量, generatePlateTypeAndLayerCnts3使用输入盘子百分比计算盘子数量。
  59. vector<PlateIdAndLayerCnt> generatePlateTypeAndLayerCnts3(const bool isMovable,const FillGlobalConfig::MultiMoveConfig* mulMoveConfig,const int difficulty,const int totEquvSmallJewelCnt,const LevelExtInputData& extdata );
  60. //生成针对可移动盘子的组合
  61. //残余等效小宝石数量返回到 residueEquvSmlJewelCnt 里面
  62. vector<PlateIdAndLayerCnt> generatePlateTypeAndLayerCntsForMovablePlates(const FillGlobalConfig::MultiMoveConfig* mulMoveConfig,const int totEquvSmallJewelCnt, int& retResidueEquvSmlJewelCnt );
  63. //判断一个组合是否恰恰装入宝石个数,规则是如果少一个盘就恰好装不下.
  64. bool isJustFilledAll2(
  65. const vector<int>& plateCaps,//每个盘子的容量
  66. const vector<int> eachPlateLyrCnt,//对应盘子的层数
  67. const int totSmlJewCnt) ;
  68. vector<int> randIndices(const int count0 ) ;
  69. /// 随机从库存中取出needEquvSmlCnt个等效小宝石,取出的宝石从库存减掉
  70. /// @param needEquvSmlCnt 需要取出的等价小宝石数量
  71. /// @param unsolvedPercent 取出宝石的不可解百分比
  72. /// @param jewStorages 库存数据,取出数据要从库存减去,key:jewId value:tuple<Sz,Cnt>
  73. /// @return 返回宝石ID和对应的数量
  74. unordered_map<int, int> randPickJewels( const int needEquvSmlCnt,const float solvedPercent, unordered_map<int,tuple<int,int>>& jewStorages ) ;
  75. /// 填充一个盘子,用掉的宝石从库存减掉
  76. vector<FillResult> fillPlateOneLayer(RandomGridFiller& filler,const int plateId, unordered_map<int,int>& jewStoragesForUse ) ;
  77. /// 宝石尺寸转等效小宝石数量
  78. int jewSz2SmlCnt(int sz) ;
  79. /// 查找库存剩余的宝石,返回 jewId,Cnt,并扣除库存数量
  80. unordered_map<int, int> findUnfilledInStorages(unordered_map<int,tuple<int,int>>& jewStorages);
  81. /// 整理结果数据为 关卡-盘子-层-宝石的层次结构
  82. void regroupPlateLyrFillResults( vector<tuple<int,int,vector<FillResult>,int>>& pidlyrFillMvidArray, vector<PlateFillResult>& results ) ;
  83. /// 摆放盘子
  84. void placePlates(const bool movable, const FillGlobalConfig::MultiMoveConfig* mulMoveConfig, const vector<PlateFillResult>& plateFRArr, vector<ContourData::Point>& resultPlateCenterPointArr ) ;
  85. // 根据移动盘子情况计算关卡大盘子数量和中盘子数量,该数字包含移动盘子和非移动盘子。
  86. void computePlateCount(const FillGlobalConfig::MultiMoveConfig* mmc ,int& retBigPlateCnt, int& retMidPlateCnt ) ;
  87. } ;
  88. #endif /* LevelGenerate_hpp */