/********************************* * * txtから問題生成 * * *******************************/ public static void manageMakingProblemFromTxt() { Problem p = new Problem(); if (!p.readDotTapaTxt(Problem.dotfile_path)) { return; } p.setBoxNumber(); if (Tapa.DEBUG) { Console.WriteLine("数字マス配置完了"); Tapa.printBoard(); } // 0:add 1:del 2:add+del p.generateTapaPrblem(1); Tapa.processnum_numbox = Tapa.numbox_coord_list.Count; generateTapaProblemText(Problem.savefile_path); }
/********************************* * * 問題のランダム生成 * * *******************************/ public static void manageMakingProblem() { Problem p; do { Tapa.resetBoard(); p = new Problem(); p.setRandomWhiteBox(); if (Tapa.DEBUG) { Console.WriteLine("白マス配置完了"); Tapa.printBoard(); } p.makeBlackBoxRoute(); if (Tapa.DEBUG) { Console.WriteLine("黒マス配置完了"); Tapa.printBoard(); } } while (!Tapa.isCorrectAnswer()); p.setBoxNumber(); if (Tapa.DEBUG) { Console.WriteLine("数字マス配置完了"); Tapa.printBoard(); } p.generateTapaPrblem(1); Tapa.processnum_numbox = Tapa.numbox_coord_list.Count; generateTapaProblemText(Problem.savefile_path); }
/********************************* * * txtからヒントを生成 * * *******************************/ public static bool manageMakingHintFromTxt() { Problem p = new Problem(); p.readPartwayTapaTxt(Problem.prb_hintfile_path); StateSave partway = new StateSave(); StateSave result = new StateSave(); // 入力盤面の保存 StateSave.saveNowState(partway); // 初期盤面を解けないとき,途中まででも出力. if (!Problem.judgeCanSolveInitialBoard(partway, result)) { StateSave.loadSavedState(result); generateTapaHintText(Problem.ans_hintfile_path); return false; } // 途中盤面が正しい場合,ヒントを与える. if (Problem.isCorrectMiddleBoard(partway)) { Tapa.solveTapa(Tapa.not_deployedbox_coord_list.Count - calcHintNum()); } // そうでない場合,間違った箇所を未定マスにする. else { Problem.modifyMistakeBoard(partway, result); } // ans_hintfile_path = @"C:\Users\Amano\OneDrive\zemi\ans_tapa.txt"; // ヒントtxtはexeファイルと同じディレクトリ generateTapaHintText(Problem.ans_hintfile_path); return true; }
/********************************* * * 数字マスを追加して問題生成する。 * 引数: * boxnumber_in_whitebox_coord_dict : 数字マスの座標と数字の対応 * * *******************************/ private void generateTapaProblemInAddNumBox(Dictionary <Coordinates, int> boxnumber_in_whitebox_coord_dict) { do { // 時間計測開始 System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); // 埋める数字マスをランダムに選択 Coordinates adopting_boxnumber_coord = Problem.can_be_number_whitebox_list[ Problem.getRandomInt(0, Problem.can_be_number_whitebox_list.Count)]; Box tmp_box = Tapa.box[adopting_boxnumber_coord.x][adopting_boxnumber_coord.y]; // 選択した座標が既に配色済みの場合 if (tmp_box.Color != Box.NOCOLOR) { Problem.can_be_number_whitebox_list.Remove(adopting_boxnumber_coord); // 数字マスを格納できる座標リストから除外 // boxnumber_in_whitebox_coord_dict.Remove(adopting_boxnumber_coord); // ハッシュから除外 continue; } Box.during_make_inputbord = true; tmp_box.hasNum = true; // 数字を持ってるフラグをオンにする tmp_box.boxNum = boxnumber_in_whitebox_coord_dict[adopting_boxnumber_coord]; // 選択した座標に数字を格納 Tapa.numbox_coord_list.Add(new Coordinates(adopting_boxnumber_coord)); // 数字マスリストに追加 Tapa.not_deployedbox_coord_list.Remove(adopting_boxnumber_coord); // 未定マスリストから除外 tmp_box.id_list = PatternAroundNumBox.getPatternAroundNumBoxList(tmp_box.boxNum); // 数字に対応したidを格納 Problem.can_be_number_whitebox_list.Remove(adopting_boxnumber_coord); // 数字マスを格納できる座標リストから除外 boxnumber_in_whitebox_coord_dict.Remove(adopting_boxnumber_coord); // ハッシュから除外 Box.during_make_inputbord = false; Tapa.solveTapa(); //時間計測終了 sw.Stop(); adopting_boxnumber_coord.printCoordinates(); Console.WriteLine("の追加にかかった時間 >> " + sw.Elapsed + "(" + Problem.can_be_number_whitebox_list.Count + ")"); } while (Problem.can_be_number_whitebox_list.Count > 0); Console.WriteLine("数字マスランダム配置後"); Tapa.printBoard(); while (Tapa.not_deployedbox_coord_list.Count > 0) { Console.WriteLine("未定マスが存在!!!!"); // 白マス周りにある未定マスの数を格納 Dictionary <Coordinates, int> count_whitebox_dict = new Dictionary <Coordinates, int>(); foreach (Coordinates tmp_co in Tapa.not_deployedbox_coord_list) { List <Coordinates> whitebox_around_notdeployedbox_list = Box.getWhiteBoxCoordAround8(tmp_co); foreach (Coordinates tmp_whitebox_co in whitebox_around_notdeployedbox_list) { if (!count_whitebox_dict.ContainsKey(tmp_whitebox_co)) { count_whitebox_dict[tmp_whitebox_co] = 1; } else { count_whitebox_dict[tmp_whitebox_co]++; } } } int max = 0; Coordinates white2numbox = new Coordinates(); // 未定マスが最も多く周囲にある白マス foreach (KeyValuePair <Coordinates, int> pair in count_whitebox_dict) { if (pair.Value > max) { white2numbox = new Coordinates(pair.Key); } } Box.during_make_inputbord = true; Box tmp_box = Tapa.box[white2numbox.x][white2numbox.y]; tmp_box.hasNum = true; tmp_box.boxNum = boxnumber_in_whitebox_coord_dict[white2numbox]; // 数字を格納 Tapa.numbox_coord_list.Add(new Coordinates(white2numbox)); // 数字マスリストに追加 tmp_box.id_list = PatternAroundNumBox.getPatternAroundNumBoxList(tmp_box.boxNum); // 数字に対応したidを格納 Box.during_make_inputbord = false; Tapa.solveTapa(); if (Tapa.DEBUG) { Console.WriteLine("未定マス修正"); Tapa.printBoard(); } } // 数字ごとのidを元に戻す(回答中にid_listは減少) PatternAroundNumBox.preparePatternArroundNumBox(); // 盤面にある数字マス以外のマスを未定マスにする Tapa.numbox_coord_list.Clear(); // 数字マスの座標リスト Tapa.not_deployedbox_coord_list.Clear(); // 未定マスの座標リスト Tapa.isolation_notdeployedboxes_group_list.Clear(); // 一繋がりの未定マス群の座標リスト Tapa.edge_blackbox_coord_list.Clear(); // 伸び代のある黒マスの座標リスト Tapa.isolation_blackboxes_group_list.Clear(); // 一繋がりの黒マス群の座標リスト for (int i = 1; i <= Tapa.MAX_BOARD_ROW; i++) { for (int j = 1; j <= Tapa.MAX_BOARD_COL; j++) { Box tmp = Tapa.box[i][j]; if (!tmp.hasNum) { tmp.revision_color = Box.NOCOLOR; Tapa.not_deployedbox_coord_list.Add(new Coordinates(tmp.coord)); } else { Tapa.numbox_coord_list.Add(new Coordinates(tmp.coord)); } } } }
/********************************* * * 切断点以外の団子マスを除去する * * *******************************/ private static void removeDumpling() { Problem p = new Problem(); p.doTarjan(Tapa.isolation_blackboxes_group_list[0], Box.BLACK); for (int i = Tapa.isolation_blackboxes_group_list[0].Count - 1; i >= 0; i--) { Coordinates co = Tapa.isolation_blackboxes_group_list[0][i]; if (!Box.checkNotDumplingBlackBoxAround(co) // 自身の周りで団子マスができていて && !Problem.cutpoint_list.Contains(co)) { // かつ自身が切断点ではないなら Box b = Tapa.box[co.x][co.y]; // 自身を未定マスにする b.revision_color = Box.NOCOLOR; Tapa.isolation_blackboxes_group_list[0].RemoveAt(i); // 切断点を再度記録 p.doTarjan(Tapa.isolation_blackboxes_group_list[0], Box.BLACK); } } }
/********************************* * * モザイク画からぱずぷれ形式に変換する * * 引数 * dir_path : 保存先ディレクトリ * file_name : 保存ファイル名の頭 * mozaic : 変換対象のbitmap * size : モザイクのサイズ * * *******************************/ public static void makePzprFromMozaic(string savedir_path, string file_name, Bitmap mozaic, int size) { // 末尾に \ がなければ追加 savedir_path += savedir_path[savedir_path.Length - 1].Equals('\\') ? "" : @"\"; // 拡張子を削除したファイルパスを取得 // http://jeanne.wankuma.com/tips/csharp/path/getfilenamewithoutextension.html string file_midpath = savedir_path + System.IO.Path.GetFileNameWithoutExtension(file_name); string mozaic_path = file_midpath + "_mozaic.txt"; string connect_path = file_midpath + "_connect.txt"; string deldump1_path = file_midpath + "_deldump1.txt"; string deldump2_path = file_midpath + "_deldump2.txt"; // 時間計測 System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); // ぱずぷれ形式に変換 makeBoardFromDot(mozaic, size); Problem.generateTapaHintText(mozaic_path); Console.WriteLine("complete pzpr_mozaic " + sw.Elapsed); sw.Restart(); // 孤立した黒マスを繋げる Problem p = new Problem(); // p.readDotTapaTxt(tmp_dir + dot_name + "deldump1.txt"); p.readDotTapaTxt(mozaic_path); connectIsoBlackBoxGroup(); Problem.generateTapaHintText(connect_path); Console.WriteLine("complete pzpr_connect " + sw.Elapsed); sw.Restart(); // 黒塗り部分を白にする avoidDumplingBoxes(); Problem.generateTapaHintText(deldump1_path); Console.WriteLine("complete pzpr_deldump1 " + sw.Elapsed); sw.Restart(); connectIsoBlackBoxGroup(); // 黒マスの団子を削除 removeDumpling(); removeCutDumpling(); Problem.generateTapaHintText(deldump2_path); Console.WriteLine("complete pzpr_deldump2 " + sw.Elapsed); sw.Reset(); }