public Te getNextTe(Kyokumenn k, int tesu) { Te te; if ((te = joseki.fromjoseki(k, tesu)) != null) { return(te); } leaf = 0; node = 0; List <Te> teList = k.GenerateLegalMoves(); te = teList[Random.Range(0, teList.Count)]; if (k.turn % 2 == 1) { //評価値最大の手をえる this.NegaMax(ref te, k, -1000000, 1000000, 0, DEPTH_MAX); } else { //評価値最小の手をえる this.NegaMax(ref te, k, -100000, 1000000, 0, DEPTH_MAX); } return(te); }
//コンピューターに打たせるAlphaBeta public void AlphaBeta() { //Sikouクラスから次の手をもらう Te te = sikou.getNextTeKai(kk, kk.turn); //合法手出ない場合は合法手の中からランダムに手を作る if (!LegalMove(te)) { var teList = new List <Te>(); teList = kk.GenerateLegalMoves(); te = teList [Random.Range(0, teList.Count)]; } if (te.from == 0) { //使った持ち駒を減らす kk.hand [kk.turn % 2] [te.koma] -= 1; //持ち駒数の表示を正しくし、タップマーカーを消す if (kk.turn % 2 == 1) { hand [te.koma].GetComponent <Text> ().text = kk.hand [1] [te.koma].ToString(); motiGoma [te.koma].GetComponent <Image> ().color = new Color(255f / 255f, 255f / 255f, 255f / 255f, 255f / 255f); } else { hand [te.koma - 8].GetComponent <Text> ().text = kk.hand [0] [te.koma].ToString(); motiGoma [te.koma - 8].GetComponent <Image> ().color = new Color(255f / 255f, 255f / 255f, 255f / 255f, 255f / 255f); } //行き先に駒をおく Put(te.to, te.koma); //駒、持ち駒の選択フラグを消す isSelectKoma = 0; isSelectMotigoma = 0; } else { //移動先に相手の駒があったらとる int toKoma = kk.banKoma [te.to]; if (8 < toKoma && toKoma <= 16 || 24 < toKoma && toKoma <= 32) { toKoma -= 8; } //先手の駒なら後手に追加,後手の駒なら先手に追加 if (0 != toKoma && toKoma <= 16) { kk.hand [0] [toKoma + 16] += 1; hand [toKoma + 8].GetComponent <Text> ().text = kk.hand [0] [toKoma + 16].ToString(); } else if (toKoma != 0 && 17 <= toKoma) { kk.hand [1] [toKoma - 16] += 1; hand [toKoma - 16].GetComponent <Text> ().text = kk.hand [1] [toKoma - 16].ToString(); } //駒があった場所を空にする Put(te.from, 0); //成る場合は成った駒を、ならない場合はそのままの駒を移動先におく if (te.promote) { Put(te.to, te.koma + 8); } else { Put(te.to, te.koma); } } //手番を変える //this.ChangeTurn (te); StartCoroutine(Changeturn(te)); }
// 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); }