/********************************* * * bitmapからぱずぷれ形式のtxtを生成 * * 引数 * mozaic : 変換対象のbitmap * size : マスのサイズ * * *******************************/ public static void makeBoardFromDot(Bitmap mozaic, int size = 6) { // ビットマップ画像から全てのピクセルを抜き出す PixelManipulator s = PixelManipulator.LoadBitmap(mozaic); // 範囲チェック if (size < 1) { size = 1; } if (size > 32) { size = 32; } int w = size * 2 + 1; Tapa.MAX_BOARD_ROW = s.height / w; // 問題の行数 Tapa.MAX_BOARD_COL = s.width / w; // 問題の列数 Tapa.BOX_SUM = Tapa.MAX_BOARD_ROW * Tapa.MAX_BOARD_COL; Tapa.resetBoard(); // 全てのピクセルを巡回する Box.during_make_inputbord = true; s.EachPixel((x, y) => { // 確認の終わったモザイクマスは飛ばす if (x % w != 0 || y % w != 0) { return; } // 2値画像なので、rのみのチェックでok Tapa.box[y / w][x / w].Color = (s.R(x, y) == 0) ? Box.BLACK : Box.NOCOLOR; }); Box.during_make_inputbord = false; }
/********************************* * * 盤面の間違っている箇所を未定マスにする. * * 引数 * partway : 途中盤面を保存したもの * result : 解答 * * *******************************/ private static void modifyMistakeBoard(StateSave partway, StateSave result) { // 数字マスの座標と数値のハッシュを作成 Dictionary <Coordinates, int> num_dict = new Dictionary <Coordinates, int>(); foreach (Coordinates num in Tapa.numbox_coord_list) { num_dict[num] = Tapa.box[num.x][num.y].boxNum; } // 盤面の初期化 Tapa.resetBoard(); // 数字マスの設置 Problem.setNumBoxInBoard(num_dict); // 回答途中の盤面のうち,正しいマスのみを残す for (int i = 1; i <= Tapa.MAX_BOARD_ROW; i++) { for (int j = 1; j <= Tapa.MAX_BOARD_COL; j++) { Box r = result.saved_box[i][j]; Box p = partway.saved_box[i][j]; if (p.Color == Box.NOCOLOR || p.Color != r.Color) { continue; } else { Tapa.box[i][j].Color = p.Color; } } } }
/********************************* * * 問題のランダム生成 * * *******************************/ 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); }
/********************************* * * 盤面の初期状態から始めて問題を解けるか判断する. * * True:解ける * * 引数 * partway : 途中盤面を保存したもの * result : 解答保存用 * * *******************************/ private static bool judgeCanSolveInitialBoard(StateSave partway, StateSave result) { // 数字マスの座標と数値のハッシュを作成 Dictionary <Coordinates, int> num_dict = new Dictionary <Coordinates, int>(); foreach (Coordinates num in Tapa.numbox_coord_list) { num_dict[num] = Tapa.box[num.x][num.y].boxNum; } // 盤面の初期化 Tapa.resetBoard(); // 数字マスの設置 Problem.setNumBoxInBoard(num_dict); // 回答する Tapa.solveTapa(); StateSave.saveNowState(result); if (Tapa.isCorrectAnswer()) { StateSave.loadSavedState(partway); return(true); } StateSave.loadSavedState(partway); return(false); }
/********************************* * * ぱずぷれで作成したtxtファイルの読み込み(回答途中) * # : 黒 * + : 白 * ・ : 未定 * 1,2 : [12] * * *******************************/ public void readPartwayTapaTxt(string readfile_path) { List <string> line_list = new List <string>(); using (StreamReader sr = new StreamReader( readfile_path, Encoding.GetEncoding("Shift_JIS"))) { string line = ""; while ((line = sr.ReadLine()) != null) { line_list.Add(line); } } if (line_list[0] != "pzprv3" || line_list[1] != "tapa") { Problem.is_correct_txtformat = false; return; } Tapa.MAX_BOARD_ROW = Convert.ToInt32(line_list[2]); // 3行目に行数 Tapa.MAX_BOARD_COL = Convert.ToInt32(line_list[3]); // 4行目に列数 Tapa.BOX_SUM = Tapa.MAX_BOARD_ROW * Tapa.MAX_BOARD_COL; // 盤面生成 Tapa.resetBoard(); for (int i = 1; i <= Tapa.MAX_BOARD_ROW; i++) { string wk_str = line_list[i + 3].Replace(",", ""); // 数字マスの区切りを削除 for (int j = 1; j <= Tapa.MAX_BOARD_COL; j++) { int pt = wk_str.IndexOf(' '); if (wk_str.Substring(0, pt) == "#") { Tapa.box[i][j].connecting_color = Box.BLACK; } else if (wk_str.Substring(0, pt) == "+") { Tapa.box[i][j].connecting_color = Box.WHITE; } else if (char.IsDigit(wk_str, 0)) { Box tmp_box = Tapa.box[i][j]; tmp_box.hasNum = true; tmp_box.boxNum = int.Parse(wk_str.Substring(0, pt)); Tapa.not_deployedbox_coord_list.Remove(tmp_box.coord); Tapa.numbox_coord_list.Add(tmp_box.coord); } else { } wk_str = wk_str.Substring(pt + 1); } } // 数字に対応したidを格納 PatternAroundNumBox.preparePatternArroundNumBox(); }
/********************************* * * 盤面の埋め方が正しいか判断する * * true : 正しい * * 引数 * partway : 途中盤面 * * *******************************/ private static bool isCorrectMiddleBoard(StateSave partway) { Tapa.solveTapa(); if (Tapa.isCorrectAnswer()) { StateSave.loadSavedState(partway); return(true); } StateSave.loadSavedState(partway); return(false); }
/********************************* * * 問題を生成するプログラムを呼び出す。 * 引数 * pattern : 呼び出すプログラムのid * 0 >> 数字を追加して問題生成する * 1 >> 数字を削除して問題生成する * 2 >> 数字を追加したあと冗長な数字を削除して問題生成する * * *******************************/ private void generateTapaPrblem(int pattern) { // 数字マスの座標とその数字を関連付けたハッシュ Dictionary <Coordinates, int> boxnumber_in_whitebox_coord_dict = new Dictionary <Coordinates, int>(); foreach (Coordinates tmp_co in Problem.can_be_number_whitebox_list) { boxnumber_in_whitebox_coord_dict[tmp_co] = Tapa.box[tmp_co.x][tmp_co.y].boxNum; } // (黒マスListなども含む)盤面の初期化 Tapa.resetBoard(); switch (pattern) { case 0: generateTapaProblemInAddNumBox(boxnumber_in_whitebox_coord_dict); break; case 1: // 数字マスを全て配置する Box.during_make_inputbord = true; foreach (KeyValuePair <Coordinates, int> pair in boxnumber_in_whitebox_coord_dict) { Box tmp_box = Tapa.box[pair.Key.x][pair.Key.y]; tmp_box.hasNum = true; // 数字を持ってるフラグをオンにする tmp_box.boxNum = boxnumber_in_whitebox_coord_dict[pair.Key]; // 選択した座標に数字を格納 Tapa.numbox_coord_list.Add(new Coordinates(pair.Key)); // 数字マスリストに追加 Tapa.not_deployedbox_coord_list.Remove(pair.Key); // 未定マスリストから除外 PatternAroundNumBox.preparePatternArroundNumBox(); // 数字に対応したidを格納 } Box.during_make_inputbord = false; generateTapaProblemInDeleteNumBox(); break; case 2: // 時間計測開始 System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); generateTapaProblemInAddNumBox(boxnumber_in_whitebox_coord_dict); //時間計測終了 sw.Stop(); Console.WriteLine("generateTapaProblemInAddNumBoxの総時間 >> " + sw.Elapsed + "(" + Problem.can_be_number_whitebox_list.Count + ")"); // 時間計測開始 System.Diagnostics.Stopwatch sw2 = System.Diagnostics.Stopwatch.StartNew(); generateTapaProblemInDeleteNumBox(); //時間計測終了 sw2.Stop(); Console.WriteLine("generateTapaProblemInDeleteNumBoxの総時間 >> " + sw2.Elapsed + "(" + Problem.can_be_number_whitebox_list.Count + ")"); break; } }
/********************************* * * 盤面sのうち、bの座標を未定マスにした盤面を作成する。 * * *******************************/ public static void makeEditBoard(StateSave s) { Tapa.resetBoard(); for (int i = 1; i <= Tapa.MAX_BOARD_ROW; i++) { for (int j = 1; j <= Tapa.MAX_BOARD_COL; j++) { Tapa.box[i][j].connecting_color = s.saved_box[i][j].Color; } } }
/********************************* * * ぱずぷれで作成したtxtファイルの読み込み(Dot画用) * # : 黒 * + : 白 * ・ : 未定 * 1,2 : [12] * * True : Tapaの解として正しい * false: Tapaの解として正しくない * * *******************************/ public bool readDotTapaTxt(string readfile_path) { List <string> line_list = new List <string>(); using (StreamReader sr = new StreamReader( readfile_path, Encoding.GetEncoding("Shift_JIS"))) { string line = ""; while ((line = sr.ReadLine()) != null) { line_list.Add(line); } } if (line_list[0] != "pzprv3" || line_list[1] != "tapa") { Problem.is_correct_txtformat = false; return(false); } Tapa.MAX_BOARD_ROW = Convert.ToInt32(line_list[2]); // 3行目に行数 Tapa.MAX_BOARD_COL = Convert.ToInt32(line_list[3]); // 4行目に列数 Tapa.BOX_SUM = Tapa.MAX_BOARD_ROW * Tapa.MAX_BOARD_COL; // 盤面生成 Tapa.resetBoard(); for (int i = 1; i <= Tapa.MAX_BOARD_ROW; i++) { string wk_str = line_list[i + 3]; for (int j = 1; j <= Tapa.MAX_BOARD_COL; j++) { int pt = wk_str.IndexOf(' '); if (wk_str.Substring(0, pt) == "#") { Tapa.box[i][j].connecting_color = Box.BLACK; } else { Tapa.box[i][j].connecting_color = Box.WHITE; } wk_str = wk_str.Substring(pt + 1); } } // 入力された盤面が正しいか if (Tapa.isCorrectAnswer()) { return(true); } Problem.is_correct_tapa_dot = false; return(false); }
/********************************* * * 一繋がりの未定マス群毎にバックトラックを行う * * *******************************/ public void manageBackTrack() { //StateSave state_base = new StateSave(); //StateSave.saveNowState(state_base); // 一繋がりの未定マス群のリストを作成 // Box.divideNotDeployedBoxToGroup(); do { if (doBackTrack(0)) { StateSave.loadSavedState(BackTrack.correct_save_point); Console.WriteLine("バックトラック成功 深さ:{0}", min_Depth); Tapa.printBoard(); Console.WriteLine(); } } while (Tapa.not_deployedbox_coord_list.Count > 0); }
/********************************* * * 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); }
/********************************* * * 未定マスを試し塗りしてバックトラックを行う * バックトラックの結果が一度でも正しければtrueを返す * 引数 * depth : バックトラックの深さ * * *******************************/ private bool doBackTrack(int depth) { StateSave save_point = new StateSave(); StateSave.saveNowState(save_point); bool ret_bool = false; // true:(途中)盤面が正しい // 深さをインクリメント depth++; // 黒マスと接している未定マスのリストを作成 List <Coordinates> adjacent_notdeployedbox_coord_list = new List <Coordinates>(); // 黒マスと接している未定マスがある時 foreach (Coordinates tmp_ndbox_coord in Tapa.not_deployedbox_coord_list) { if (Box.existBlackBoxAround(tmp_ndbox_coord)) { adjacent_notdeployedbox_coord_list.Add(tmp_ndbox_coord); } } // 未定マスはあるが、黒マスと接している未定マスがない時 if (adjacent_notdeployedbox_coord_list.Count == 0 && Tapa.not_deployedbox_coord_list.Count > 0) { foreach (Coordinates tmp_ndbox_coord in Tapa.not_deployedbox_coord_list) { adjacent_notdeployedbox_coord_list.Add(new Coordinates(tmp_ndbox_coord)); } } // 注目している未定マス領域に未定マスがただ1つ存在する時の処理 if (adjacent_notdeployedbox_coord_list.Count == 1) { for (int i = 0; i < 2; i++) { Coordinates tmp_ndbox_coord = adjacent_notdeployedbox_coord_list[0]; Tapa.box[tmp_ndbox_coord.x][tmp_ndbox_coord.y].Color = (i == 0) ? Box.BLACK : Box.WHITE; // 変化がなくなるまで処理を行う do { Tapa.was_change_board = false; PatternAroundNumBox.managePatternAroundNumBox(); Box.manageBlackBox(); } while (Tapa.was_change_board); // 処理中の未定マス群から色のついたマスを除外したリストを作成 List <Coordinates> arg_list = new List <Coordinates>(Tapa.not_deployedbox_coord_list); for (int j = arg_list.Count - 1; j >= 0; j--) { if (Tapa.box[arg_list[j].x][arg_list[j].y].Color != Box.NOCOLOR) { arg_list.RemoveAt(j); } } // 未定マスが存在すれば再起する if (arg_list.Count > 0) { ret_bool = ret_bool || doBackTrack(depth); } else // 未定マスが存在しない { if (Box.checkNotIsolationBlackBoxGroup() || Tapa.isCorrectAnswer()) // 盤面の一繋がりの黒マス群が孤立していないか { StateSave.saveNowState(BackTrack.correct_save_point); // 正しければ現在の盤面を保存 if (depth < min_depth) // 先読みした深さ(のうち小さい方)を記録 { min_depth = depth; tmp_ndbox_coord.printCoordinates(); Console.WriteLine(":min_depth >> " + min_depth); } ret_bool = true; } } // 元の状態に戻す StateSave.loadSavedState(save_point); // 黒マスで塗ったら正解の盤面が生成できなかった場合 if (!ret_bool) { // 未定マスの色を白にする Tapa.box[tmp_ndbox_coord.x][tmp_ndbox_coord.y].Color = Box.WHITE; StateSave.saveNowState(save_point); } } return(ret_bool); } // 注目している未定マス領域に未定マスが複数存在する時の処理 // 未定マスをたどる for (int i = 0; i < adjacent_notdeployedbox_coord_list.Count; i++) { Coordinates tmp_ndbox_coord = adjacent_notdeployedbox_coord_list[i]; // 未定マスの色を黒にする Tapa.box[tmp_ndbox_coord.x][tmp_ndbox_coord.y].Color = Box.BLACK; // 変化がなくなるまで処理を行う do { Tapa.was_change_board = false; PatternAroundNumBox.managePatternAroundNumBox(); Box.manageBlackBox(); } while (Tapa.was_change_board); // 処理中の未定マス群から色のついたマスを除外したリストを作成 List <Coordinates> arg_list = new List <Coordinates>(Tapa.not_deployedbox_coord_list); for (int j = arg_list.Count - 1; j >= 0; j--) { if (Tapa.box[arg_list[j].x][arg_list[j].y].Color != Box.NOCOLOR) { arg_list.RemoveAt(j); } } // 処理中の未定マス群に未定マスが残っていれば再起する if (arg_list.Count > 0) { ret_bool = ret_bool || doBackTrack(depth); } else // 処理中の未定マス群に未定マスが存在しない // 盤面に一繋がりの黒マス群が孤立していない or 盤面が正解 { if (Box.checkNotIsolationBlackBoxGroup() || Tapa.isCorrectAnswer()) { StateSave.saveNowState(BackTrack.correct_save_point); // 正しければ現在の盤面を保存 if (depth < min_depth) // 先読みした深さ(のうち小さい方)を記録 { min_depth = depth; tmp_ndbox_coord.printCoordinates(); Console.WriteLine(":min_depth >> " + min_depth); } ret_bool = true; } } // 元の状態に戻す StateSave.loadSavedState(save_point); // 黒マスで塗ったら正解の盤面が生成できなかった場合 if (!ret_bool) { // 未定マスの色を白にする Tapa.box[tmp_ndbox_coord.x][tmp_ndbox_coord.y].Color = Box.WHITE; StateSave.saveNowState(save_point); } } return(ret_bool); }
/********************************* * * 数字マスを削除して問題生成する。 * 引数: * boxnumber_in_whitebox_coord_dict : 数字マスの座標と数字の対応 * * *******************************/ private void generateTapaProblemInDeleteNumBox() { if (Tapa.DEBUG) { Console.WriteLine("ソート前"); Tapa.printCoordList(Problem.can_be_number_whitebox_list); } // 【削除する数字マスを選ぶ順番】 // ヒント数で降順にソート[固定] のみ //////// ヒント数が同数だったらidの数で昇順にソートしたデータを後ろから選ぶ Tapa.numbox_coord_list.Sort( delegate(Coordinates co1, Coordinates co2) { int hint1 = Tapa.box[co1.x][co1.y].min_hint; int hint2 = Tapa.box[co2.x][co2.y].min_hint; if (hint1 < hint2) { return(1); } else if (hint1 > hint2) { return(-1); } else { return(0); //int num1 = Tapa.box[co1.x][co1.y].id_list.Count; //int num2 = Tapa.box[co2.x][co2.y].id_list.Count; //if (num1 < num2) { return -1; } //else if (num1 > num2) { return 1; } //else return 0; } }); // 未削除の数字マスリストを現在残っている数字マスリストで更新 Problem.can_be_number_whitebox_list = new List <Coordinates>(Tapa.numbox_coord_list); if (Tapa.DEBUG) { Console.WriteLine("ソート後"); Tapa.printCoordList(Problem.can_be_number_whitebox_list); } // 削除対象のリストを後ろからチェック for (int i = Problem.can_be_number_whitebox_list.Count - 1; i >= 0; i--) { // 時間計測開始 System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); // 現在の状態を保存 StateSave save_point = new StateSave(); StateSave.saveNowState(save_point); // 削除判定の行われていない数字マスの内、 // [最少ヒント数で降順][パターン数で昇順]でソートしたリストの後ろから順に数字マスを選ぶ Coordinates deleting_numbox_coord = Problem.can_be_number_whitebox_list[i]; // 選択された数字マスを、未削除の数字マス座標リストから除外する。 Problem.can_be_number_whitebox_list.Remove(deleting_numbox_coord); Box deleting_box = Tapa.box[deleting_numbox_coord.x][deleting_numbox_coord.y]; // 浅いコピー // 選択した数字マスを未定マスにする deleting_box.revision_color = Box.NOCOLOR; // 選択した座標を未定マスにする deleting_box.hasNum = false; // 数字を持ってるフラグをオフにする Tapa.numbox_coord_list.Remove(deleting_numbox_coord); // 数字マスリストから除外 Tapa.not_deployedbox_coord_list.Add(new Coordinates(deleting_numbox_coord)); // 未定マスリストに追加 // 問題を解く Tapa.solveTapa(); // 解ならば復元後に、選択した数字マスをそのまま未定マスにする。 if (Tapa.isCorrectAnswer()) { StateSave.loadSavedState(save_point); // 選択した数字マスを未定マスにする Tapa.box[deleting_numbox_coord.x][deleting_numbox_coord.y].revision_color = Box.NOCOLOR; // 選択した座標を未定マスにする Tapa.box[deleting_numbox_coord.x][deleting_numbox_coord.y].hasNum = false; // 数字を持ってるフラグをオフにする Tapa.numbox_coord_list.Remove(deleting_numbox_coord); // 数字マスリストから除外 Tapa.not_deployedbox_coord_list.Add(new Coordinates(deleting_numbox_coord)); // 未定マスリストに追加 } else { // 解でないなら、盤面を復元するのみ。 StateSave.loadSavedState(save_point); } //時間計測終了 sw.Stop(); deleting_numbox_coord.printCoordinates(); Console.WriteLine("del >> " + sw.Elapsed + "(" + Problem.can_be_number_whitebox_list.Count + ")"); } }
/********************************* * * 数字マスを追加して問題生成する。 * 引数: * 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)); } } } }
public static void makeSampleData() { //for (Tapa.MAX_BOARD_ROW = MIN_GEN_ROW; Tapa.MAX_BOARD_ROW <= MAX_GEN_ROW; Tapa.MAX_BOARD_ROW++) { // for (Tapa.MAX_BOARD_COL = MIN_GEN_COL; Tapa.MAX_BOARD_COL <= MAX_GEN_COL; Tapa.MAX_BOARD_COL++) { Tapa.MAX_BOARD_ROW = Tapa.MAX_BOARD_COL = 8; for (int rate = 25; rate <= 90; rate += 5) { Problem.MAX_WHITEBOX_START_RATE = rate; Problem.MIN_WHITEBOX_START_RATE = rate; Tapa.BOX_SUM = Tapa.MAX_BOARD_COL * Tapa.MAX_BOARD_ROW; dir_name = "tapa_fast_normal_" + Tapa.MAX_BOARD_ROW + "" + Tapa.MAX_BOARD_COL + "_r" + rate; FolderManagement.makeFolder(base_directory, dir_name); // MAX_TXT個の問題に対する PreBook sum = new PreBook("average"); // 合計 PreBook min = new PreBook("max"); // 最大 PreBook max = new PreBook("min", true); // 最少 for (int txt_id = 0; txt_id < MAX_TXT; txt_id++) { Tapa.file_name = "tapa" + Tapa.MAX_BOARD_ROW + Tapa.MAX_BOARD_COL + String.Format("{0:00000}", txt_id) + ".txt"; Tapa.processnum_kuromasu = 0; Tapa.processnum_kakuteijogaiid = 0; Tapa.processnum_dangoid = 0; Tapa.processnum_korituid = 0; Tapa.processnum_betu0id = 0; Tapa.processnum_kakuteimasu = 0; Tapa.processnum_numbox = 0; Tapa.visittimes_kuromasu = 0; Tapa.visittimes_kakuteijogaiid = 0; Tapa.visittimes_dangoid = 0; Tapa.visittimes_korituid = 0; Tapa.visittimes_betu0id = 0; Tapa.visittimes_kakuteimasu = 0; Tapa.sum_times_kuromasu = 0; Tapa.sum_times_kakuteijogaiid = 0; Tapa.sum_times_dangoid = 0; Tapa.sum_times_korituid = 0; Tapa.sum_times_betu0id = 0; Tapa.sum_times_kakuteimasu = 0; //// 時間計測開始 System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew(); Problem.manageMakingProblem(); ////時間計測終了 sw.Stop(); Tapa.time_makeproblem = sw.ElapsedMilliseconds; Tapa.is_count = true; Tapa.solveTapa(); Tapa.is_count = false; calcSum(sum); calcMax(min); calcMin(max); // http://kageura.hatenadiary.jp/entry/2015/05/18/200000 // csvファイルに書き込むlist MyCSVManagement.svc_list.Add( new Book() { tapa_name = Tapa.file_name, c_blackbox = Tapa.isolation_blackboxes_group_list[0].Count.ToString(), c_whitebox = (Tapa.BOX_SUM - Tapa.isolation_blackboxes_group_list[0].Count).ToString(), c_numbox = Tapa.processnum_numbox.ToString(), kuromasu = Tapa.processnum_kuromasu.ToString(), kakuteiIdJogai = Tapa.processnum_kakuteijogaiid.ToString(), dangoIdJogai = Tapa.processnum_dangoid.ToString(), korituIdJogai = Tapa.processnum_korituid.ToString(), betuId0Jogai = Tapa.processnum_betu0id.ToString(), kakuteimasu = Tapa.processnum_kakuteimasu.ToString(), visittimes_kuromasu = Tapa.visittimes_kuromasu.ToString(), visittimes_kakuteijogaiid = Tapa.visittimes_kakuteijogaiid.ToString(), visittimes_dangoid = Tapa.visittimes_dangoid.ToString(), visittimes_korituid = Tapa.visittimes_korituid.ToString(), visittimes_betu0id = Tapa.visittimes_betu0id.ToString(), visittimes_kakuteimasu = Tapa.visittimes_kakuteimasu.ToString(), sum_times_kuromasu = Tapa.sum_times_kuromasu.ToString(), sum_times_kakuteijogaiid = Tapa.sum_times_kakuteijogaiid.ToString(), sum_times_dangoid = Tapa.sum_times_dangoid.ToString(), sum_times_korituid = Tapa.sum_times_korituid.ToString(), sum_times_betu0id = Tapa.sum_times_betu0id.ToString(), sum_times_kakuteimasu = Tapa.sum_times_kakuteimasu.ToString(), avetimes_kuromasu = (Tapa.visittimes_kuromasu == 0) ? 0 : Tapa.sum_times_kuromasu / (float)Tapa.visittimes_kuromasu, avetimes_kakuteijogaiid = (Tapa.visittimes_kakuteijogaiid == 0) ? 0 : Tapa.sum_times_kakuteijogaiid / (float)Tapa.visittimes_kakuteijogaiid, avetimes_dangoid = (Tapa.visittimes_dangoid == 0) ? 0 : Tapa.sum_times_dangoid / (float)Tapa.visittimes_dangoid, avetimes_korituid = (Tapa.visittimes_korituid == 0) ? 0 : Tapa.sum_times_korituid / (float)Tapa.visittimes_korituid, avetimes_betu0id = (Tapa.visittimes_betu0id == 0) ? 0 : Tapa.sum_times_betu0id / (float)Tapa.visittimes_betu0id, avetimes_kakuteimasu = (Tapa.visittimes_kakuteimasu == 0) ? 0 : Tapa.sum_times_kakuteimasu / (float)Tapa.visittimes_kakuteimasu, time_maketapa = Tapa.time_makeproblem.ToString() }); } addAveBook(sum); addBook(max); addBook(min); writeCSV(); MyCSVManagement.svc_list.Clear(); } //// // } //} }