Ejemplo n.º 1
0
    //打ち歩詰めの判定関数
    public bool IsUtifuDume(Te te)
    {
        //歩(1,17)で打たれた時(段が0)に相手に合法手がなければ打ち歩詰め
        if (te.koma == 1 || te.koma == 17)
        {
            if (te.from == 0)
            {
                this.Move(te.DeepCopy());
                this.turn += 1;

                if (this.GenerateLegalMoves().Count == 0)
                {
                    return(true);
                }
                this.Back(te.DeepCopy());
                this.turn -= 1;
            }
        }
        return(false);
    }
Ejemplo n.º 2
0
    /*
     * //手番を進める関数
     * void ChangeTurn(Te te){
     *
     *      if (kk.turn % 2 == 1) {
     *              turn.GetComponent<Text> ().text = "後手";
     *      } else {
     *              turn.GetComponent<Text> ().text = "先手";
     *      }
     *
     *
     *      kk.turn = kk.turn + 1;
     *      kihu.Add (te.DeepCopy());
     *
     *      if (te.capture != 0 && te.capture != 1 && te.capture != 17) {
     *              phase = true;
     *      }
     *
     *      if (kk.turn > 10 && phase) {
     *              sikou.DEPTH_MAX = 3;
     *      }
     *
     *
     *
     *      for (int j = 0; j < historykyokumenn.Count; j++) {
     *              if (kk.equals (historykyokumenn [j])) {
     *                      kk.sameKyokumenn += 1;
     *              }
     *
     *      }
     *
     *      if (kk.sameKyokumenn > 3) {
     *              vsCom = false;
     *              vsComGote = false;
     *              winner.GetComponent<Text>().text = "千日手により引き分けです";
     *              resultCanvas.GetComponent<Canvas>().enabled = true;
     *
     *              for (int i = 1;i <= 81 ; i++){
     *
     *                      Masu [i - 1].GetComponent<Button> ().interactable = false;
     *                      Masu [i - 1].GetComponent<Image> ().color = new Color (255f / 255f, 255f / 255f, 255f / 255f, 255f / 255f);
     *
     *              }
     *      }
     *      kk.sameKyokumenn = 0;
     *
     *
     *      historykyokumenn.Add (kk.DeepCopyKyokumenn());
     *
     *
     *      if (kihu.Count > 1) {
     *               Masu [kihu [kk.turn - 3].to - 1].GetComponent<Image> ().color = new Color (255f / 255f, 255f / 255f, 255f / 255f, 255f / 255f);
     *      }
     *      Masu [te.to - 1].GetComponent<Image> ().color = new Color (255f / 255f, 180f / 255f, 0f / 255f, 255f / 255f);
     *
     *
     *      //合法手が無くなったら
     *      if (kk.GenerateLegalMoves ().Count == 0) {
     *
     *              vsCom = false;
     *              vsComGote = false;
     *              print (kk.turn);
     *
     *              if (kk.turn % 2 == 1) {
     *                      winner.GetComponent<Text>().text = "後手の勝利です";
     *              } else {
     *                      winner.GetComponent<Text>().text = "先手の勝利です";
     *              }
     *              //勝敗がついたらボタンをオフに
     *              for (int i = 1;i <= 81 ; i++){
     *
     *                      Masu [i - 1].GetComponent<Button> ().interactable = false;
     *                      Masu [i - 1].GetComponent<Image> ().color = new Color (255f / 255f, 255f / 255f, 255f / 255f, 255f / 255f);
     *
     *              }
     *
     *              resultCanvas.GetComponent<Canvas>().enabled = true;
     *
     *      }
     * }
     *
     *
     *
     */


    //手番を進める関数
    IEnumerator Changeturn(Te te)
    {
        if (kk.turn % 2 == 1)
        {
            turn.GetComponent <Text> ().text = "後手";
        }
        else
        {
            turn.GetComponent <Text> ().text = "先手";
        }

        yield return(new WaitForEndOfFrame());

        kk.turn = kk.turn + 1;
        kihu.Add(te.DeepCopy());

        for (int j = 0; j < historykyokumenn.Count; j++)
        {
            if (kk.equals(historykyokumenn [j]))
            {
                kk.sameKyokumenn += 1;
            }
        }

        if (kk.sameKyokumenn > 3)
        {
            vsCom     = false;
            vsComGote = false;
            winner.GetComponent <Text>().text            = "千日手により引き分けです";
            resultCanvas.GetComponent <Canvas>().enabled = true;

            for (int i = 1; i <= 81; i++)
            {
                Masu [i - 1].GetComponent <Button> ().interactable = false;
                Masu [i - 1].GetComponent <Image> ().color         = new Color(255f / 255f, 255f / 255f, 255f / 255f, 255f / 255f);
            }
        }
        kk.sameKyokumenn = 0;


        historykyokumenn.Add(kk.DeepCopyKyokumenn());


        if (kihu.Count > 1)
        {
            Masu [kihu [kk.turn - 3].to - 1].GetComponent <Image> ().color = new Color(255f / 255f, 255f / 255f, 255f / 255f, 255f / 255f);
        }
        Masu [te.to - 1].GetComponent <Image> ().color = new Color(255f / 255f, 180f / 255f, 0f / 255f, 255f / 255f);


        //合法手が無くなったら
        if (kk.GenerateLegalMoves().Count == 0)
        {
            vsCom     = false;
            vsComGote = false;
            print(kk.turn);

            if (kk.turn % 2 == 1)
            {
                winner.GetComponent <Text>().text = "後手の勝利です";
            }
            else
            {
                winner.GetComponent <Text>().text = "先手の勝利です";
            }
            //勝敗がついたらボタンをオフに
            for (int i = 1; i <= 81; i++)
            {
                Masu [i - 1].GetComponent <Button> ().interactable = false;
                Masu [i - 1].GetComponent <Image> ().color         = new Color(255f / 255f, 255f / 255f, 255f / 255f, 255f / 255f);
            }

            resultCanvas.GetComponent <Canvas>().enabled = true;
        }
    }
Ejemplo n.º 3
0
    public List <Te> GenerateLegalMoves()
    {
        //合法手を格納する変数
        List <Te> teList  = new List <Te>();
        List <Te> removed = new List <Te>();
        Te        te      = new Te();

        for (int masu = 1; masu <= 81; masu++)
        {
            int koma = this.banKoma [masu];
            //探索する駒が手番の駒かどうか
            if ((this.turn % 2 == 1 && koma >= 1 && koma <= 16) || (this.turn % 2 == 0 && koma >= 17))
            {
                //各方向に移動する手を生成
                for (int direct = 0; direct < 12; direct++)
                {
                    if (KomaMoves.canMove [direct, koma])
                    {
                        te.koma = koma;
                        te.to   = masu + KomaMoves.diff [direct];
                        te.from = masu;


                        if ((masu % 9 == 0 && te.to % 9 == 1) || (masu % 9 == 1 && te.to % 9 == 0))
                        {
                            continue;
                        }

                        //移動先は盤内か
                        if (1 <= te.to && te.to <= 81)
                        {
                            //移動先に自分の駒はないか
                            int toKoma = this.banKoma[te.to];
                            te.capture = this.banKoma [te.to];
                            if ((this.turn % 2 == 1 && (toKoma == 0 || toKoma >= 17)) || (this.turn % 2 == 0 && toKoma <= 16))
                            {
                                //桂馬は敵二段目まで、歩は一段目までで成らずはできない
                                if ((te.koma != 3 || te.to > 18) && (te.koma != 19 || te.to < 64) && (te.koma != 1 || te.to >= 10) && (te.koma != 17 || te.to <= 72))
                                {
                                    te.promote = false;
                                    teList.Add(te.DeepCopy());
                                }
                                //移動先が敵陣
                                if ((te.to <= 27 && this.turn % 2 == 1) || (te.to >= 55 && this.turn % 2 == 0))
                                {
                                    //成れる駒
                                    if (KomaMoves.canPromote[koma])
                                    {
                                        te.promote = true;
                                        teList.Add(te.DeepCopy());
                                    }
                                }

                                //移動元が敵陣
                                if ((te.from <= 27 && this.turn % 2 == 1) || (te.from >= 55 && this.turn % 2 == 0))
                                {
                                    //成れる駒
                                    if (KomaMoves.canPromote[koma])
                                    {
                                        te.promote = true;
                                        teList.Add(te.DeepCopy());
                                    }
                                }
                            }
                        }
                    }
                }

                //各方向に「飛ぶ」手を生成
                for (int direct = 0; direct < 8; direct++)
                {
                    if (KomaMoves.canJump [direct, koma])
                    {
                        te.from = masu;
                        te.koma = koma;


                        for (int i = 1; i < 9; i++)
                        {
                            //移動先を生成

                            te.to = masu + KomaMoves.diff[direct] * i;

                            if (((te.to % 9 == 0) && (((te.to - KomaMoves.diff[direct]) % 9) == 1)) || ((te.to % 9 == 1) && ((te.to - KomaMoves.diff[direct]) % 9 == 0)))
                            {
                                break;
                            }

                            //移動先は盤内か
                            if (1 <= te.to && te.to <= 81)
                            {
                                //移動先に自分の駒はないか
                                int toKoma = this.banKoma[te.to];
                                te.capture = this.banKoma [te.to];
                                if ((this.turn % 2 == 1 && (toKoma == 0 || toKoma >= 17)) || (this.turn % 2 == 0 && toKoma <= 16))
                                {
                                    //香車は敵の一段目まで行って成らずは不可
                                    if ((te.koma != 2 || te.to > 9) && (te.koma != 18 || te.to < 73))
                                    {
                                        te.promote = false;
                                        teList.Add(te.DeepCopy());
                                    }
                                    //移動先が敵陣
                                    if ((te.to <= 27 && this.turn % 2 == 1) || (te.to >= 55 && this.turn % 2 == 0))
                                    {
                                        //成れる駒
                                        if (KomaMoves.canPromote[koma])
                                        {
                                            te.promote = true;
                                            teList.Add(te.DeepCopy());
                                        }
                                    }
                                    //移動元が敵陣
                                    if ((te.from <= 27 && this.turn % 2 == 1) || (te.from >= 55 && this.turn % 2 == 0))
                                    {
                                        //成れる駒
                                        if (KomaMoves.canPromote[koma])
                                        {
                                            te.promote = true;
                                            teList.Add(te.DeepCopy());
                                        }
                                    }
                                }
                                //空きマスでなければここでループ終わり
                                if (toKoma != 0)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }

        //持ち駒からだす手を追加(銀、金、角、飛車)
        if (this.turn % 2 == 1)                                        //先手の場合
        //銀~飛車までループ
        {
            for (int i = 4; i <= 7; i++)
            {
                //探索中の駒を持っているか
                if (this.hand [1] [i] >= 1)
                {
                    te.koma = i;

                    for (int masu = 1; masu <= 81; masu++)
                    {
                        //駒は(0,0)点からとおく
                        te.to      = masu;
                        te.from    = 0;
                        te.promote = false;
                        te.capture = this.banKoma [te.to];

                        if (this.banKoma [masu] == 0)
                        {
                            teList.Add(te.DeepCopy());
                        }
                    }
                }
            }
        }
        else                                                            //後手の場合
        //銀~飛車までループ
        {
            for (int i = 20; i <= 23; i++)
            {
                //探索中の駒を持っているか
                if (this.hand [0] [i] >= 1)
                {
                    te.koma = i;

                    for (int masu = 1; masu <= 81; masu++)
                    {
                        //駒は(0,0)点からとおく
                        te.to      = masu;
                        te.from    = 0;
                        te.promote = false;
                        te.capture = this.banKoma [te.to];

                        if (this.banKoma [masu] == 0)
                        {
                            teList.Add(te.DeepCopy());
                        }
                    }
                }
            }
        }

        if (this.turn % 2 == 1)                                        //先手の場合

        //先手の持ち駒に歩がある
        {
            if (this.hand [1] [1] >= 1)
            {
                te.koma = 1;

                //二歩チェック
                for (int suji = 1; suji <= 9; suji++)
                {
                    bool isNifu = false;                                                //二歩チェック用変数
                    for (int dan = 1; dan <= 9; dan++)
                    {
                        if (this.banKoma [(dan - 1) * 9 + suji] == 1)
                        {
                            isNifu = true;
                        }
                    }
                    if (isNifu)
                    {
                        continue;
                    }
                    //これ以上進めない1段目を除き、駒がなければ歩を出す手を追加する
                    for (int dan = 2; dan <= 9; dan++)
                    {
                        //駒は(0,0)点からとおく
                        te.to      = (dan - 1) * 9 + suji;
                        te.from    = 0;
                        te.promote = false;
                        te.capture = this.banKoma [te.to];

                        if (this.banKoma [(dan - 1) * 9 + suji] == 0)
                        {
                            teList.Add(te.DeepCopy());
                        }
                    }
                }
            }


            //先手の持ち駒に香車がある
            if (this.hand [1] [2] >= 1)
            {
                te.koma = 2;


                for (int masu = 10; masu <= 81; masu++)
                {
                    //これ以上進めない1段目を除き、駒がなければ香車を出す手を追加する


                    //駒は(0,0)点からとおく
                    te.to      = masu;
                    te.from    = 0;
                    te.promote = false;
                    te.capture = this.banKoma [te.to];

                    if (this.banKoma [masu] == 0)
                    {
                        teList.Add(te.DeepCopy());
                    }
                }
            }



            //先手の持ち駒に桂馬がある
            if (this.hand [1] [3] >= 1)
            {
                te.koma = 3;


                for (int masu = 19; masu <= 81; masu++)
                {
                    //これ以上進めない1,2段目を除き、駒がなければ桂馬を出す手を追加する


                    //駒は(0,0)点からとおく
                    te.to      = masu;
                    te.from    = 0;
                    te.promote = false;
                    te.capture = this.banKoma [te.to];

                    if (this.banKoma [masu] == 0)
                    {
                        teList.Add(te.DeepCopy());
                    }
                }
            }
        }
        else                                     //後手の場合

        //持ち駒に歩がある
        {
            if (this.hand [0] [17] >= 1)
            {
                te.koma = 17;
                //二歩チェック
                for (int suji = 1; suji <= 9; suji++)
                {
                    bool isNifu = false;                                                //二歩チェック用変数
                    for (int dan = 1; dan <= 9; dan++)
                    {
                        if (this.banKoma [(dan - 1) * 9 + suji] == 17)
                        {
                            isNifu = true;
                        }
                    }
                    if (isNifu)
                    {
                        continue;
                    }
                    //これ以上進めない1段目を除き、駒がなければ歩を出す手を追加する
                    for (int dan = 1; dan <= 8; dan++)
                    {
                        //駒は(0,0)点からとおく
                        te.to      = (dan - 1) * 9 + suji;
                        te.from    = 0;
                        te.promote = false;
                        te.capture = this.banKoma [te.to];

                        if (this.banKoma [(dan - 1) * 9 + suji] == 0)
                        {
                            teList.Add(te.DeepCopy());
                        }
                    }
                }
            }


            //持ち駒に香車がある
            if (this.hand [0] [18] >= 1)
            {
                te.koma = 18;

                for (int masu = 1; masu <= 72; masu++)
                {
                    //これ以上進めない1段目を除き、駒がなければ香車を出す手を追加する


                    //駒は(0,0)点からとおく
                    te.to      = masu;
                    te.from    = 0;
                    te.promote = false;
                    te.capture = this.banKoma [te.to];

                    if (this.banKoma [masu] == 0)
                    {
                        teList.Add(te.DeepCopy());
                    }
                }
            }

            //持ち駒に桂馬がある
            if (this.hand [0] [19] >= 1)
            {
                te.koma = 19;

                for (int masu = 1; masu <= 63; masu++)
                {
                    //これ以上進めない1段目を除き、駒がなければ桂馬を出す手を追加する


                    //駒は(0,0)点からとおく
                    te.to      = masu;
                    te.from    = 0;
                    te.promote = false;
                    te.capture = this.banKoma [te.to];

                    if (this.banKoma [masu] == 0)
                    {
                        teList.Add(te.DeepCopy());
                    }
                }
            }
        }


        //王手を放置している手を抜く
        int gyoku = 0;


        for (int i = 0; i < teList.Count; i++)
        {
            bool isOuteHouchi = false;
            Te   teTest       = teList [i];
            this.Move(teTest);

            if (this.turn % 2 == 1)
            {
                gyoku = gyokuSente;
            }
            else
            {
                gyoku = gyokuGote;
            }

            // 玉の周辺(12方向)から相手の駒が利いていたら、その手は取り除く
            for (int direct = 0; direct < 12 && !isOuteHouchi; direct++)
            {
                //方向の反対側にある駒の取得

                int masuSerch = gyoku - KomaMoves.diff[direct];

                if (((masuSerch % 9 == 0) && (((masuSerch + KomaMoves.diff[direct]) % 9) == 1)) || ((masuSerch % 9 == 1) && ((masuSerch + KomaMoves.diff[direct]) % 9 == 0)))
                {
                    continue;
                }

                if (1 <= masuSerch && masuSerch <= 81)
                {
                    int koma = this.banKoma [masuSerch];
                    //その駒が敵の駒で手番の玉を取れるか
                    if (this.turn % 2 == 1 && 17 <= koma || this.turn % 2 == 0 && koma <= 16 && 1 <= koma)
                    {
                        //動けるなら、この手は王手を放置しているので追加しない
                        if (KomaMoves.canMove [direct, koma])
                        {
                            isOuteHouchi = true;
                            break;
                        }
                    }
                }
            }
            // 玉の周り(8方向)から相手の駒の飛び利きがあるなら、その手は取り除く
            for (int direct = 0; direct < 8 && !isOuteHouchi; direct++)
            {
                // 方向の反対方向にある駒を取得
                int masuSerch = gyoku - KomaMoves.diff[direct];



                // その方向にマスがある限り、駒を探す
                while (1 <= masuSerch && masuSerch <= 81)
                {
                    if (((masuSerch % 9 == 0) && (((masuSerch + KomaMoves.diff[direct]) % 9) == 1)) || (((masuSerch % 9 == 1) && ((masuSerch + KomaMoves.diff[direct]) % 9) == 0)))
                    {
                        break;
                    }

                    int koma = this.banKoma [masuSerch];
                    // 味方駒で利きが遮られているなら、チェック終わり
                    if (this.turn % 2 == 1 && koma <= 16 && 1 <= koma || this.turn % 2 == 0 && 17 <= koma)
                    {
                        break;
                    }
                    // 遮られていない相手の駒の利きがあるなら、王手がかかっている。
                    if (this.turn % 2 == 1 && 17 <= koma || this.turn % 2 == 0 && koma <= 16 && 1 <= koma)
                    {
                        //動けるなら、この手は王手を放置しているので追加しない
                        if (KomaMoves.canJump [direct, koma])
                        {
                            isOuteHouchi = true;
                            break;
                        }
                        else
                        {
                            // 敵駒で利きが遮られているから、チェック終わり
                            break;
                        }
                    }
                    //玉から一つ離してループ
                    masuSerch -= KomaMoves.diff[direct];
                }
            }

            this.Back(teTest);

            if (!isOuteHouchi)
            {
                removed.Add(teList [i]);
            }
        }

        return(removed);
    }
Ejemplo n.º 4
0
//	float countTime;

    /*
     * public void Update () {
     *      countTime += Time.deltaTime;
     *      Debug.Log ("(●・▽・●)");
     * }
     */

    private int NegaMax(ref Te t, Kyokumenn k, int alpha, int beta, int depth, int depthMax)
    {
        int value = new int();

        //深さが最大に達していたら評価値を返して終了
        if (depth >= depthMax)
        {
            leaf++;
            value = k.evaluate();

            //先手ならプラス、後手でマイナスの値を返す
            if (k.turn % 2 == 1)
            {
                return(value);
            }
            else
            {
                return(-value);
            }
        }

        node++;

        //現在の局面での合法手を生成
        var teList = new List <Te>();

        teList = k.GenerateLegalMoves();

        value = -100000000;

        for (int i = 0; i < teList.Count; i++)
        {
            Te te = teList [i];

            //その手で一手進めた局面を作る
            //		KyokumennArray nextKyokumenn = k.DeepCopyKyokumenn ();
            k.Move(te.DeepCopy());
            k.turn += 1;

            Te tempTe = new Te();

            int eval = -NegaMax(ref tempTe, k, -beta, -alpha, depth + 1, depthMax);
            k.Back(te.DeepCopy());
            k.turn -= 1;

            //大きかったら
            if (eval > value)
            {
                value = eval;

                //αの値も更新
                if (eval > alpha)
                {
                    alpha = eval;
                }
                //最善手を更新
                best [depth, depth] = te;
                t.koma    = te.koma;
                t.from    = te.from;
                t.to      = te.to;
                t.promote = te.promote;
                t.capture = k.banKoma [te.to];

                for (int j = depth + 1; j < depthMax; j++)
                {
                    best [depth, j] = best [depth + 1, j];
                }
                //βカットの条件を満たしていたらループ終了
                if (eval >= beta)
                {
                    break;
                }
            }
        }
        return(value);
    }