Example #1
0
 public StateSave(StateSave origin_state)
 {
     // 引数の盤面の全てのマス
     this.saved_box = new Box[Tapa.MAX_BOARD_ROW + 2][];
     for (int i = 0; i < Tapa.MAX_BOARD_ROW + 2; i++) {
         this.saved_box[i] = new Box[Tapa.MAX_BOARD_COL + 2];
         for (int j = 0; j < Tapa.MAX_BOARD_COL + 2; j++) {
             this.saved_box[i][j] = new Box(origin_state.saved_box[i][j]);
         }
     }
     // 引数の数字マスの座標のリスト
     this.saved_numbox_coord_list = StateSave.getStateCoordList(origin_state.saved_numbox_coord_list);
     // 引数の未定マスの座標リスト
     this.saved_not_deployedbox_coord_list = StateSave.getStateCoordList(origin_state.saved_not_deployedbox_coord_list);
     // 引数の伸び代のある黒マスの座標リスト
     this.saved_edge_blackbox_coord_list = StateSave.getStateCoordList(origin_state.saved_edge_blackbox_coord_list);
     // 引数の一繋がりの黒マス群の座標リスト
     this.saved_isolation_blackboxes_group_list
         = StateSave.getStateMultiCoordList(origin_state.saved_isolation_blackboxes_group_list);
     // 引数の一繋がりの未定マス群の座標リスト
     //this.saved_isolation_notdeployedboxes_group_list
     //	= StateSave.getStateMultiCoordList(origin_state.saved_isolation_notdeployedboxes_group_list);
     // 引数の盤面が変更されたかの情報
     this.saved_was_changed_board = origin_state.saved_was_changed_board;
 }
Example #2
0
        /*********************************
         *
         * 未定マスを試し塗りしてバックトラックを行う
         * バックトラックの結果が一度でも正しければ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;
        }
Example #3
0
        /*********************************
        *
        * 切断点のみの団子マスに接している黒マス群のうち
        * 最も短い黒マス群とそれに接している切断点を削除する
        *
        * *******************************/
        private static void removeCutDumpling()
        {
            // 団子マス4つの保存用
            List <Coordinates> dump_coord;

            // 団子マスの座標を取得、団子マスがなければ終わり
            while ((dump_coord = Box.getDumpCoord()) != null)
            {
                // 切断点に接している切断点以外の黒マス保存用
                // Key	 : 切断点に接している黒マス
                // Value : 切断点
                Dictionary <Coordinates, Coordinates> adj_dict = new Dictionary <Coordinates, Coordinates>();
                foreach (Coordinates co in dump_coord)
                {
                    // 切断点が接している黒マス座標を取得
                    List <Coordinates> tmp_adj_coord = Box.getWhatColorBoxCoordListAround(co, Box.BLACK);
                    // 接している黒マスのうち切断点の情報を除外
                    foreach (Coordinates tmp_co in dump_coord)
                    {
                        tmp_adj_coord.Remove(tmp_co);
                    }
                    adj_dict[tmp_adj_coord[0]] = co;
                }
                // 盤面編集用
                StateSave edit = new StateSave();
                StateSave.saveNowState(edit);

                // 盤面editの団子マスdump_coordを未定マスにする
                foreach (Coordinates co in dump_coord)
                {
                    edit.saved_box[co.x][co.y].revision_color = Box.NOCOLOR;
                }
                // edit盤面を生成
                // (一繋がりの黒マス群が複数生成される)
                StateSave.makeEditBoard(edit);

                // 黒マス群リストのうち、最少の黒マス群の参照を取得
                List <Coordinates> min_bblist = Box.getMinIsoBlackBoxListRef();

                // 切断点の黒マスの団子を黒く塗る
                foreach (Coordinates co in dump_coord)
                {
                    edit.saved_box[co.x][co.y].revision_color = Box.BLACK;
                }

                // min_bblistとそれに接している切断点を未定マスにする
                foreach (Coordinates co in min_bblist)
                {
                    edit.saved_box[co.x][co.y].revision_color = Box.NOCOLOR;
                    if (!adj_dict.ContainsKey(co))
                    {
                        continue;
                    }
                    edit.saved_box[adj_dict[co].x][adj_dict[co].y].revision_color = Box.NOCOLOR;
                }

                // edit盤面を生成
                // (団子マスを1つ除外できた盤面)
                StateSave.makeEditBoard(edit);
            }
        }
Example #4
0
        /*********************************
         *
         * 数字マスを削除して問題生成する。
         * 引数:
         * 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 + ")");

            }
        }
Example #5
0
        /*********************************
         *
         * 盤面の間違っている箇所を未定マスにする.
         *
         * 引数
         * 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; }
                }
            }
        }
Example #6
0
        /*********************************
         *
         * 盤面の初期状態から始めて問題を解けるか判断する.
         *
         * 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;
        }
Example #7
0
 /*********************************
  *
  * 盤面の埋め方が正しいか判断する
  *
  * true	:	正しい
  *
  * 引数
  * partway	:	途中盤面
  *
  * *******************************/
 private static bool isCorrectMiddleBoard(StateSave partway)
 {
     Tapa.solveTapa();
     if (Tapa.isCorrectAnswer()) {
         StateSave.loadSavedState(partway);
         return true;
     }
     StateSave.loadSavedState(partway);
     return false;
 }
Example #8
0
        /*********************************
         *
         * 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;
        }
Example #9
0
        /*********************************
        *
        * 未定マスを試し塗りしてバックトラックを行う
        * バックトラックの結果が一度でも正しければ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);
        }
Example #10
0
        /*********************************
        *
        * 数字マスを削除して問題生成する。
        * 引数:
        * 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 + ")");
            }
        }
Example #11
0
        /*********************************
         *
         * 1. 呼ばれた時の状態を保存する。
         * 2. co座標のid_listからidを取り出し、配置する。
         * 3. 黒マスの孤立を調べ、孤立していればidを除外する。
         * 4. 状態を元に戻す。
         * 5. 2-4をid_list内のid全てに対して行う。
         *
         * 引数
         * co		: 数字マスの座標
         * id_list	: idのリスト
         *
         * *******************************/
        private static void excludeIdToMakeIsolationBlackBoxGroup(Coordinates co, List<byte> id_list)
        {
            StateSave save_point = new StateSave();
            // 現在の状態を保存
            StateSave.saveNowState(save_point);

            // 孤立するidのid_listでの要素番号を保存するリスト
            List<int> iso_id_ite_list = new List<int>();
            for (int i = id_list.Count - 1; i >= 0; i--) {
                PatternAroundNumBox.setPatternAroundNumBox(co, id_list[i]);

                // 数字マスの周囲5*5マス以内にある黒マス群のリストを取得
                List<int> bbgroup_index_list = Box.getIndexBlackBoxGroupListAround55(co);
                List<List<Coordinates>> multi_list = new List<List<Coordinates>>();
                foreach (int index in bbgroup_index_list) {
                    multi_list.Add(Tapa.isolation_blackboxes_group_list[index]);
                }

                if (!Box.checkNotIsolationBlackBoxGroup(multi_list)		// 盤面に孤立した黒マス群がないか調べる
                    && Tapa.not_deployedbox_coord_list.Count > 0) {
                    iso_id_ite_list.Add(i);
                }
                StateSave.loadSavedState(save_point);
            }

            // 孤立したidをid_listから削除
            foreach (int tmp_ite in iso_id_ite_list) {
                // id_list.RemoveAt(tmp_ite);
                Tapa.box[co.x][co.y].id_list.RemoveAt(tmp_ite);
            }
        }
Example #12
0
        /*********************************
         *
         * 1. 呼ばれた時の状態を保存する。
         * 2. co座標のid_listからidを取り出し、配置する。
         * 3. 2.の状態で他の数字マスのidのチェック→除外を行う。
         * 4. どれか1つでも数字マスのid_listの大きさが0になった場合、
         *	 そのidのid_listでの添字を記録する。
         * 5. id_listの次のidに対して、2-5を繰り返す。
         * 6. id_listのid全ての調査が終わったら、4.で記録したidをid_listから除外する。
         *
         * 引数
         * co		: 数字マスの座標
         * id_list	: idのリスト
         *
         * *******************************/
        private static void excludeIdToKillOtherNameBoxAllId(Coordinates co, List<byte> id_list)
        {
            StateSave save_point = new StateSave();
            // 現在の状態を保存
            StateSave.saveNowState(save_point);

            // 除外するidのid_listでのインデックスを保存するリスト
            List<int> kill_id_ite_list = new List<int>();
            for (int i = id_list.Count - 1; i >= 0; i--) {
                // idの試し塗り
                PatternAroundNumBox.setPatternAroundNumBox(co, id_list[i]);
                // 数字マスのリストから今回試し塗りしたidの数字マスを除外
                Tapa.numbox_coord_list.Remove(co);
                Tapa.box[co.x][co.y].hasNum = false;

                // co周り5*5マスにある黒マスが属する黒マス群のインデックスを取得
                List<int> bbgroup_index_list = Box.getIndexBlackBoxGroupListAround55(co);

                List<Coordinates> numbox_around_bbgroup_coord_list = Box.getCoordListAroundBlackBoxGroup(bbgroup_index_list);

                for (int ite_coord = numbox_around_bbgroup_coord_list.Count - 1; ite_coord >= 0; ite_coord--) { // 黒マス群付近の数字マスリスト
                    Coordinates tmp_co = new Coordinates(numbox_around_bbgroup_coord_list[ite_coord]);

                    for (int ite_id = Tapa.box[tmp_co.x][tmp_co.y].id_list.Count - 1; ite_id >= 0; ite_id--) {	// id_list
                        byte tmp_id = Tapa.box[tmp_co.x][tmp_co.y].id_list[ite_id];
                        if (!PatternAroundNumBox.checkPatternAroundNumBox(tmp_co, tmp_id)) {	// idのパターンが配置できない
                            Tapa.box[tmp_co.x][tmp_co.y].id_list.RemoveAt(ite_id);
                        }
                    }
                    // idの通り配置したら黒マスの団子ができてしまう
                    PatternAroundNumBox.excludeDumplingId(tmp_co, Tapa.box[tmp_co.x][tmp_co.y].id_list);

                    // id_listのうち、孤立する黒マス群を作るidを除外(id_listごとに処理したほうが効率的)
                    PatternAroundNumBox.excludeIdToMakeIsolationBlackBoxGroup(tmp_co, Tapa.box[tmp_co.x][tmp_co.y].id_list);

                    // id_listの大きさが0なら今回試し塗りしたidの添字を、除外するid_listに追加し、次のidを見に行く。
                    if (Tapa.box[tmp_co.x][tmp_co.y].id_list.Count == 0) {
                        kill_id_ite_list.Add(i);
                        break;
                    }
                }
                // 保存した状態をロード
                StateSave.loadSavedState(save_point);
            }
            // 除外対象のidをid_listから除外
            foreach (int tmp_ite in kill_id_ite_list) {
                Tapa.box[co.x][co.y].id_list.RemoveAt(tmp_ite);
            }
        }
Example #13
0
 /*********************************
  *
  *   リストや盤面の状態を保存
  *
  * *******************************/
 public static void saveNowState(StateSave save_point)
 {
     ////// 呼びだされた時点での盤面の全てのマス
     for (int i = 0; i < Tapa.MAX_BOARD_ROW + 2; i++) {
         save_point.saved_box[i] = new Box[Tapa.MAX_BOARD_COL + 2];
         for (int j = 0; j < Tapa.MAX_BOARD_COL + 2; j++) {
             save_point.saved_box[i][j] = new Box(Tapa.box[i][j]);
         }
     }
     // 呼びだされた時点での数字マスの座標のリスト
     save_point.saved_numbox_coord_list = StateSave.getStateCoordList(Tapa.numbox_coord_list);
     // 呼びだされた時点での未定マスの座標リスト
     save_point.saved_not_deployedbox_coord_list = StateSave.getStateCoordList(Tapa.not_deployedbox_coord_list);
     // 呼びだされた時点での伸び代のある黒マスの座標リスト
     save_point.saved_edge_blackbox_coord_list = StateSave.getStateCoordList(Tapa.edge_blackbox_coord_list);
     // 呼びだされた時点での一繋がりの黒マス群の座標リスト
     save_point.saved_isolation_blackboxes_group_list
         = StateSave.getStateMultiCoordList(Tapa.isolation_blackboxes_group_list);
     // 呼びだされた時点での一繋がりの黒マス群の座標リスト
     //save_point.saved_isolation_notdeployedboxes_group_list
     //	= StateSave.getStateMultiCoordList(Tapa.isolation_notdeployedboxes_group_list);
     // 呼びだされた時点での盤面が変更されたかの情報
     save_point.saved_was_changed_board = Tapa.was_change_board;
 }
Example #14
0
 /*********************************
  *
  * 盤面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;
         }
     }
 }
Example #15
0
 /*********************************
  *
  *   リストや盤面の状態を引数の状態に復元
  *
  * *******************************/
 public static void loadSavedState(StateSave save_point)
 {
     for (int i = 0; i < Tapa.MAX_BOARD_ROW + 2; i++) {
         for (int j = 0; j < Tapa.MAX_BOARD_COL + 2; j++) {
             Tapa.box[i][j] = new Box(save_point.saved_box[i][j]);
         }
     }
     loadSavedStateEdgeBlackBoxCoordList(save_point.saved_edge_blackbox_coord_list);
     loadSavedStateIsolationBlackBoxesGroupList(save_point.saved_isolation_blackboxes_group_list);
     loadSavedStateNotDeployedBoxCoordList(save_point.saved_not_deployedbox_coord_list);
     loadSavedStateNumBoxCoordList(save_point.saved_numbox_coord_list);
     Tapa.was_change_board = save_point.saved_was_changed_board;
 }
Example #16
0
        /*********************************
         *
         * 切断点のみの団子マスに接している黒マス群のうち
         * 最も短い黒マス群とそれに接している切断点を削除する
         *
         * *******************************/
        private static void removeCutDumpling()
        {
            // 団子マス4つの保存用
            List<Coordinates> dump_coord;

            // 団子マスの座標を取得、団子マスがなければ終わり
            while ((dump_coord = Box.getDumpCoord()) != null) {

                // 切断点に接している切断点以外の黒マス保存用
                // Key	 : 切断点に接している黒マス
                // Value : 切断点
                Dictionary<Coordinates, Coordinates> adj_dict = new Dictionary<Coordinates, Coordinates>();
                foreach (Coordinates co in dump_coord) {
                    // 切断点が接している黒マス座標を取得
                    List<Coordinates> tmp_adj_coord = Box.getWhatColorBoxCoordListAround(co, Box.BLACK);
                    // 接している黒マスのうち切断点の情報を除外
                    foreach (Coordinates tmp_co in dump_coord) {
                        tmp_adj_coord.Remove(tmp_co);
                    }
                    adj_dict[tmp_adj_coord[0]] = co;
                }
                // 盤面編集用
                StateSave edit = new StateSave();
                StateSave.saveNowState(edit);

                // 盤面editの団子マスdump_coordを未定マスにする
                foreach (Coordinates co in dump_coord) {
                    edit.saved_box[co.x][co.y].revision_color = Box.NOCOLOR;
                }
                // edit盤面を生成
                // (一繋がりの黒マス群が複数生成される)
                StateSave.makeEditBoard(edit);

                // 黒マス群リストのうち、最少の黒マス群の参照を取得
                List<Coordinates> min_bblist = Box.getMinIsoBlackBoxListRef();

                // 切断点の黒マスの団子を黒く塗る
                foreach (Coordinates co in dump_coord) {
                    edit.saved_box[co.x][co.y].revision_color = Box.BLACK;
                }

                // min_bblistとそれに接している切断点を未定マスにする
                foreach (Coordinates co in min_bblist) {
                    edit.saved_box[co.x][co.y].revision_color = Box.NOCOLOR;
                    if (!adj_dict.ContainsKey(co)) { continue; }
                    edit.saved_box[adj_dict[co].x][adj_dict[co].y].revision_color = Box.NOCOLOR;
                }

                // edit盤面を生成
                // (団子マスを1つ除外できた盤面)
                StateSave.makeEditBoard(edit);
            }
        }