diff --git a/Engine.cpp b/Engine.cpp new file mode 100644 index 0000000..2e9ece7 --- /dev/null +++ b/Engine.cpp @@ -0,0 +1,644 @@ +#include +#include +#include +#include +#include +using namespace std; + +ifstream File_Input; +ofstream File_Output; +const unsigned char Up = 1, Down = 2, Left = 3, Right = 4; + +//用于寻找下一布局 +struct block_struct { + unsigned char address; //0~19 + unsigned char style; //0:2*2 1:2*1 2:1*2 3:1*1 +}; +unsigned char table[20]; //0~9:block[?] 0xA:space 0xFF:empty +unsigned char space[2]; //space[0~1]的位置 +struct block_struct block[10]; //0:2*2 1~5:1*2,2*1 6~9:1*1 + +bool quick; //仅计算最短步骤 +int Solution_num_quick; +vector Source_quick; //父布局编号 +vector Solution_quick; //最短路径 + +//用于绘制整个队列树 +unsigned int Now_Move; //目前正在进行计算的布局编号 +list int_list; //空列表 +vector int_vector; //空vector +list Hash[0x10000]; //哈希索引表 +vector List; //所有情况的队列 +vector Layer_Num; //所在层的编号 +vector Layer_Index; //层中所属的编号 +vector > Source; //父布局编号 +vector > Layer; //分层 +vector > > Layer_Next; //分层链接 + +//布局的基本参数 +int group_size; //整个队列组的大小 +int min_steps; //解的最少步骤 +int farthest_steps; //最远布局的步数 +vector Solutions; //所有解 +vector Solutions_steps; //所有解的最少步 +vector min_Solutions; //所有最少步解 +vector farthest_cases; //所有最远的布局 +//vector solution_path; //最少步解法 + +void debug(); +void Find_All_Case(); +void Data_Output(string File_name); +void Split_Layer(); +unsigned int Change_int (char str[8]); +string Change_str (unsigned int dat); +void Output_Graph (unsigned int Code); +void Analyse_Code (unsigned int Code); +void Add_Case (unsigned int Code); +void Calculate (unsigned int Start_Code); +void Date_Back_quick (int num); +void Calculate_quick (unsigned int Start_Code); +bool Check (unsigned int Code); +unsigned int Get_Code(); +void Find_Next(); +bool Check_Empty (unsigned char address,unsigned char dir,unsigned char num); +void Move_Block (unsigned char num,unsigned char dir_1,unsigned char dir_2); +void Fill_Block (unsigned char addr, unsigned char style, unsigned char filler); +vector Search_Path (unsigned int target_num); +void Analyse_Case (unsigned int Start_Code); + +int main(int argc, char* argv[]) { + unsigned int Code, i; + string File_name, Parameter; + cout << "HRD-Engine by Dnomd343" << endl; + if (argc == 3) { + Parameter = argv[1]; + Code = Change_int(argv[2]); + if (Check(Code) == false) {cout << "Code Error" << endl; return 0;} + File_name = Change_str(Code) + ".txt"; + if (Parameter == "-q") { + cout << "Quick Calculate Mode." << endl; + cout << "Code: " << Change_str(Code) << endl; + cout << "Data Save at " << File_name << endl; + quick = true; + Calculate_quick(Code); + Date_Back_quick(Solution_num_quick); + File_Output.open(File_name.c_str()); + if (Solution_quick.size() == 0) { + File_Output << "No Solution" << endl; + } else { + File_Output << Solution_quick.size() - 1 << endl; + } + for (i = 0; i < Solution_quick.size(); i++) { + File_Output << Change_str(Solution_quick[i]) << endl; + } + File_Output.close(); + } else if (Parameter == "-a") { + cout << "All Calculate Mode." << endl; + cout << "Code: " << Change_str(Code) << endl; + cout << "Data Save at " << File_name << endl; + quick = false; + Analyse_Case(Code); + Data_Output(File_name); + } else { + cout << "Parameter Error" << endl; + } + } else { + cout << "Usage: [HRD-Engine.exe] [-q]/[-a] Code" << endl; + cout << "-q: Quick Calculate Mode" << endl << "-a: All Calculate Mode" << endl; + cout << "Such as 'HRD-Engine.exe -q 4FEA134'" << endl << " or 'HRD-Engine.exe -a 1A9BF0C'" << endl; + } + return 0; +} + +void Analyse_Case (unsigned int Start_Code) { //对一个布局进行分析 + unsigned int i, first_solution; + if (Check(Start_Code) == false) {return;} //若输入编码无效则退出 + Calculate(Start_Code); //通过计算建立队列表 + group_size = List.size(); //整个队列树大小 + min_steps = -1; + farthest_steps = -1; + Solutions.clear(); + Solutions_steps.clear(); + min_Solutions.clear(); + farthest_cases.clear(); + //solution_path.clear(); + bool get_it = false; + for (i = 0; i < List.size(); i++) { //遍历队列中所有元素 + Analyse_Code(List[i]); + if (block[0].address == 13) { //若当前布局为有效解 + if (get_it == false){ + min_steps = Layer_Num[i]; //第一个找到的解为最少步解 + first_solution = i; + get_it = true; + } + Solutions.push_back(List[i]); //将找到的有效解加入解集中 + Solutions_steps.push_back(Layer_Num[i]); + if (Layer_Num[i] == min_steps) { + min_Solutions.push_back(List[i]); //将找到的最小步有效解加入最小步解集中 + } + } + } + farthest_steps = Layer_Num[Layer_Num.size() - 1]; //计算最远布局的步数 + for (i = Layer_Num.size() - 1; i > 0; i--) { //找到所有最远的布局 + if(Layer_Num[i] != farthest_steps) {break;} + farthest_cases.push_back(List[i]); + } + //if (min_steps != -1) {solution_path = Search_Path(first_solution);} +} + +void Split_Layer() { + vector > temp; + int i, num, index; + num = -1; + index = 0; + for (i = 0; i < Layer_Num.size(); i++) { + if (Layer_Num[i] != num) { + Layer.push_back(int_vector); + Layer_Next.push_back(temp); + num = Layer_Num[i]; + index = 0; + } + Layer_Index.push_back(index); + index++; + Layer[num].push_back(List[i]); + Layer_Next[num].push_back(int_vector); + } + + list ::iterator poi; + for (i = 1; i < List.size(); i++) { + poi = Source[i].begin(); + while (poi != Source[i].end()) { + Layer_Next[Layer_Num[*poi]][Layer_Index[*poi]].push_back(Layer_Index[i]); + ++poi; + } + } +} + +vector Search_Path (unsigned int target_num) { //搜索到达目标布局的一条最短路径 返回vector类 + vector path; + int temp = -1; + path.push_back(target_num); //路径中加入目标布局 + while (temp != 0) { + temp = path[path.size() - 1]; + path.push_back(*Source[temp].begin()); + } + path.pop_back(); //去掉重复的根布局 + temp = path.size() / 2; //反置整个路径 + for (int i = 0; i < temp; i++) { + swap(path[i], path[path.size() - i - 1]); + } + for (int i = 0; i < path.size(); i++){ //将序号改成布局的编码 + path[i] = List[path[i]]; + } + return path; +} + +void Date_Back_quick (int num) { + if (num == -1) {return;} + Solution_quick.push_back(List[num]); + if (num == 0) {return;} + while (Source_quick[num] != 0) { + num = Source_quick[num]; + Solution_quick.push_back(List[num]); + } + Solution_quick.push_back(List[0]); + unsigned int i; + for (i = 0; i < Solution_quick.size() / 2 ; i++) { + swap(Solution_quick[i],Solution_quick[Solution_quick.size() - i - 1]); + } +} + +void Calculate_quick (unsigned int Start_Code) { //启动计算引擎 + unsigned int i; + for (i = 0; i <= 0xFFFF; i++) {Hash[i].clear();} //初始化 + List.clear(); + Source_quick.clear(); + Solution_num_quick = -1; + Hash[(Start_Code>>4) & 0xFFFF].push_back(0); //加入初始布局 + List.push_back(Start_Code); + Source_quick.push_back(0); + Now_Move = 0; //搜索目标指向根节点 + while (Now_Move != List.size()) { //进行广度优先搜索 + Analyse_Code(List[Now_Move]); //解析目标布局 + if (block[0].address == 13) { + Solution_num_quick = Now_Move; + return; + } + Find_Next(); //根据解析结果搜索所有子布局 + Now_Move++; + } +} + +void Calculate (unsigned int Start_Code) { //启动计算引擎 + unsigned int i; + for (i = 0; i <= 0xFFFF; i++) {Hash[i].clear();} //初始化 + List.clear(); + Layer_Num.clear(); + Source.clear(); + Hash[(Start_Code>>4) & 0xFFFF].push_back(0); //加入初始布局 + List.push_back(Start_Code); + Layer_Num.push_back(0); + Source.push_back(int_list); + Now_Move = 0; //搜索目标指向根节点 + while (Now_Move != List.size()) { //进行广度优先搜索 + Analyse_Code(List[Now_Move]); //解析目标布局 + Find_Next(); //根据解析结果搜索所有子布局 + Now_Move++; + } + Split_Layer(); +} + +void Add_Case (unsigned int Code) { //将计算结果加入队列 + list ::iterator poi; //定义迭代器 + poi = Hash[(Code>>4) & 0xFFFF].begin(); //设置poi为索引表的起始点 + while (poi != Hash[(Code>>4) & 0xFFFF].end()) { //遍历索引表 + if (Code == List[*poi]) { //若发现重复 + if (quick == true) {return;} + if ((Layer_Num[*poi] - Layer_Num[Now_Move]) == 1) { //若高一层 + Source[*poi].push_back(Now_Move); //加入父节点列表 + } + return; //重复 退出 + } + ++poi; + } + Hash[(Code>>4) & 0xFFFF].push_back(List.size()); //将计算结果添加至索引表 + List.push_back(Code); //将计算结果加入队列 + if (quick == false) { + Layer_Num.push_back(Layer_Num[Now_Move] + 1); //添加对应的层数 + Source.push_back(int_list); //初始化其父节点列表 + Source[Source.size()-1].push_back(Now_Move); //将正在进行搜索的布局添加为父节点 + } else { + Source_quick.push_back(Now_Move); //将正在进行搜索的布局添加为父布局 + } +} + +void Fill_Block (unsigned char addr, unsigned char style, unsigned char filler) { //用指定内容填充table中指定的位置 + if (style == 0) {table[addr] = table[addr + 1] = table[addr + 4] = table[addr + 5] = filler;} //2*2 + else if (style == 1) {table[addr] = table[addr + 1] = filler;} //2*1 + else if (style == 2) {table[addr] = table[addr + 4] = filler;} //1*2 + else if (style == 3) {table[addr] = filler;} //1*1 +} + +void Move_Block (unsigned char num, unsigned char dir_1, unsigned char dir_2) { //按要求移动块并将移动后的编码传给Add_Case + unsigned char i, addr, addr_bak; + addr = block[num].address; + addr_bak = addr; + + if (dir_1 == Up) {addr -= 4;} //第一次移动 + else if (dir_1==Down) {addr += 4;} + else if (dir_1==Left) {addr--;} + else if (dir_1==Right) {addr++;} + if (dir_2 == Up) {addr -= 4;} //第二次移动 + else if (dir_2 == Down) {addr += 4;} + else if (dir_2 == Left) {addr--;} + else if (dir_2 == Right) {addr++;} + + Fill_Block(addr_bak, block[num].style, 0xA); //修改 table为移动后的状态 + Fill_Block(addr, block[num].style, num); + block[num].address = addr; + + Add_Case(Get_Code()); //生成编码并赋予Add_Case + + block[num].address = addr_bak; + Fill_Block(addr, block[num].style, 0xA); //还原 table原来的状态 + Fill_Block(addr_bak, block[num].style, num); +} + +void Find_Next() { //寻找所有移动的方式并提交给Move_Block + bool Can_Move[10]; + unsigned char i, addr; + for (i = 0; i < 10; i++) {Can_Move[i] = false;} + for (i = 0; i <= 1; i++) { //寻找位于空格周围的所有块 + addr = space[i]; + if (addr > 3) + if (table[addr - 4] != 0xA) {Can_Move[table[addr - 4]] = true;} + if (addr < 16) + if (table[addr + 4] != 0xA) {Can_Move[table[addr + 4]] = true;} + if (addr % 4 != 0) + if (table[addr - 1] != 0xA) {Can_Move[table[addr - 1]] = true;} + if (addr % 4 != 3) { + if (table[addr + 1] != 0xA) {Can_Move[table[addr + 1]] = true;}} + } + + for (i = 0; i <= 9; i++) { + if (Can_Move[i] == true) { //若该块可能可以移动 + addr = block[i].address; + if (block[i].style == 0) { //2*2 + if ((Check_Empty(addr, Up, 1) == true) && + (Check_Empty(addr + 1,Up, 1) == true)) {Move_Block(i, Up, 0);} + + if ((Check_Empty(addr, Down, 2) == true) && + (Check_Empty(addr + 1,Down, 2) == true)) {Move_Block(i, Down, 0);} + + if ((Check_Empty(addr, Left, 1) == true) && + (Check_Empty(addr + 4, Left, 1) == true)) {Move_Block(i, Left, 0);} + + if ((Check_Empty(addr, Right, 2) == true) && + (Check_Empty(addr + 4, Right, 2) == true)) {Move_Block(i, Right, 0);} + } + else if (block[i].style == 1) { //2*1 + if ((Check_Empty(addr, Up, 1) == true) && + (Check_Empty(addr + 1, Up, 1) == true)) {Move_Block(i, Up, 0);} + + if ((Check_Empty(addr, Down, 1) == true) && + (Check_Empty(addr + 1, Down, 1) == true)) {Move_Block(i, Down, 0);} + + if (Check_Empty(addr, Left, 1) == true) { + Move_Block(i, Left, 0); + if (Check_Empty(addr, Left, 2) == true) {Move_Block(i, Left, Left);} + } + + if (Check_Empty(addr, Right, 2) == true) { + Move_Block(i, Right, 0); + if (Check_Empty(addr, Right, 3) == true) {Move_Block(i, Right, Right);} + } + } + else if (block[i].style == 2) { //1*2 + if (Check_Empty(addr, Up, 1) == true) { + Move_Block(i, Up, 0); + if (Check_Empty(addr, Up, 2) == true) {Move_Block(i, Up, Up);} + } + + if (Check_Empty(addr, Down, 2) == true) { + Move_Block(i, Down, 0); + if (Check_Empty(addr, Down, 3) == true) {Move_Block(i, Down, Down);} + } + + if ((Check_Empty(addr, Left, 1) == true) && + (Check_Empty(addr + 4, Left, 1) == true)) {Move_Block(i, Left, 0);} + + if ((Check_Empty(addr, Right, 1) == true) && + (Check_Empty(addr + 4, Right, 1) == true)) {Move_Block(i, Right, 0);} + } + else if (block[i].style == 3) { //1*1 + if (Check_Empty(addr, Up, 1) == true) { + Move_Block(i, Up, 0); + if (Check_Empty(addr - 4, Up, 1) == true) {Move_Block(i, Up, Up);} + if (Check_Empty(addr - 4, Left, 1) == true) {Move_Block(i, Up, Left);} + if (Check_Empty(addr - 4, Right, 1) == true) {Move_Block(i, Up, Right);} + } + + if (Check_Empty(addr, Down, 1) == true) { + Move_Block(i, Down, 0); + if (Check_Empty(addr + 4, Down, 1) == true) {Move_Block(i, Down, Down);} + if (Check_Empty(addr + 4, Left, 1) == true) {Move_Block(i, Down, Left);} + if (Check_Empty(addr + 4, Right, 1) == true) {Move_Block(i, Down, Right);} + } + + if (Check_Empty(addr, Left, 1) == true) { + Move_Block(i, Left, 0); + if (Check_Empty(addr - 1, Up, 1) == true) {Move_Block(i, Left, Up);} + if (Check_Empty(addr - 1, Down, 1) == true) {Move_Block(i, Left, Down);} + if (Check_Empty(addr - 1, Left, 1) == true) {Move_Block(i, Left, Left);} + } + + if (Check_Empty(addr, Right, 1) == true) { + Move_Block(i, Right, 0); + if (Check_Empty(addr + 1, Up, 1) == true) {Move_Block(i, Right, Up);} + if (Check_Empty(addr + 1, Down, 1) == true) {Move_Block(i, Right, Down);} + if (Check_Empty(addr + 1, Right, 1) == true) {Move_Block(i, Right, Right);} + } + } + } + } +} + +bool Check_Empty (unsigned char address, unsigned char dir, unsigned char num) { //判断指定位置是否为空格 若不是空格或者无效返回false + unsigned char x, y, addr; + if (address > 19) {return false;} //输入位置不存在 + + x = address % 4; + y = (address - x) / 4; + if (dir == Up) { //上方 + if (y < num) {return false;} + addr = address - num * 4; + } + if (dir == Down) { //下方 + if (y + num > 4) {return false;} + addr = address + num * 4; + } + if (dir == Left) { //左侧 + if (x < num) {return false;} + addr = address - num; + } + if (dir == Right) { //右侧 + if(x + num > 3){return false;} + addr = address + num; + } + + if (table[addr] == 0xA) { + return true; + } else { + return false; + } +} + +unsigned int Get_Code() { //生成编码 + bool temp[20]; + unsigned int Code = 0; + unsigned char i, addr, style; + + for (i = 0; i < 20; i++) {temp[i] = false;} //初始化 + temp[block[0].address] = temp[block[0].address + 1] = + temp[block[0].address + 4] = temp[block[0].address + 5] = true; + + Code |= block[0].address<<24; //2*2块的位置 + addr = 0; + for (i = 1; i <= 11; i++) { + while(temp[addr] == true){ //找到下一个未填充的空格 + if (addr < 19) { + addr++; + } else { + return 0; + } + } + if (table[addr] == 0xA) { //空格 + temp[addr] = true; + } else { + style = block[table[addr]].style; + if (style == 1) { //2*1 + temp[addr] = temp[addr + 1] = true; + Code |= 1<<(24 - i * 2); + } + else if (style == 2) { //1*2 + temp[addr] = temp[addr + 4] = true; + Code |= 2<<(24 - i * 2); + } + else if (style == 3) { //1*1 + temp[addr] = true; + Code |= 3<<(24 - i * 2); + } + } + } + return Code; +} + +void Analyse_Code (unsigned int Code) { //解译编码到 table[20] block[10] space[2]中 + unsigned char i, addr, style; + unsigned char num_space = 0, num_type_1 = 0, num_type_2 = 5; + space[0] = space[1] = 0xFF; //初始化 + for (i = 0; i < 20; i++) {table[i] = 0xFF;} + for (i = 0; i <= 9; i++) { + block[i].address = 0xFF; + block[i].style = 0xFF; + } + + block[0].address = 0xF & (Code>>24); //开始解译 + if (block[0].address > 14) {goto err;} //2*2块越界 退出 + block[0].style = 0; //设置2*2块的参数 + Fill_Block(block[0].address, 0, 0x0); + addr = 0; + for (i = 0; i < 11; i++) { //遍历 10个块 + while (table[addr] != 0xFF){ //向下搜索空块 + if (addr < 19) { + addr++; + } else { + break; + } + } + style = 0x3 & (Code>>(22 - i * 2)); //0:space 1:2*1 2:1*2 3:1*1 + if (style == 0) { //space + table[addr] = 0xA; + space[num_space] = addr; + if (num_space == 0) {num_space++;} + } + if (style == 1) { //2*1 + if (num_type_1 < 5) {num_type_1++;} + if (addr > 18) {goto err;} //2*1块越界 + block[num_type_1].style = 1; + block[num_type_1].address = addr; + table[addr] = table[addr + 1] = num_type_1; + } + if (style == 2) { //1*2 + if (num_type_1 < 5) {num_type_1++;} + if (addr > 15) {goto err;} //1*2块越界 + block[num_type_1].style = 2; + block[num_type_1].address = addr; + table[addr] = table[addr + 4] = num_type_1; + } + if (style == 3) { //1*1 + if (num_type_2 < 9) {num_type_2++;} + block[num_type_2].style = 3; + block[num_type_2].address = addr; + table[addr] = num_type_2; + } + } + err:; +} + +bool Check (unsigned int Code) { //检查编码是否合法 正确返回true 错误返回false + bool temp[20]; + unsigned char addr, i; + Analyse_Code(Code); + + for (i = 0; i < 20; i++){temp[i] = false;} //初始化 + for (i = 0; i < 20; i++) { //检查table内容是否合法 + if (table[i] > 10) {return false;} + } + + if (block[0].style != 0) {return false;} //检查2*2块 + for (i = 1; i <= 5; i++) { //检查2*1与1*2块 + if ((block[i].style != 1) && (block[i].style != 2)) {return false;} + } + for (i = 6; i <= 9; i++) { //检查1*1块 + if (block[i].style != 3) {return false;} + } + for (i = 0; i <= 1; i++) { //检查空格 + if (space[i] > 19) { + return false; + } else { + temp[space[i]] = true; + } + } + + addr = block[0].address; //检查2*2块 + if ((addr > 14) || (addr%4 == 3)) {return false;} + if ((temp[addr] == true) || (temp[addr + 1] == true) || + (temp[addr + 4] == true) || (temp[addr + 5] == true)) {return false;} + temp[addr] = temp[addr + 1] = temp[addr + 4] = temp[addr + 5] = true; + for (i = 1; i <= 5; i++) { //检查2*1与1*2块 + addr = block[i].address; + if (block[i].style == 1) { + if ((addr > 18) || (addr % 4 == 3)) {return false;} + if ((temp[addr] == true) || (temp[addr + 1] == true)) {return false;} + temp[addr] = temp[addr + 1] = true; + } + if (block[i].style == 2) { + if (addr > 15) {return false;} + if ((temp[addr] == true) || (temp[addr + 4] == true)) {return false;} + temp[addr] = temp[addr + 4] = true; + } + } + for (i = 6; i <= 9; i++) { //检查1*1块 + addr = block[i].address; + if (addr > 19) {return false;} + if (temp[addr] == true) {return false;} + temp[addr] = true; + } + return true; +} + +string Change_str (unsigned int dat) { //将编码数据转化为字符 + unsigned char i, bit; + string str = ""; + for (i = 0; i < 7; i++) { + bit = 0xF & dat>>(6 - i)*4; //分离单个十六进制位 + if ((bit >= 0) && (bit <= 9)) {str += bit + 48;} //0~9 + if ((bit >= 0xA) && (bit <= 0xF)) {str += bit + 55;} //A~F + } + return str; +} + +unsigned int Change_int (char str[8]) { //将编码字符转化为int + unsigned int i, dat = 0; + for (i = 0; i < 7; i++) { + if ((str[i] >= 48) && (str[i] <= 57)) {dat = dat | (str[i] - 48)<<(24 - i * 4);} //0~9 + if ((str[i] >= 65) && (str[i] <= 70)) {dat = dat | (str[i] - 55)<<(24 - i * 4);} //A~F + if ((str[i] >= 97) && (str[i] <= 102)) {dat = dat | (str[i] - 87)<<(24 - i * 4);} //a~f + } + return dat; +} + +void Find_All_Case(){ //Right_File's MD5: 4A0179C6AEF266699A73E41ECB4D87C1 + File_Output.open("All_Case.txt"); + unsigned int i; + for (i = 0; i < 0xFFFFFFF; i += 4) { + if (Check(i) == true) {File_Output << Change_str(i) << endl;} + } + File_Output.close(); +} + +void Data_Output(string File_name){ + unsigned int i, j, layer; + File_Output.open(File_name.c_str()); + File_Output << "[Group_size]" << endl << group_size << endl; + File_Output << "[Min_steps]" << endl << min_steps << endl; + File_Output << "[Farthest_steps]" << endl << farthest_steps << endl; + File_Output << "[Min_Solutions]" << endl; + for (i = 0; i < min_Solutions.size(); i++) { + File_Output << Change_str(min_Solutions[i]) << endl; + } + File_Output << "[Farthest_cases]" << endl; + for (i = 0; i < farthest_cases.size(); i++) { + File_Output << Change_str(farthest_cases[i]) << endl; + } + File_Output << "[Solutions]" << endl; + for (i = 0; i < Solutions.size(); i++) { + File_Output << Change_str(Solutions[i]) << " (" << Solutions_steps[i] << ")" << endl; + } + File_Output << "[List]" << endl; + for (i = 0; i < List.size(); i++) { + File_Output << i << " -> " << Change_str(List[i]) << " (" << Layer_Num[i] << "," << Layer_Index[i] << ")" << endl; + } + File_Output << "[Layer]" << endl; + for (layer = 0; layer < Layer.size(); layer++) { + for (i = 0; i < Layer_Next[layer].size(); i++) { + File_Output << "(" << layer << "," << i << ")" << " -> "; + for (j = 0; j < Layer_Next[layer][i].size(); j++) { + File_Output << "(" << (layer+1) << "," << Layer_Next[layer][i][j] << ") "; + } + File_Output << endl; + } + } + File_Output.close(); +} diff --git a/Engine.exe b/Engine.exe deleted file mode 100644 index e126d20..0000000 Binary files a/Engine.exe and /dev/null differ diff --git a/Form_Detail.frm b/Form_Detail.frm new file mode 100644 index 0000000..4d435c1 --- /dev/null +++ b/Form_Detail.frm @@ -0,0 +1,358 @@ +VERSION 5.00 +Begin VB.Form Form_Detail + AutoRedraw = -1 'True + BorderStyle = 1 'Fixed Single + Caption = "ϸϢ" + ClientHeight = 4605 + ClientLeft = 45 + ClientTop = 390 + ClientWidth = 7965 + LinkTopic = "Form1" + MaxButton = 0 'False + MinButton = 0 'False + ScaleHeight = 4605 + ScaleWidth = 7965 + StartUpPosition = 2 'Ļ + Begin VB.CommandButton Command_Analyse + Caption = "ȫԴ" + Height = 300 + Left = 2520 + TabIndex = 4 + Top = 120 + Width = 1695 + End + Begin VB.Timer Timer_Debug + Interval = 100 + Left = 0 + Top = 0 + End + Begin VB.TextBox Text_Debug + Height = 4380 + Left = 7960 + MultiLine = -1 'True + TabIndex = 3 + Top = 120 + Width = 2415 + End + Begin VB.Timer Timer_Get_Data + Interval = 50 + Left = 0 + Top = 0 + End + Begin VB.ListBox List_Data + Height = 4020 + ItemData = "Form_Detail.frx":0000 + Left = 2520 + List = "Form_Detail.frx":0002 + TabIndex = 2 + Top = 480 + Width = 1695 + End + Begin VB.ComboBox Combo_Detail + Height = 300 + Left = 120 + Style = 2 'Dropdown List + TabIndex = 1 + Top = 120 + Width = 2295 + End + Begin VB.ListBox List_Detail + Height = 4020 + ItemData = "Form_Detail.frx":0004 + Left = 120 + List = "Form_Detail.frx":0006 + TabIndex = 0 + Top = 480 + Width = 2295 + End +End +Attribute VB_Name = "Form_Detail" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +Option Explicit +Private Type Case_Block + address As Integer + style As Integer +End Type +Private Type Layer_struct + size As Integer + layer_dat() As String +End Type +Dim wait_data As Boolean, loading As Boolean +Dim Block(0 To 9) As Case_Block +Dim start_x As Integer, start_y As Integer, square_width As Integer, gap As Integer +Dim group_size As Long, min_steps As Integer, farthest_steps As Integer +Dim min_solutions() As String, farthest_cases() As String, solutions() As String, layers() As String, layer() As Layer_struct +Private Sub Form_Load() + start_x = 4350 + start_y = 135 + square_width = 777 + gap = 75 + loading = False + If debug_mode = True Then + Form_Detail.width = 10575 + Text_Debug.Visible = True + Else + Form_Detail.width = 8055 + Text_Debug.Visible = False + End If + If on_top = True Then + SetWindowPos Me.hwnd, -1, 0, 0, 0, 0, 1 Or 2 + Else + SetWindowPos Me.hwnd, -2, 0, 0, 0, 0, 1 Or 2 + End If + ReDim min_solutions(0) + ReDim farthest_cases(0) + ReDim solutions(0) + ReDim layers(0) + ReDim layer(0 To 0) + Combo_Detail.AddItem "ٲ" + Combo_Detail.AddItem "еĽ" + Combo_Detail.AddItem "ԶIJ" + Combo_Detail.AddItem "IJ" + wait_file_name = start_code & ".txt" + If Dir(start_code & ".txt") <> "" Then Kill start_code & ".txt" + Shell "Engine.exe -a " & start_code + wait_cancel = False + waiting = True + wait_data = True + Form_Wait.Show 1 + Print_Block start_x, start_y, square_width * 4 + gap * 5, square_width * 5 + gap * 6, case_line_width, case_color, case_line_color +End Sub +Private Sub Combo_Detail_Click() + Dim i As Long + List_Detail.Clear + If Combo_Detail.ListIndex = 0 Then + If min_steps = -1 Then + List_Detail.AddItem "޽" + Else + List_Detail.AddItem Combo_Detail.Text & "(" & min_steps & "," & UBound(min_solutions) & ")" + End If + ElseIf Combo_Detail.ListIndex = 1 Then + List_Detail.AddItem Combo_Detail.Text & "(" & UBound(solutions) & ")" + ElseIf Combo_Detail.ListIndex = 2 Then + List_Detail.AddItem Combo_Detail.Text & "(" & farthest_steps & "," & UBound(farthest_cases) & ")" + ElseIf Combo_Detail.ListIndex = 3 Then + For i = 0 To UBound(layer) + List_Detail.AddItem "" & i & "(" & layer(i).size & ")" + Next i + End If + List_Detail.ListIndex = 0 +End Sub +Private Sub List_Detail_Click() + Dim i As Long, n As Integer + loading = True + List_Data.Clear + If Combo_Detail.ListIndex = 0 Then + For i = 1 To UBound(min_solutions) + If Not min_steps = -1 Then List_Data.AddItem min_solutions(i) & "(" & min_steps & ")" + Next i + ElseIf Combo_Detail.ListIndex = 1 Then + For i = 1 To UBound(solutions) + n = n + 1 + If n = 200 Then n = 0: DoEvents + List_Data.AddItem Left(solutions(i), 7) & Mid(solutions(i), 9, Len(solutions(i)) - 9) & ")" + Next i + ElseIf Combo_Detail.ListIndex = 2 Then + For i = 1 To UBound(farthest_cases) + List_Data.AddItem farthest_cases(i) & "(" & farthest_steps & ")" + Next i + ElseIf Combo_Detail.ListIndex = 3 Then + For i = 0 To UBound(layer(List_Detail.ListIndex).layer_dat) + List_Data.AddItem layer(List_Detail.ListIndex).layer_dat(i) & "(" & List_Detail.ListIndex & ")" + Next i + End If + If Not min_steps = -1 Then + List_Data.ListIndex = 0 + Else + If Combo_Detail.ListIndex = 2 Or Combo_Detail.ListIndex = 3 Then List_Data.ListIndex = 0 + End If + loading = False +End Sub +Private Sub List_Data_Click() + Call Analyse_Code(Left(List_Data.List(List_Data.ListIndex), 7)) + Call Output_Graph +End Sub +Private Sub Timer_Get_Data_Timer() + Dim dat As String + Combo_Detail.Enabled = Not loading + If wait_data = True And waiting = False Then + wait_data = False + MsgBox Form_Game.Label_Title, , "> _ <" + Call Get_Data(start_code & ".txt") + dat = "" & group_size & "ֲ" & vbCrLf & "ԶΪ" & farthest_steps & "" & vbCrLf + If min_steps = -1 Then dat = dat & "޽" Else dat = dat & "Ҫ" & min_steps & "" + MsgBox dat, , "> _ <" + Combo_Detail.ListIndex = 0 + End If +End Sub +Private Sub Command_Analyse_Click() + MsgBox "ûQAQ", , "> _ <" +End Sub +Private Sub Get_Data(file_name As String) + Dim temp As String + ReDim min_solutions(0) + ReDim farthest_cases(0) + ReDim solutions(0) + ReDim layers(0) + Open file_name For Input As #1 + Line Input #1, temp: Line Input #1, temp + group_size = temp + Line Input #1, temp: Line Input #1, temp + min_steps = temp + Line Input #1, temp: Line Input #1, temp + farthest_steps = temp + Line Input #1, temp: Line Input #1, temp + While (temp <> "[Farthest_cases]") + ReDim Preserve min_solutions(UBound(min_solutions) + 1) + min_solutions(UBound(min_solutions)) = temp + Line Input #1, temp + Wend + Line Input #1, temp + While (temp <> "[Solutions]") + ReDim Preserve farthest_cases(UBound(farthest_cases) + 1) + farthest_cases(UBound(farthest_cases)) = temp + Line Input #1, temp + Wend + Line Input #1, temp + While (temp <> "[List]") + ReDim Preserve solutions(UBound(solutions) + 1) + solutions(UBound(solutions)) = temp + Line Input #1, temp + Wend + Line Input #1, temp + While (temp <> "[Layer]") + ReDim Preserve layers(UBound(layers) + 1) + layers(UBound(layers)) = temp + Line Input #1, temp + Wend + Close #1 + Call split_layer +End Sub +Private Sub split_layer() + Dim i As Long, code As String, num As Integer, index As Integer + For i = 1 To UBound(layers) + code = Mid(layers(i), InStr(1, layers(i), ">") + 2, 7) + num = Mid(layers(i), InStr(1, layers(i), "(") + 1, InStr(1, layers(i), ",") - InStr(1, layers(i), "(") - 1) + index = Mid(layers(i), InStr(1, layers(i), ",") + 1, Len(layers(i)) - InStr(1, layers(i), ",") - 1) + ReDim Preserve layer(0 To num) + ReDim Preserve layer(num).layer_dat(0 To index) + layer(num).layer_dat(index) = code + layer(num).size = index + 1 + Next i +End Sub +Private Sub Output_Graph() + Dim m, X, Y As Integer + Dim width As Integer, height As Integer + Print_Block start_x, start_y, square_width * 4 + gap * 5, square_width * 5 + gap * 6, case_line_width, case_color, case_line_color + For m = 0 To 9 + If Block(m).address <> 25 Then + X = (Block(m).address Mod 4) * (square_width + gap) + gap + start_x + Y = Int(Block(m).address / 4) * (square_width + gap) + gap + start_y + If Block(m).style = 0 Or Block(m).style = 1 Then + width = square_width * 2 + gap + Else + width = square_width + End If + If Block(m).style = 0 Or Block(m).style = 2 Then + height = square_width * 2 + gap + Else + height = square_width + End If + Print_Block X, Y, width, height, block_line_width, block_color, block_line_color + End If + Next m +End Sub +Private Sub Print_Block(print_start_x, print_start_y, print_width, print_height, print_line_width, print_color, print_line_color) + If print_width < 0 Or print_height < 0 Then Exit Sub + FillStyle = 0 + DrawWidth = print_line_width + FillColor = print_color + Line (print_start_x, print_start_y)-(print_start_x + print_width, print_start_y + print_height), print_color, B + Line (print_start_x, print_start_y)-(print_start_x + print_width, print_start_y + print_height), print_line_color, B +End Sub +Private Sub Analyse_Code(code As String) + On Error Resume Next + Dim temp(1 To 12) As Integer + Dim i, addr, style As Integer + Dim type_1, type_2, type_3 As Integer + Dim Table(0 To 19) As Integer + Dim num As Integer, b1 As Integer, b2 As Integer + Dim dat As String + For i = 1 To 6 + dat = Mid(code, i + 1, 1) + If Asc(dat) >= 48 And Asc(dat) <= 57 Then num = Int(dat) + If Asc(dat) >= 65 And Asc(dat) <= 70 Then num = Asc(dat) - 55 + b1 = num Mod 4 + b2 = (num - b1) / 4 Mod 4 + temp(i * 2 - 1) = b2 + temp(i * 2) = b1 + Next i + type_1 = 0: type_2 = 0: type_3 = 5 + For i = 0 To 19 + Table(i) = 69 + Next i + For i = 0 To 9 + Block(i).address = 69 + Block(i).style = 69 + Next i + dat = Left(code, 1) + If Asc(dat) >= 48 And Asc(dat) <= 57 Then num = Int(dat) + If Asc(dat) >= 65 And Asc(dat) <= 70 Then num = Asc(dat) - 55 + Block(0).address = num + Block(0).style = 0 + If Block(0).address > 14 Then GoTo err + Table(Block(0).address) = 0 + Table(Block(0).address + 1) = 0 + Table(Block(0).address + 4) = 0 + Table(Block(0).address + 5) = 0 + addr = 0 + For i = 1 To 11 + Do While Table(addr) <> 69 + If addr < 19 Then + addr = addr + 1 + Else + Exit Do + End If + Loop + style = temp(i) + If style = 0 Then + Table(addr) = 10 + ElseIf style = 1 Then + If type_2 < 5 Then type_2 = type_2 + 1 + If addr > 18 Then GoTo err + Block(type_2).style = 1 + Block(type_2).address = addr + Table(addr) = type_2 + Table(addr + 1) = type_2 + ElseIf style = 2 Then + If type_2 < 5 Then type_2 = type_2 + 1 + If addr > 15 Then GoTo err + Block(type_2).style = 2 + Block(type_2).address = addr + Table(addr) = type_2 + Table(addr + 4) = type_2 + ElseIf style = 3 Then + If type_3 < 9 Then type_3 = type_3 + 1 + Block(type_3).style = 3 + Block(type_3).address = addr + Table(addr) = type_3 + End If + Next i +err: +End Sub +Private Sub Timer_Debug_Timer() + Dim debug_dat As String + debug_dat = debug_dat & "group_size=" & group_size & vbCrLf + debug_dat = debug_dat & "min_steps=" & min_steps & vbCrLf + debug_dat = debug_dat & "farthest_steps=" & farthest_steps & vbCrLf + debug_dat = debug_dat & vbCrLf + debug_dat = debug_dat & "min_solutions->" & UBound(min_solutions) & vbCrLf + debug_dat = debug_dat & "farthest_cases->" & UBound(farthest_cases) & vbCrLf + debug_dat = debug_dat & "solutions->" & UBound(solutions) & vbCrLf + debug_dat = debug_dat & "layers->" & UBound(layers) & vbCrLf + debug_dat = debug_dat & "layer->" & UBound(layer) & vbCrLf + Text_Debug = debug_dat +End Sub diff --git a/Form_Detail.frx b/Form_Detail.frx new file mode 100644 index 0000000..1b1cb4d Binary files /dev/null and b/Form_Detail.frx differ diff --git a/Form_Game.frm b/Form_Game.frm index 732d4c4..47404a5 100644 --- a/Form_Game.frm +++ b/Form_Game.frm @@ -2,7 +2,7 @@ VERSION 5.00 Begin VB.Form Form_Game AutoRedraw = -1 'True BorderStyle = 1 'Fixed Single - Caption = "HRD Game v1.7 by Dnomd343" + Caption = "HRD Game v1.8 by Dnomd343" ClientHeight = 7305 ClientLeft = 45 ClientTop = 690 @@ -14,6 +14,14 @@ Begin VB.Form Form_Game ScaleHeight = 7305 ScaleWidth = 7290 StartUpPosition = 2 'Ļ + Begin VB.CommandButton Command_Detail + Caption = "ϸ" + Height = 495 + Left = 5760 + TabIndex = 15 + Top = 6360 + Width = 1335 + End Begin VB.CommandButton Command_Prompt Caption = "ʾһ" Height = 495 @@ -319,6 +327,9 @@ End Sub Private Sub Command_Solution_Click() Form_Solution.Show 1 End Sub +Private Sub Command_Detail_Click() + Form_Detail.Show 1 +End Sub Private Sub Command_Add_Favourite_Click() favourite_add_save = True favourite_add_init_code = Label_Code diff --git a/HRD_Game.vbp b/HRD_Game.vbp index bfe667f..a85915d 100644 --- a/HRD_Game.vbp +++ b/HRD_Game.vbp @@ -9,6 +9,7 @@ Form=Form_Favourite.frm Form=Form_Favourite_Add.frm Form=Form_Solution.frm Form=Form_Wait.frm +Form=Form_Detail.frm IconForm="Form_Game" Startup="Form_Game" HelpFile="" @@ -19,7 +20,7 @@ Name="HRD_Game" HelpContextID="0" CompatibleMode="0" MajorVer=1 -MinorVer=7 +MinorVer=8 RevisionVer=0 AutoIncrementVer=0 ServerSupportFiles=0 diff --git a/HRD_Game.vbw b/HRD_Game.vbw index 3331a4e..ab50f7a 100644 --- a/HRD_Game.vbw +++ b/HRD_Game.vbw @@ -1,9 +1,10 @@ Form_Game = 52, 52, 883, 479, , 26, 28, 857, 453, C Module = 52, 52, 883, 479, -Form_Classic_Cases = 104, 104, 891, 531, Z, 104, 104, 937, 531, C +Form_Classic_Cases = 104, 104, 891, 531, , 104, 104, 937, 531, C Form_Creator = 130, 130, 917, 557, , 104, 104, 891, 531, C Form_Rand_Case = 78, 78, 855, 505, , 156, 156, 933, 583, C Form_Favourite = 52, 52, 829, 479, , 26, 26, 803, 453, C Form_Favourite_Add = 156, 156, 933, 583, , 182, 182, 959, 609, C Form_Solution = 104, 104, 862, 531, , 0, 0, 758, 427, C Form_Wait = 104, 104, 862, 531, , 78, 78, 836, 505, C +Form_Detail = 26, 26, 784, 453, , 78, 78, 836, 505, C diff --git a/Module.bas b/Module.bas index a37690e..5679489 100644 --- a/Module.bas +++ b/Module.bas @@ -5,6 +5,7 @@ Public Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal Public Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hkey As Long) As Long Public Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long Public Declare Function SHDeleteKey Lib "shlwapi.dll" Alias "SHDeleteKeyA" (ByVal hkey As Long, ByVal pszSubKey As String) As Long +Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Public Type FILETIME dwLowDateTime As Long dwHighDateTime As Long