Newer
Older
Algolike / src / main / java / controls / BotIntelligence.java
package controls;

import interfaces.IAttack;
import interfaces.IBotBehavior;

import java.util.*;
import java.util.stream.Collectors;

import static views.Constants.DECK_COUNT;

public class BotIntelligence implements IBotBehavior {

    public BotIntelligence(){

    }
    /**
    未確定の数字を列挙する
     */
    List<Integer> calculateCandidate(IAttack iAttack){
        //候補の初期化
        var candidates = new ArrayList<Integer>();
        for(int i=0;i<DECK_COUNT;i++)candidates.add(i);

        candidates.removeAll(iAttack.getOpponentHands().stream().map(x -> x.getKey()).collect(Collectors.toList()));
        candidates.removeAll(iAttack.getMyHands().stream().filter(x -> x.getValue()).map(x -> x.getKey()).collect(Collectors.toList()));

        return candidates;
    }

    /**
     * 相手の手札に対して、候補となる数字を割り当てる
     * @param iAttack
     * @return 候補のリスト
     */
    List<int[]> assignCandidateNumberEachHand(IAttack iAttack){
        var myHands=iAttack.getMyHands();
        var result=new ArrayList<int[]>();

        for(var card:myHands){//ユーザーの手札を左から見ていく
            var index=myHands.indexOf(card);//左からindex番目に
            var candidateList = calculateCandidate(iAttack);//確認するカード


            if(card.getValue()) {
                candidateList.clear();
            }else{                  //裏の場合

                //そのカードから右隣のカードを確認していく
                for(int i=0;i<myHands.size()-index-1;i++){
                    //今確認していっているカード
                    var currentCard = myHands.get(i+index+1);
                    if(currentCard.getValue()){//確認しているカードが表なら、(YES)
                        candidateList.removeIf(x -> x > currentCard.getKey());//その確認したカードの数字より大きい数字を除外する。
                        for(int j=1;j<i;j++){//そして、その確認したカードよりjだけ小さいそのカードからj番目の数字を除外する。
                            candidateList.remove(candidateList.size()-1);
                        }
                        break;
                    }
                }

                //そのカードから左隣のカードを確認していく
                for(int i=1;i<=index;i++){
                    //今確認していっているカード
                    var currentCard = myHands.get(index-i);
                    if(currentCard.getValue()){//表があれば、それより小さい数字を候補から削除する
                        candidateList.removeIf(x-> x<currentCard.getKey());
                    }
                }


            }
            var s=(card.getValue()?"+":"-")+card.getKey()+":[";
            for (var i:candidateList)s+=i+" ";
            s+="]\n";
            System.out.println(s);
            result.add(candidateList.stream().mapToInt(x -> x).toArray());
        }
        return result;
    }

    //公開されていないカードのインデックスを選ぶ(カードにかかれている番号ではない)
    @Override
    public int selectAttacker(IAttack iAttack) {
        var botHands = iAttack.getOpponentHands();

        for(var i:botHands){//小さいものから選択
            if(!i.getValue())return botHands.indexOf(i);
        }
        return 0;
    }

    @Override
    public int selectTarget(IAttack iAttack) {
        var candidate= assignCandidateNumberEachHand(iAttack);
        int result=0;
        int min=DECK_COUNT;
        for(var i:candidate){
            if(i.length<min&&i.length!=0){
                result=candidate.indexOf(i);
                min=i.length;
            }
        }
        return result;
    }

    @Override
    public int declareNumber(IAttack iAttack, int target) {
        var array =assignCandidateNumberEachHand(iAttack).get(target);
        return array[new Random().nextInt(array.length)];
    }


}