package controls; import interfaces.IBotBehavior; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Random; import java.util.stream.Collectors; import static views.Constants.DECK_COUNT; public class BotIntelligence implements IBotBehavior { TurnBot turnBot; public BotIntelligence(TurnBot turnBot) { this.turnBot = turnBot; } /** * 未確定の数字を列挙する */ List<Integer> calculateCandidate() { //候補の初期化 List<Integer> candidates = new ArrayList<Integer>(); for (int i = 0; i < DECK_COUNT; i++) candidates.add(i); candidates.removeAll(turnBot.getOpponentHands().stream().map(x -> x.getKey()).collect(Collectors.toList())); candidates.removeAll(turnBot.getMyHands().stream().filter(x -> x.getValue()).map(x -> x.getKey()).collect(Collectors.toList())); return candidates; } /** * 相手の手札に対して、候補となる数字を割り当てる * * @return 候補のリスト */ List<int[]> assignCandidateNumberEachHand() { List<Map.Entry<Integer, Boolean>> myHands = turnBot.getMyHands(); List<int[]> result = new ArrayList<int[]>(); for (Map.Entry<Integer, Boolean> card : myHands) {//ユーザーの手札を左から見ていく int index = myHands.indexOf(card);//左からindex番目に List<Integer> candidateList = calculateCandidate();//確認するカード if (card.getValue()) { candidateList.clear(); } else { //裏の場合 //そのカードから右隣のカードを確認していく for (int i = 0; i < myHands.size() - index - 1; i++) { //今確認していっているカード Map.Entry<Integer, Boolean> 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++) { //今確認していっているカード Map.Entry<Integer, Boolean> currentCard = myHands.get(index - i); if (currentCard.getValue()) {//表があれば、それより小さい数字を候補から削除する candidateList.removeIf(x -> x < currentCard.getKey()); } } } String s = (card.getValue() ? "+" : "-") + card.getKey() + ":["; for (int i : candidateList) s += i + " "; s += "]\n"; System.out.println(s); result.add(candidateList.stream().mapToInt(x -> x).toArray()); } return result; } //公開されていないカードのインデックスを選ぶ(カードにかかれている番号ではない) @Override public int selectAttacker() { List<Map.Entry<Integer, Boolean>> botHands = turnBot.getOpponentHands(); for (Map.Entry<Integer, Boolean> i : botHands) {//小さいものから選択 if (!i.getValue()) return botHands.indexOf(i); } return 0; } @Override public int selectTarget() { List<int[]> candidate = assignCandidateNumberEachHand(); int result = 0; int min = DECK_COUNT; for (int[] i : candidate) { if (i.length < min && i.length != 0) { result = candidate.indexOf(i); min = i.length; } } return result; } @Override public int declareNumber(int target) { int[] array = assignCandidateNumberEachHand().get(target); return array[new Random().nextInt(array.length)]; } }