forked from kuri8ive/Reversi-on-CUI
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGeneralPlayer.java
More file actions
65 lines (59 loc) · 2.46 KB
/
GeneralPlayer.java
File metadata and controls
65 lines (59 loc) · 2.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import java.util.*;
// モンテカルロ法を用い,Boardインターフェースを守っているゲーム盤なら何でも,ある程度
// 「よい」手を選ぶ,何でも屋ゲームプレイヤー
public class GeneralPlayer implements Player {
private static final String TITLE = "General AI";
private final String name;
private final Random random;
public GeneralPlayer(String name) {
this.name = name;
random = new Random();
}
public String getName() { return name; }
@Override
public int move(Board board) {
List<Integer> moves = board.legalMoves();
int n = moves.size();
Player.ID myID = board.nextTurn();
long[] win = new long[n];
long[] lost = new long[n];
long start = System.nanoTime();
while (System.nanoTime() - start < 10000000000L) {
//while (System.nanoTime() - start < 35000000000L) { // 35秒間シミュレーションを繰り返す
int i = 0;
for (int m : moves) { // すべての可能な手について1回ずつシミュレーションする
board.put(m);
Player.ID winner = tryOne(board); // ゲーム終了までランダムな手を選ぶ
if (winner == myID) { // 自分の勝ちだった
win[i]++;
} else if (winner != Player.ID.NONE) {
lost[i]++; // 勝ちでも引き分けでもなければ負け
}
board.unput();
i++;
}
}
// (勝利数 - 敗北数) がもっとも大きい手を選ぶ
int max = 0;
for (int i = 0; i < n; i++) {
if (win[max] - lost[max] < win[i] - lost[i]) {
max = i;
}
}
return moves.get(max);
}
private Player.ID tryOne(Board board) {
if (board.isEndOfGame()) {
return board.winner(); // 最終的な勝者を返す
}
List<Integer> m = board.legalMoves();
board.put(m.get(random.nextInt(m.size()))); // ランダムな手を選ぶ
Player.ID value = tryOne(board); // 再帰的に次の局面へ
board.unput(); // 元の状態を復元
return value; // このシミュレーションの結果の勝者
}
@Override
public String getTitle() {
return TITLE;
}
}