├── bin
├── bc.jpg
├── util
│ ├── Point.class
│ ├── Message.class
│ ├── MyPiece.class
│ ├── RobotGo.class
│ ├── ShowTime.class
│ ├── UctNode.class
│ └── BasicVariables.class
├── application
│ ├── Main.class
│ ├── RedeHistory.class
│ └── application.css
└── view
│ ├── ChessBorderController$1.class
│ ├── ChessBorderController$2.class
│ ├── ChessBorderController$3.class
│ ├── ChessBorderController.class
│ └── ChessBorde.fxml
├── src
├── bc.jpg
├── application
│ ├── application.css
│ ├── RedeHistory.java
│ ├── NoThreadSafeJavaFXUI.java
│ └── Main.java
├── util
│ ├── Point.java
│ ├── Message.java
│ ├── ShowTime.java
│ ├── BasicVariables.java
│ ├── UctNode.java
│ ├── MyPiece.java
│ └── RobotGo.java
└── view
│ ├── ChessBorde.fxml
│ └── ChessBorderController.java
├── images
├── 启动.png
├── 完整棋局.png
└── 对战模式.png
├── .gitattributes
├── .settings
├── com.genuitec.eclipse.modernweb.common.core.prefs
└── org.eclipse.jdt.core.prefs
├── .classpath
├── Hex.txt
├── README.md
├── .project
└── LICENSE
/bin/bc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/bc.jpg
--------------------------------------------------------------------------------
/src/bc.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/src/bc.jpg
--------------------------------------------------------------------------------
/images/启动.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/images/启动.png
--------------------------------------------------------------------------------
/images/完整棋局.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/images/完整棋局.png
--------------------------------------------------------------------------------
/images/对战模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/images/对战模式.png
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/bin/util/Point.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/util/Point.class
--------------------------------------------------------------------------------
/bin/util/Message.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/util/Message.class
--------------------------------------------------------------------------------
/bin/util/MyPiece.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/util/MyPiece.class
--------------------------------------------------------------------------------
/bin/util/RobotGo.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/util/RobotGo.class
--------------------------------------------------------------------------------
/bin/util/ShowTime.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/util/ShowTime.class
--------------------------------------------------------------------------------
/bin/util/UctNode.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/util/UctNode.class
--------------------------------------------------------------------------------
/bin/application/Main.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/application/Main.class
--------------------------------------------------------------------------------
/bin/util/BasicVariables.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/util/BasicVariables.class
--------------------------------------------------------------------------------
/bin/application/RedeHistory.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/application/RedeHistory.class
--------------------------------------------------------------------------------
/bin/view/ChessBorderController$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/view/ChessBorderController$1.class
--------------------------------------------------------------------------------
/bin/view/ChessBorderController$2.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/view/ChessBorderController$2.class
--------------------------------------------------------------------------------
/bin/view/ChessBorderController$3.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/view/ChessBorderController$3.class
--------------------------------------------------------------------------------
/bin/view/ChessBorderController.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hitong/Hexy/HEAD/bin/view/ChessBorderController.class
--------------------------------------------------------------------------------
/.settings/com.genuitec.eclipse.modernweb.common.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | prefer-global-node-apps=false
3 |
--------------------------------------------------------------------------------
/bin/application/application.css:
--------------------------------------------------------------------------------
1 | /* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */
2 | .label{
3 | -fx-background-image: url("../images/111.png");
4 | }
--------------------------------------------------------------------------------
/src/application/application.css:
--------------------------------------------------------------------------------
1 | /* JavaFX CSS - Leave this comment until you have at least create one rule which uses -fx-Property */
2 | .label{
3 | -fx-background-image: url("../images/111.png");
4 | }
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Hex.txt:
--------------------------------------------------------------------------------
1 | 第1手坐标5 5 第2手坐标6 6 第3手坐标7 4 第4手坐标8 5 第5手坐标8 4 第6手坐标3 6 第7手坐标3 7 第8手坐标4 7 第9手坐标4 6 第10手坐标1 8 第11手坐标1 9 第12手坐标2 9 第13手坐标1 10 第14手坐标2 8 第15手坐标2 10 第16手坐标6 4 第17手坐标6 5 第18手坐标0 10 第19手坐标0 9 第20手坐标3 5 第21手坐标4 4 第22手坐标3 9 第23手坐标3 10 第24手坐标9 4 第25手坐标9 3 第26手坐标6 7 第27手坐标6 8 第28手坐标4 9 第29手坐标4 10 第30手坐标5 9 第31手坐标5 10 第32手坐标6 9 第33手坐标6 10 第34手坐标1 7
--------------------------------------------------------------------------------
/src/util/Point.java:
--------------------------------------------------------------------------------
1 | package util;
2 |
3 | /**
4 | * 将落子坐标的X和Y进行包装
5 | * @author Supertong
6 | *
7 | */
8 | public class Point {
9 | public int x;
10 | public int y;
11 |
12 | public Point(int x, int y){
13 | this.x = x;
14 | this.y = y;
15 | }
16 |
17 | public boolean outRange(int tableX, int tableY) {
18 | return x < 0 || y < 0 || x > tableX - 1 || y > tableY - 1;
19 | }
20 |
21 | public String toString() {
22 | return x + " " + y;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 海克斯棋简介
2 | 六贯棋(英语:Hex)是在六边形格的棋盘上玩的图版游戏,亦是数学游戏,通常使用10乘10或11乘11的菱形棋盘(约翰·纳什则采用14×14的棋盘)。
3 | # 海克斯棋规则
4 | 六贯棋由两个人一起玩,有两种颜色,通常是红、蓝或黑、白。四个边平行填上两方的颜色。双方轮流下,每次占领一处空白格,在空白格放上自己颜色的棋子(或填上自己的颜色)。最先将棋盘属于自己的颜色的边连成一线的一方为胜。
5 | # 程序运行要求
6 | 要求jdk1.8以上(因为使用了JavaFX来搭建棋盘UI)
7 |
8 | # 程序运行示例
9 | ## 启动:
10 | 
11 | ## 模式选择:
12 | 
13 | ## 对局示例:
14 | 
15 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hex
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.xtext.ui.shared.xtextBuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.xtext.ui.shared.xtextNature
21 | org.eclipse.jdt.core.javanature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.8
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.source=1.8
12 |
--------------------------------------------------------------------------------
/src/util/Message.java:
--------------------------------------------------------------------------------
1 | package util;
2 |
3 | import javafx.beans.property.SimpleStringProperty;
4 | import javafx.beans.property.StringProperty;
5 |
6 | public class Message {
7 | private final StringProperty message;
8 | private final StringProperty people;
9 |
10 | public Message() {
11 | this(null,null);
12 | }
13 |
14 | public Message(String people,String message) {
15 | this.people = new SimpleStringProperty(people);
16 | this.message = new SimpleStringProperty(message);
17 | }
18 |
19 | public StringProperty getMessage() {
20 | return message;
21 | }
22 |
23 | public StringProperty getPeople() {
24 | return people;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/application/RedeHistory.java:
--------------------------------------------------------------------------------
1 | package application;
2 |
3 | import java.io.File;
4 | import java.io.FileNotFoundException;
5 | import java.util.Scanner;
6 |
7 | public class RedeHistory {
8 | public static void main(String[] args) {
9 | File f = new File("Hex.txt");
10 | try {
11 | Scanner input = new Scanner(f);
12 | String s = input.nextLine();
13 | String[] t = s.split(" ");
14 | System.out.println(t.length);
15 | for (int i = 0; i <= t.length / 2; i++) {
16 | System.out.println(t[i * 2]);
17 | int m, n;
18 | String[] tmp = t[i * 2].split("坐标");
19 | tmp = tmp[1].split(" ");
20 | m = Integer.parseInt(tmp[0]);
21 | n = Integer.parseInt(tmp[1]);
22 | System.out.println(m + " " + n);
23 | }
24 |
25 | input.close();
26 | } catch (FileNotFoundException e) {
27 | // TODO Auto-generated catch block
28 | e.printStackTrace();
29 | }
30 |
31 | }
32 | }
--------------------------------------------------------------------------------
/src/util/ShowTime.java:
--------------------------------------------------------------------------------
1 | package util;
2 |
3 | public class ShowTime {
4 | public static String setTime(String last) {
5 | String tmp;
6 | String[] s = last.split(":");
7 | int min = Integer.parseInt(s[0]);
8 | int sec = Integer.parseInt(s[1]);
9 | if (++sec == 60) {
10 | min++;
11 | sec = 0;
12 | }
13 | if (min < 10) {
14 | tmp = "0" + min + ":";
15 | } else {
16 | tmp = min + ":";
17 | }
18 | if (sec < 10) {
19 | tmp += "0" + sec;
20 | } else {
21 | tmp += sec;
22 | }
23 |
24 | return tmp;
25 | }
26 |
27 | public static String initTime() {
28 | return "00:00";
29 | }
30 |
31 | public static String getAllTime(String s1, String s2) {
32 | String[] m1 = s1.split(":");
33 | String[] m2 = s2.split(":");
34 |
35 | int min1 = Integer.parseInt(m1[0]);
36 | int sec1 = Integer.parseInt(m1[1]);
37 | int min2 = Integer.parseInt(m2[0]);
38 | int sec2 = Integer.parseInt(m2[1]);
39 | int tmp = sec1 + sec2;
40 | min1 += tmp / 60;
41 | sec1 = tmp % 60;
42 | min1 += min2;
43 | String re;
44 | if (min1 != 0) {
45 | re = min1 + "分 ";
46 | } else {
47 | re = "";
48 | }
49 |
50 | if (sec1 != 0) {
51 | re = re + sec1 + "秒";
52 | }
53 |
54 | return re;
55 | }
56 | }
--------------------------------------------------------------------------------
/src/util/BasicVariables.java:
--------------------------------------------------------------------------------
1 | package util;
2 |
3 | import java.util.Stack;
4 |
5 | import javafx.scene.paint.Color;
6 |
7 | public class BasicVariables {
8 | public final static int size = 20;
9 | public final static int LEFT = 1;
10 | public final static int RIGHT = 2;
11 | public final static int TOP = 3;
12 | public final static int BOTTOM = 4;
13 | public final static Color FIRST_COLOR = Color.GREENYELLOW;
14 | public final static Color SECOND_COLOR = Color.ROYALBLUE;
15 | public final static Color SPACE_COLOR = Color.WHITE;
16 | public static int UndoCheckWin = 0;//该变量用于存储棋子撤回前胜负的状态,0为无结果,1为先手胜,-1为后手胜
17 | public static float TMP = 0;
18 | public static int ROBOT = 0;
19 | public static Point ROBOTMOVE = null;
20 |
21 | public final static Color MOUSE_ON_FIRST = Color.LIGHTGREEN;
22 | public final static Color MOUSE_ON_SECOND = Color.DARKTURQUOISE;
23 | public final static String EXPRESION = "Hex棋,又叫六角棋,译作海克斯棋。据说这个游戏是约翰·纳什发明的。"
24 | + "棋盘为11×11的六边形小格子组成,它是一种两人添子类游戏(跟五子棋一样)。"
25 | + "它的游戏规则是:两人轮流下子,直到有一方用棋子沟通了两条边(比如先手沟通上"
26 | + "下两边则胜利,后手沟通左右两边则胜利)";
27 | public final static String ADITOR = "使用中有任何问题都可以通过QQ邮箱:1906194855@qq.com联系我\n共同学习共同进步!!!😁";
28 | public static int[][] TABLE = new int[11][11];// 先手为1,后手为-1,空白为0
29 | public static Stack HISTORY = new Stack<>();
30 | }
31 |
--------------------------------------------------------------------------------
/src/application/NoThreadSafeJavaFXUI.java:
--------------------------------------------------------------------------------
1 | //package application;
2 | //
3 | //import javafx.application.Application;
4 | //import javafx.application.Platform;
5 | //import javafx.collections.ObservableList;
6 | //import javafx.scene.Node;
7 | //import javafx.scene.Scene;
8 | //import javafx.scene.control.Button;
9 | //import javafx.scene.control.Label;
10 | //import javafx.scene.layout.AnchorPane;
11 | //import javafx.stage.Stage;
12 | //
13 | //public class NoThreadSafeJavaFXUI extends Application {
14 | //
15 | // @Override
16 | // public void start(Stage primaryStage) {
17 | // try {
18 | // AnchorPane root = new AnchorPane();
19 | // Label label = new Label("旧的值");
20 | // Button button = new Button();
21 | //
22 | // label.setLayoutX(100);
23 | // label.setLayoutY(100);
24 | // label.setPrefWidth(100);
25 | //
26 | // button.setLayoutX(100);
27 | // button.setLayoutY(150);
28 | // button.setText("开始");
29 | //
30 | // button.setOnAction((event) -> {
31 | // Thread thread = new Thread() {
32 | // @Override
33 | // public void run() {
34 | // Platform.runLater(() -> {
35 | // label.setText("新的值");
36 | // });
37 | // }
38 | // };
39 | // thread.setName("thread1");
40 | // thread.start();
41 | //
42 | // });
43 | //
44 | // ObservableList children = root.getChildren();
45 | // children.add(label);
46 | // children.add(button);
47 | //
48 | // Scene scene = new Scene(root, 400, 400);
49 | // primaryStage.setScene(scene);
50 | // primaryStage.show();
51 | // } catch (Exception e) {
52 | // e.printStackTrace();
53 | // }
54 | // }
55 | //
56 | // public static void main(String[] args) {
57 | // launch(args);
58 | // }
59 | //}
--------------------------------------------------------------------------------
/src/util/UctNode.java:
--------------------------------------------------------------------------------
1 | package util;
2 |
3 | import java.util.ArrayList;
4 |
5 | public class UctNode {
6 | int visit = 0;
7 | int win = 0;
8 | ArrayList child = new ArrayList<>();
9 | Point bestMove;
10 | Point lastMove;
11 |
12 | public UctNode() {
13 | }
14 |
15 | private UctNode(Point p) {
16 | lastMove = p;
17 | }
18 |
19 | public void getAllChildren(int[][] table) {
20 | // int[] x = this.getLmt(lastMove.x);
21 | // int[] y = this.getLmt(lastMove.y);
22 | // for (int i = x[0]; i <= x[1]; i++) {
23 | // for (int j = y[0]; j <= y[1]; j++) {
24 | // if (table[i][j] == 0) {
25 | // UctNode tmp = new UctNode(new Point(i, j));
26 | // tmp.lastMove = new Point(i, j);
27 | // child.add(tmp);
28 | // }
29 | // }
30 | // }
31 | // if(child.size() == 0) {
32 | for (int i = 0; i < table.length; i++) {
33 | for (int j = 0; j < table[0].length; j++) {
34 | if (table[i][j] == 0) {
35 | child.add(new UctNode(new Point(i, j)));
36 | }
37 | }
38 | }
39 | }
40 |
41 | public int[] getLmt(int t) {
42 | int[] tmp = new int[2];
43 | if (t == 0 || t == 1) {
44 | tmp[0] = 0;
45 | tmp[1] = 4;
46 | } else if (t == 10 || t == 9) {
47 | tmp[0] = 6;
48 | tmp[1] = 10;
49 | } else {
50 | tmp[0] = t - 2;
51 | tmp[1] = t + 2;
52 | }
53 | return tmp;
54 | }
55 |
56 | public UctNode bestSelect(UctNode root, boolean now, boolean boot) {
57 | if (child.isEmpty()) {
58 | return null;
59 | } else {
60 | double UCT = 0;
61 | double winrate = 0;
62 | double bestUct = Integer.MIN_VALUE;
63 | double UCTvalue;
64 | UctNode tmp = null;
65 | for (int i = 0; i < child.size(); i++) {
66 | if (child.get(i).visit == 0) {
67 | UCTvalue = 10000;
68 | } else {
69 | winrate =( child.get(i).win * 1.0) / (child.get(i).visit * 1.0);
70 | UCT = 1 * Math.sqrt(Math.log(root.visit) / (5 * child.get(i).visit));
71 | if (now != boot) {
72 | UCTvalue = winrate + UCT;
73 | } else {
74 | UCTvalue = 1 - winrate + UCT;
75 | }
76 | //
77 | // if(flag == 1){
78 | // System.out.println(UCTvalue);
79 | // }
80 | }
81 | if (UCTvalue > bestUct) {
82 | bestUct = UCTvalue;
83 | tmp = child.get(i);
84 | }
85 | }
86 | // System.out.println();
87 | // System.out.println();
88 | return tmp;
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/util/MyPiece.java:
--------------------------------------------------------------------------------
1 | package util;
2 |
3 | import util.BasicVariables;
4 | import javafx.scene.paint.Color;
5 | import javafx.scene.shape.Polygon;
6 | import javafx.scene.shape.StrokeType;
7 |
8 | public class MyPiece {
9 |
10 | public static Polygon myPiece(double x, double y) {
11 | Polygon polygon = new Polygon();
12 | polygon.getPoints()
13 | .addAll(new Double[] { x, y - 2 * BasicVariables.size, x - 1.2 * BasicVariables.size,
14 | y - 0.75 * BasicVariables.size, x - 1.2 * BasicVariables.size, y + 0.75 * BasicVariables.size,
15 | x, y + 2 * BasicVariables.size, x + 1.2 * BasicVariables.size, y + 0.75 * BasicVariables.size,
16 | x + 1.2 * BasicVariables.size, y - 0.75 * BasicVariables.size });
17 | polygon.setStroke(Color.BLACK);
18 | polygon.setStrokeType(StrokeType.INSIDE);
19 | polygon.setFill(BasicVariables.SPACE_COLOR);
20 | return polygon;
21 | }
22 |
23 | public static Polygon chessBorde(double x, double y, int direction) {
24 | Polygon polygon = new Polygon();
25 | switch (direction) {
26 | case BasicVariables.LEFT:
27 | polygon.getPoints()
28 | .addAll(new Double[] { x - 1.2 * BasicVariables.size, y - 0.75 * BasicVariables.size,
29 | x - 1.2 * BasicVariables.size, y + 0.75 * BasicVariables.size,
30 | x - 2.4 * BasicVariables.size, y - 2 * BasicVariables.size });
31 | polygon.setFill(BasicVariables.SECOND_COLOR);
32 | break;
33 | case BasicVariables.RIGHT:
34 | polygon.getPoints()
35 | .addAll(new Double[] { x + 2.4 * BasicVariables.size, y + 2 * BasicVariables.size,
36 | x + 1.2 * BasicVariables.size, y + 0.75 * BasicVariables.size,
37 | x + 1.2 * BasicVariables.size, y - 0.75 * BasicVariables.size });
38 | polygon.setFill(BasicVariables.SECOND_COLOR);
39 | break;
40 | case BasicVariables.TOP:
41 | polygon.getPoints().addAll(new Double[] { x, y - 2 * BasicVariables.size, x - 1.2 * BasicVariables.size,
42 | y - 0.75 * BasicVariables.size, x - 2.4 * BasicVariables.size, y - 2 * BasicVariables.size, });
43 | polygon.setFill(BasicVariables.FIRST_COLOR);
44 | break;
45 | case BasicVariables.BOTTOM:
46 | polygon.getPoints().addAll(new Double[] { x + 1.2 * BasicVariables.size, y + 0.75 * BasicVariables.size, x,
47 | y + 2 * BasicVariables.size, x + 2.4 * BasicVariables.size, y + 2 * BasicVariables.size, });
48 | polygon.setFill(BasicVariables.FIRST_COLOR);
49 | break;
50 | }
51 | polygon.setStroke(Color.BLACK);
52 | polygon.setStrokeType(StrokeType.INSIDE);
53 | return polygon;
54 | }
55 |
56 | public static Polygon northeast() {
57 | Polygon polygon = new Polygon();
58 | polygon.getPoints().addAll(new Double[] { 558 + 1.2 * BasicVariables.size, 80 - 0.75 * BasicVariables.size,
59 | 558.0, 80.0 - 2 * BasicVariables.size, 572.0, 80.0 - 2 * BasicVariables.size });
60 | polygon.setFill(BasicVariables.FIRST_COLOR);
61 | polygon.setStroke(Color.BLACK);
62 | polygon.setStrokeType(StrokeType.INSIDE);
63 | return polygon;
64 | }
65 |
66 | public static Polygon southwest() {
67 | Polygon polygon = new Polygon();
68 | polygon.getPoints()
69 | .addAll(new Double[] { 315.0, 580.0 + 2 * BasicVariables.size, 315.0 - 1.2 * BasicVariables.size,
70 | 580.0 + 0.75 * BasicVariables.size, 342.0 - 2 * BasicVariables.size,
71 | 580.0 + 2 * BasicVariables.size });
72 | polygon.setFill(BasicVariables.SECOND_COLOR);
73 | polygon.setStroke(Color.BLACK);
74 | polygon.setStrokeType(StrokeType.INSIDE);
75 | return polygon;
76 | }
77 | }
--------------------------------------------------------------------------------
/bin/view/ChessBorde.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
23 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
43 |
47 |
51 |
55 |
62 |
70 |
77 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
119 |
130 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
--------------------------------------------------------------------------------
/src/view/ChessBorde.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
23 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
43 |
47 |
51 |
55 |
62 |
70 |
77 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
119 |
130 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
--------------------------------------------------------------------------------
/src/application/Main.java:
--------------------------------------------------------------------------------
1 | package application;
2 |
3 | import java.io.File;
4 | import java.io.PrintWriter;
5 | import java.util.ArrayList;
6 | import java.util.List;
7 | import javafx.application.Application;
8 | import javafx.collections.FXCollections;
9 | import javafx.collections.ObservableList;
10 | import javafx.fxml.FXMLLoader;
11 | import javafx.scene.Scene;
12 | import javafx.scene.control.Alert;
13 | import javafx.scene.control.Button;
14 | import javafx.scene.control.TextArea;
15 | import javafx.scene.layout.BorderPane;
16 | import javafx.scene.shape.Polygon;
17 | import javafx.stage.Stage;
18 | import javafx.stage.StageStyle;
19 | import util.BasicVariables;
20 | import util.Message;
21 | import util.Point;
22 | import view.ChessBorderController;
23 |
24 | public class Main extends Application {
25 | public static void main(String[] args) {
26 | launch(args);
27 | }
28 |
29 | public ChessBorderController c;
30 | ObservableList message = FXCollections.observableArrayList();
31 | Stage primaryStage;
32 |
33 | @Override
34 | public void start(Stage primaryStage) throws Exception {
35 | // TODO Auto-generated method stub
36 | this.primaryStage = primaryStage;
37 | this.primaryStage.setTitle("Hex棋");
38 | this.primaryStage.setResizable(false);
39 | this.primaryStage.setOnCloseRequest(event -> {
40 | System.exit(0);
41 | });
42 | Application.setUserAgentStylesheet(STYLESHEET_CASPIAN);
43 | showView();
44 | }
45 |
46 | public void showView() {
47 | try {
48 | FXMLLoader loader = new FXMLLoader();
49 | loader.setLocation(Main.class.getResource("/view/ChessBorde.fxml"));
50 | BorderPane page = (BorderPane) loader.load();
51 | Scene scene = new Scene(page);
52 | this.primaryStage.setScene(scene);
53 | this.primaryStage.show();
54 | c = loader.getController();
55 | c.setMain(this);
56 | } catch (Exception ex) {
57 | ex.printStackTrace();
58 | }
59 | }
60 |
61 | public void move(String id) {
62 | String[] tmp = id.split(" ");
63 | int m = Integer.parseInt(tmp[0]);
64 | int n = Integer.parseInt(tmp[1]);
65 | if (BasicVariables.HISTORY.size() % 2 == 0) {
66 | BasicVariables.TABLE[m][n] = 1;
67 | this.message.add(new Message("先手落子" + (BasicVariables.HISTORY.size() / 2 + 1), id));
68 | } else {
69 | BasicVariables.TABLE[m][n] = -1;
70 | this.message.add(new Message("后手落子" + (BasicVariables.HISTORY.size() / 2 + 1), id));
71 | }
72 | BasicVariables.HISTORY.push(new Point(m, n));
73 | }
74 |
75 | public Point undo() {
76 | if (BasicVariables.HISTORY.isEmpty()) {
77 | return null;
78 | } else {
79 | if (BasicVariables.HISTORY.size() % 2 == 1) {
80 | message.add(new Message("先手悔棋", BasicVariables.HISTORY.peek().toString()));
81 | } else {
82 | message.add(new Message("后手悔棋", BasicVariables.HISTORY.peek().toString()));
83 | }
84 | return BasicVariables.HISTORY.pop();
85 | }
86 | }
87 |
88 | public void reStart(TextArea area) {
89 | BasicVariables.HISTORY.clear();
90 | BasicVariables.TABLE = new int[11][11];
91 | message.clear();
92 | }
93 |
94 | public boolean checkWin() {
95 | if (BasicVariables.HISTORY.size() == 0) {
96 | return false;
97 | }
98 | boolean[][] table = new boolean[11][11];
99 | boolean isFirst;
100 | if (BasicVariables.HISTORY.size() % 2 == 1) {
101 | isFirst = true;
102 | } else {
103 | isFirst = false;
104 | }
105 | boolean start;
106 | boolean end;
107 |
108 | table[BasicVariables.HISTORY.peek().x][BasicVariables.HISTORY.peek().y] = true;
109 | List p = getNeighbor(new Point(BasicVariables.HISTORY.peek().x, BasicVariables.HISTORY.peek().y), table);
110 | if (p == null) {
111 | return false;
112 | }
113 | if (isFirst) {
114 | start = (BasicVariables.HISTORY.peek().x == 0);
115 | end = (BasicVariables.HISTORY.peek().x == 10);
116 | while (!p.isEmpty()) {
117 | Point t = p.remove(p.size() - 1);
118 | if (t.x == 0) {
119 | start = true;
120 | } else if (t.x == 10) {
121 | end = true;
122 | }
123 | if (start && end) {
124 | if (BasicVariables.UndoCheckWin == 0) {
125 | BasicVariables.UndoCheckWin = 1;
126 | c.showResult(true);
127 | }
128 | c.stopAllTime();
129 | // showInfo("总步数:" + BasicVariables.HISTORY.size()
130 | // + "\n总耗时:" + ShowTime.getAllTime(c.getTime(true),
131 | // c.getTime(false))
132 | // + "\n对局结果:先手胜利"
133 | // );
134 | return true;
135 | }
136 | List tmp = getNeighbor(t, table);
137 | p.addAll(tmp);
138 | }
139 | } else {
140 | start = (BasicVariables.HISTORY.peek().y == 0);
141 | end = (BasicVariables.HISTORY.peek().y == 10);
142 | while (!p.isEmpty()) {
143 | Point t = p.remove(p.size() - 1);
144 | if (t.y == 0) {
145 | start = true;
146 | } else if (t.y == 10) {
147 | end = true;
148 | }
149 | if (start && end) {
150 | if (BasicVariables.UndoCheckWin == 0) {
151 | BasicVariables.UndoCheckWin = -1;
152 | c.showResult(false);
153 | }
154 | c.stopAllTime();
155 | // showInfo("总步数:" + BasicVariables.HISTORY.size()
156 | // + "\n总耗时:" + ShowTime.getAllTime(c.getTime(true),
157 | // c.getTime(false))
158 | // + "\n对局结果:后手胜利"
159 | // );
160 | return true;
161 | }
162 | List tmp = getNeighbor(t, table);
163 | p.addAll(tmp);
164 | }
165 | }
166 | BasicVariables.UndoCheckWin = 0;
167 | return false;
168 | }
169 |
170 | private List getNeighbor(Point mid, boolean[][] table) {
171 | int m = mid.x;
172 | int n = mid.y;
173 | ArrayList allNeighbor = new ArrayList<>();
174 | allNeighbor.add(new Point(m - 1, n));
175 | allNeighbor.add(new Point(m - 1, n + 1));
176 | allNeighbor.add(new Point(m + 1, n - 1));
177 | allNeighbor.add(new Point(m + 1, n));
178 | allNeighbor.add(new Point(m, n - 1));
179 | allNeighbor.add(new Point(m, n + 1));
180 |
181 | int f = 0;
182 | for (int i = 0; i < 6; i++) {
183 | if (!allNeighbor.get(i).outRange(BasicVariables.TABLE.length, BasicVariables.TABLE[0].length)) {
184 | if (!table[allNeighbor.get(i).x][allNeighbor.get(i).y]) {
185 | table[allNeighbor.get(i).x][allNeighbor.get(i).y] = true;
186 | Polygon p1 = (Polygon) c.getTable().getChildren().get(mid.x * 11 + mid.y);
187 | Polygon p2 = (Polygon) c.getTable().getChildren()
188 | .get(allNeighbor.get(i).x * 11 + allNeighbor.get(i).y);
189 | if (p1.getFill().equals(p2.getFill())) {
190 | allNeighbor.set(f++, allNeighbor.get(i));
191 | }
192 | }
193 | }
194 | }
195 | if (f == 0) {
196 | return new ArrayList<>();
197 | }
198 | return allNeighbor.subList(0, f);
199 | }
200 |
201 | public void showInfo(String s) {
202 | Alert information = new Alert(Alert.AlertType.INFORMATION);
203 | information.initStyle(StageStyle.DECORATED);
204 | information.setHeaderText("新消息");
205 | information.setContentText(s);
206 | Button infor = new Button("show Information");
207 | infor.setOnAction((ActionEvent) -> {
208 | information.showAndWait();
209 | });
210 | information.show();
211 | }
212 |
213 | public void showErr(String s) {
214 | Alert information = new Alert(Alert.AlertType.ERROR);
215 | information.initStyle(StageStyle.DECORATED);
216 | information.setHeaderText("错误");
217 | information.setContentText(s);
218 | Button infor = new Button("show Information");
219 | infor.setOnAction((ActionEvent) -> {
220 | information.showAndWait();
221 | });
222 | information.show();
223 | }
224 |
225 | public ObservableList getMessage() {
226 | return this.message;
227 | }
228 |
229 | public void writeToFile() {
230 | try (PrintWriter out = new PrintWriter(new File("Hex.txt"))) {
231 | for (int i = 0; i < BasicVariables.HISTORY.size(); i++) {
232 | out.write("第" + (i + 1) + "手坐标" + BasicVariables.HISTORY.get(i) + " ");
233 | }
234 | showInfo("记录已经保存至Hex.txt文档中");
235 | } catch (Exception ex) {
236 | showErr("当前暂无记录或存储空间已满,存储失败");
237 | }
238 | System.out.println("位置");
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/src/view/ChessBorderController.java:
--------------------------------------------------------------------------------
1 | package view;
2 |
3 | import java.io.File;
4 | import java.io.FileNotFoundException;
5 | import java.util.Scanner;
6 |
7 | import application.Main;
8 | import javafx.concurrent.Task;
9 | import javafx.fxml.FXML;
10 | import javafx.scene.control.ProgressBar;
11 | import javafx.scene.control.ProgressIndicator;
12 | import javafx.scene.control.TableColumn;
13 | import javafx.scene.control.TableView;
14 | import javafx.scene.control.TextArea;
15 | import javafx.scene.layout.Pane;
16 | import javafx.scene.shape.Polygon;
17 | import javafx.scene.text.Font;
18 | import javafx.scene.text.Text;
19 | import util.BasicVariables;
20 | import util.Message;
21 | import util.MyPiece;
22 | import util.Point;
23 | import util.RobotGo;
24 | import util.ShowTime;
25 |
26 | public class ChessBorderController {
27 | @FXML
28 | private TableView tablePane;
29 |
30 | @FXML
31 | private TableColumn peo;
32 |
33 | @FXML
34 | private TableColumn message;
35 |
36 | @FXML
37 | TextArea result;
38 |
39 | @FXML
40 | TextArea firstTime;// 先手计时
41 |
42 | @FXML
43 | TextArea secondTime;// 后手计时
44 |
45 | @FXML
46 | Pane mainPane; // 棋盘界面
47 |
48 | @FXML
49 | ProgressIndicator pro;
50 |
51 | @FXML
52 | ProgressBar bar;
53 |
54 | Main main;
55 |
56 | @FXML
57 | private void setRobot() {
58 | BasicVariables.ROBOT = 1;
59 | }
60 |
61 | @FXML
62 | private void setMan() {
63 | BasicVariables.ROBOT = 0;
64 | }
65 |
66 | @FXML
67 | private void initialize() {
68 | peo.setCellValueFactory(cellData -> cellData.getValue().getPeople());
69 | message.setCellValueFactory(cellData -> cellData.getValue().getMessage());
70 | }
71 |
72 | Thread robot;
73 |
74 | public void robotGo() {
75 | setDisable(true);
76 | if (robot == null) {
77 | robot = new Thread(new RobotGo(BasicVariables.TABLE, main.c));
78 | robot.start();
79 | } else {
80 | if (!robot.isAlive()) {
81 | robot = new Thread(new RobotGo(BasicVariables.TABLE, main.c));
82 | robot.start();
83 | }
84 | }
85 | }
86 |
87 | public void setMain(Main main) {
88 | this.main = main;
89 | firstTime.setText(ShowTime.initTime());
90 | secondTime.setText(ShowTime.initTime());
91 | result.setText("0:0");
92 | this.tablePane.setItems(main.getMessage());
93 | loadChessBord();
94 | mainPane.setStyle("-fx-background-image:url('/bc.jpg');");
95 | }
96 |
97 | public Task createWorker() {
98 | return new Task() {
99 | @Override
100 | protected Void call() throws Exception {
101 | BasicVariables.TMP = 0;
102 | for (int i = 0; i < 100; i++) {
103 | BasicVariables.TMP += 0.1;
104 | Thread.sleep(100);
105 | updateMessage("2000 milliseconds");
106 | updateProgress(BasicVariables.TMP, 10);
107 | }
108 | return null;
109 | }
110 | };
111 | }
112 |
113 | Task copyWorker;
114 |
115 | private void loadChessBord() {
116 | for (int i = 0; i < 11; i++) {
117 | double y = i * 50 + 80;
118 | for (int j = 0; j < 11; j++) {
119 | double x = 23.5 * i + 47.8 * j + 80;
120 | Polygon po = MyPiece.myPiece(x, y);
121 | po.setId(i + " " + j);
122 |
123 | po.setOnMouseClicked(event -> {
124 | // copyWorker = createWorker();
125 | // pro.progressProperty().unbind();
126 | // pro.progressProperty().bind(copyWorker.progressProperty());
127 | // bar.progressProperty().unbind();
128 | // bar.progressProperty().bind(copyWorker.progressProperty());
129 | // new Thread(copyWorker).start();
130 | if (po.getFill() != BasicVariables.MOUSE_ON_FIRST
131 | && po.getFill() != BasicVariables.MOUSE_ON_SECOND) {
132 | return;
133 | }
134 | if (BasicVariables.HISTORY.size() % 2 == 0) {
135 | po.setFill(BasicVariables.FIRST_COLOR);
136 | } else {
137 | po.setFill(BasicVariables.SECOND_COLOR);
138 | }
139 | main.move(po.getId());
140 | if (main.checkWin()) {
141 | setDisable(true);
142 | } else {
143 | showTime();
144 | if (BasicVariables.ROBOT == 1) {
145 | robotGo();
146 | }
147 | }
148 | });
149 | po.setOnMouseMoved(event -> {
150 | if (po.getFill() == BasicVariables.SPACE_COLOR) {
151 | if (BasicVariables.HISTORY.size() % 2 == 0) {
152 | po.setFill(BasicVariables.MOUSE_ON_FIRST);
153 | } else {
154 | po.setFill(BasicVariables.MOUSE_ON_SECOND);
155 | }
156 | }
157 | });
158 | po.setOnMouseExited(event -> {
159 | if (po.getFill() == BasicVariables.MOUSE_ON_FIRST
160 | || po.getFill() == BasicVariables.MOUSE_ON_SECOND) {
161 | po.setFill(BasicVariables.SPACE_COLOR);
162 | }
163 | });
164 | mainPane.getChildren().add(po);
165 | }
166 | } // 棋子添加
167 | mainPane.getChildren().add(MyPiece.northeast());
168 | mainPane.getChildren().add(MyPiece.southwest());
169 | Text num;
170 | for (int i = 0; i < 11; i++) {
171 | double y = i * 50 + 80;
172 | mainPane.getChildren().add(MyPiece.chessBorde(23.5 * i + 80, y, BasicVariables.LEFT));
173 | mainPane.getChildren().add(MyPiece.chessBorde(23.5 * i + 47.8 * 10 + 80, y, BasicVariables.RIGHT));
174 | mainPane.getChildren().add(MyPiece.chessBorde(47.8 * i + 80, 80, BasicVariables.TOP));
175 | mainPane.getChildren()
176 | .add(MyPiece.chessBorde(23.5 * 10 + 47.8 * i + 80, 10 * 50 + 80, BasicVariables.BOTTOM));
177 | num = new Text(i + "");
178 | num.setLayoutX(i * 47.5 + 75);
179 | num.setLayoutY(32);
180 | num.setFont(Font.font("微软雅黑", 20));
181 | mainPane.getChildren().add(num);
182 |
183 | num = new Text(i + "");
184 | num.setLayoutX(i * 23 + 30);
185 | num.setLayoutY(i * 50 + 90);
186 | num.setFont(Font.font("微软雅黑", 20));
187 | mainPane.getChildren().add(num);
188 | }
189 | }
190 |
191 | public void dd() {
192 | main.move(BasicVariables.ROBOTMOVE.x + " " + BasicVariables.ROBOTMOVE.y);
193 | Polygon p = (Polygon) mainPane.getChildren().get(BasicVariables.ROBOTMOVE.y + BasicVariables.ROBOTMOVE.x * 11);
194 | p.setFill(BasicVariables.SPACE_COLOR);
195 | if (BasicVariables.HISTORY.size() % 2 == 1) {
196 | p.setFill(BasicVariables.FIRST_COLOR);
197 | } else {
198 | p.setFill(BasicVariables.SECOND_COLOR);
199 | }
200 |
201 | if (main.checkWin()) {
202 | setDisable(true);
203 | } else {
204 | setDisable(false);
205 | showTime();
206 | }
207 | }
208 |
209 | private Thread first = new Thread(new Task() {
210 | @Override
211 | protected Void call() throws Exception {
212 | while (true) {
213 | try {
214 | Thread.sleep(1000);
215 | } catch (InterruptedException e) {
216 | e.printStackTrace();
217 | }
218 | firstTime.setText(ShowTime.setTime(firstTime.getText()));
219 | }
220 | }
221 | });
222 |
223 | private Thread second = new Thread(new Task() {
224 | protected Void call() throws Exception {
225 | while (true) {
226 | try {
227 | Thread.sleep(1000);
228 | } catch (InterruptedException e) {
229 | e.printStackTrace();
230 | }
231 | secondTime.setText(ShowTime.setTime(secondTime.getText()));
232 | }
233 | }
234 | });
235 |
236 | @SuppressWarnings("deprecation")
237 | private void showTime() {
238 | if (!first.isAlive() && !second.isAlive()) {
239 | first.start();
240 | second.start();
241 | first.suspend();
242 | } else if (BasicVariables.HISTORY.size() % 2 == 1) {
243 | first.suspend();
244 | second.resume();
245 | } else {
246 | first.resume();
247 | second.suspend();
248 | }
249 | }
250 |
251 | private void clean() {
252 | for (int i = 0; i < 11 * 11; i++) {
253 | Polygon p = (Polygon) mainPane.getChildren().get(i);
254 | p.setFill(BasicVariables.SPACE_COLOR);
255 | }
256 | this.setDisable(false);
257 | }
258 |
259 | public void showResult(boolean isFirst) {
260 | String[] re = result.getText().split(":");
261 | if (isFirst) {
262 | result.setText((Integer.parseInt(re[0]) + 1) + ":" + re[1]);
263 | } else {
264 | result.setText(re[0] + ":" + (Integer.parseInt(re[1]) + 1));
265 | }
266 | }
267 |
268 | @SuppressWarnings("deprecation")
269 | @FXML
270 | private void restart() {
271 | if (BasicVariables.HISTORY.size() != 0) {
272 | this.first.suspend();
273 | this.second.suspend();
274 | this.firstTime.setText(ShowTime.initTime());
275 | this.secondTime.setText(ShowTime.initTime());
276 | }
277 | clean();
278 | main.reStart(firstTime);
279 | }
280 |
281 | public void undo() {
282 | Point point = main.undo();
283 | if (point == null) {
284 | return;
285 | }
286 | if (BasicVariables.UndoCheckWin != 0) {
287 | String[] re = result.getText().split(":");
288 | if (BasicVariables.UndoCheckWin == 1) {
289 | result.setText((Integer.parseInt(re[0]) - 1) + ":" + re[1]);
290 | } else {
291 | result.setText(re[0] + ":" + (Integer.parseInt(re[1]) - 1));
292 | }
293 | BasicVariables.UndoCheckWin = 0;
294 | }
295 | BasicVariables.TABLE[point.x][point.y] = 0;
296 | Polygon p = (Polygon) mainPane.getChildren().get(point.x * 11 + point.y);
297 | p.setFill(BasicVariables.SPACE_COLOR);
298 | this.setDisable(false);
299 | this.showTime();
300 | }
301 |
302 | public String getTime(boolean isFirst) {
303 | if (isFirst) {
304 | return firstTime.getText();
305 | } else {
306 | return secondTime.getText();
307 | }
308 | }
309 |
310 | @SuppressWarnings("deprecation")
311 | public void stopAllTime() {
312 | first.suspend();
313 | second.suspend();
314 | }
315 |
316 | @FXML
317 | private void randomMove() {
318 | this.robotGo();
319 | }
320 |
321 | @FXML
322 | private void restore() {
323 | this.restart();
324 | File f = new File("Hex.txt");
325 | try {
326 | Scanner input = new Scanner(f);
327 | String s = input.nextLine();
328 | input.close();
329 | String[] t = s.split(" ");
330 | for (int i = 0; i <= t.length / 2; i++) {
331 | int m, n;
332 | String[] tmp = t[i * 2].split("坐标");
333 | tmp = tmp[1].split(" ");
334 | m = Integer.parseInt(tmp[0]);
335 | n = Integer.parseInt(tmp[1]);
336 | Polygon p = (Polygon) mainPane.getChildren().get(m * 11 + n);
337 | if (p.getFill().equals(BasicVariables.SPACE_COLOR)) {
338 | if (BasicVariables.HISTORY.size() % 2 == 0) {
339 | p.setFill(BasicVariables.FIRST_COLOR);
340 | } else {
341 | p.setFill(BasicVariables.SECOND_COLOR);
342 | }
343 | main.move(m + " " + n);
344 | }
345 | }
346 | if (main.checkWin()) {
347 | this.setDisable(true);
348 | }
349 | } catch (FileNotFoundException e) {
350 | // TODO Auto-generated catch block
351 | e.printStackTrace();
352 | }
353 | }
354 |
355 | public Pane getTable() {
356 | return mainPane;
357 | }
358 |
359 | private void setDisable(boolean flag) {
360 | if (flag) {
361 | for (int i = 0; i < 121; i++) {
362 | mainPane.getChildren().get(i).setDisable(true);
363 | }
364 | } else {
365 | for (int i = 0; i < 121; i++) {
366 | mainPane.getChildren().get(i).setDisable(false);
367 | }
368 | }
369 | }
370 |
371 | @FXML
372 | private void robotGoFirst() {
373 | this.restart();
374 | this.setRobot();
375 | this.robotGo();
376 | }
377 |
378 | @FXML
379 | private void explanation() {
380 | main.showInfo(BasicVariables.EXPRESION);
381 | }
382 |
383 | @FXML
384 | private void author() {
385 | main.showInfo(BasicVariables.ADITOR);
386 | }
387 |
388 | @FXML
389 | private void writeToFile() {
390 | main.writeToFile();
391 | }
392 |
393 | @FXML
394 | private void newGame() {
395 | this.restart();
396 | this.result.setText("0:0");
397 | }
398 |
399 | public void exit() {
400 | System.exit(0);
401 | }
402 | }
403 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/src/util/RobotGo.java:
--------------------------------------------------------------------------------
1 | package util;
2 |
3 | import java.util.ArrayList;
4 | import java.util.EmptyStackException;
5 | import java.util.List;
6 | import java.util.Stack;
7 |
8 | import view.ChessBorderController;
9 |
10 | /**
11 | *
12 | * 由当前局面建立根节点,生成根节点的子节点 从根节点开始 利用UCB公式计算每个子节点的UCB值,选择最大值的子节点
13 | * 若此节点不是叶节点,则从此节点开始,重复2 直到遇到叶节点,如果叶节点曾经被模拟对局过,为这个叶节点生成子节点,从此节点开始,重复2
14 | * 否则对这个叶节点进行模拟对局,得到胜负结果,将这个收益按对应颜色更新到该节点及它的每一级祖先节点上去 回到1,除非时间结束或者达到预设循环次数
15 | * 从根节点的子节点中挑选平均收益最高的,作为最佳点
16 | */
17 |
18 | public class RobotGo implements Runnable {
19 | private int[][] table;
20 | private int searchWidth;
21 | private int hasMove = 0;
22 | int devX = 0;
23 | int devY = 0;
24 | int f = 0;
25 | int s = 0;
26 | public boolean isFirst = false;
27 | public ArrayList child = new ArrayList();
28 | private Point lastMove;
29 | private ChessBorderController c;
30 | private boolean goOne = false;
31 | private int[][] backUp = new int[11][11];
32 | private int count = 0;
33 | private UctNode root;
34 |
35 | /**
36 | * 将不同的小数组和对应偏移量算出获取
37 | *
38 | * @param table
39 | * @param c
40 | */
41 | public RobotGo(int[][] table, ChessBorderController c) {
42 | int first = 0;
43 | int second = 0;
44 | this.c = c;
45 | for (int i = 0; i < 11; i++) {
46 | for (int j = 0; j < 11; j++) {
47 | if (table[i][j] == 1) {
48 | first++;
49 | backUp[i][j] = 1;
50 | hasMove++;
51 | } else if (table[i][j] == -1) {
52 | second++;
53 | backUp[i][j] = -1;
54 | hasMove++;
55 | }
56 | }
57 | }
58 | isFirst = (first == second);
59 | try {
60 | lastMove = new Point(BasicVariables.HISTORY.peek().x, BasicVariables.HISTORY.peek().y);
61 | } catch (EmptyStackException ex) {
62 | lastMove = null;
63 | }
64 | System.out.println("table: " + hasMove);
65 | System.out.println("isFirst:" + isFirst);
66 | // System.out.println("lastMove:" + lastMove.x + " " + lastMove.y);
67 | if(hasMove < 30){
68 | goOne = evaluateTable(table, lastMove);
69 | }
70 | else {
71 | this.table = table;
72 | searchWidth = 10;
73 | }
74 | }
75 |
76 | private boolean evaluateTable(int[][] table, Point p) {
77 | if (p == null) {
78 | return true;
79 | }
80 | for (int i = 3; i < 11; i++) {
81 | this.searchWidth = i;
82 | changeTable(table, p, i);
83 | if (checkTable()) {// ******************
84 | int canMove = 0, j = 0, k = 0;
85 | for (; j < this.table.length; j++) {
86 | for (k = 0; k < this.table[0].length; k++) {
87 | if (this.table[j][k] == 0) {
88 | canMove++;
89 | }
90 | }
91 | }
92 | if (canMove > j * k / 2) {
93 | break;
94 | }
95 | }
96 | this.lastMove.x += devX;
97 | this.lastMove.y += devY;
98 | }
99 | System.out.println("search width: " + this.searchWidth + " ");
100 | return false;
101 | }
102 |
103 | private boolean checkTable() {
104 | boolean flag = false;
105 | for (int i = 0; i < table.length; i++) {
106 | if (table[i][0] == 1) {
107 | if (checkWin(table, new Point(i, 0)) != 0) {
108 | return false;
109 | }
110 | } else if (table[i][0] == 0 || table[i][table[0].length - 1] == 0) {
111 | flag = true;
112 | }
113 | }
114 | for (int i = 0; i < table[0].length; i++) {
115 | if (table[0][i] == -1) {
116 | if (checkWin(table, new Point(0, i)) != 0) {
117 | return false;
118 | }
119 | } else if (table[0][i] == 0 || table[table.length - 1][i] == 0) {
120 | flag = true;
121 | }
122 | }
123 | return flag;
124 | }
125 |
126 | private void changeTable(int[][] table, Point p, int range) {
127 | int limXF = p.x - range;
128 | int limXN = p.x + range;
129 | int limYF = p.y - range;
130 | int limYN = p.y + range;
131 | if (limXF < 0) {
132 | limXF = 0;
133 | }
134 | if (limXN > 10) {
135 | limXN = 10;
136 | }
137 |
138 | if (limYF < 0) {
139 | limYF = 0;
140 | }
141 | if (limYN > 10) {
142 | limYN = 10;
143 | }
144 |
145 | devX = limXF;
146 | devY = limYF;
147 | this.table = new int[limXN - limXF + 1][limYN - limYF + 1];
148 | for (int i = 0; i < this.table.length; i++) {
149 | for (int j = 0; j < this.table[0].length; j++) {
150 | this.table[i][j] = table[limXF + i][limYF + j];
151 | }
152 | } // 数据装入
153 | this.lastMove.x -= devX;
154 | this.lastMove.y -= devY;
155 | }
156 |
157 | @Override
158 | public void run() {
159 | if (goOne) {
160 | BasicVariables.ROBOTMOVE = new Point(5, 5);
161 | } else {
162 | BasicVariables.ROBOTMOVE = UctSearch();
163 | }
164 | c.dd();
165 | }
166 |
167 | private Point UctSearch() {
168 | // long startTime = System.currentTimeMillis();
169 | // long endTime = System.currentTimeMillis();
170 | UctNode node = new UctNode();
171 | root = node;
172 | node.lastMove = lastMove;
173 | int t = 0;
174 | // while (endTime - startTime < 15000) {// 1000为1秒
175 | while (t++ < 300000.0 / this.searchWidth) {
176 | playSimulation(node);
177 | // endTime = System.currentTimeMillis();
178 | }
179 | setBest(node);
180 | // if(node.win * 1.0 / node.visit < 0.4){
181 | // t = 0;
182 | // node.child = new ArrayList<>();
183 | // this.table = backUp;
184 | // devX = 0;
185 | // devY = 0;
186 | // while (t++ < 10000) {
187 | // System.out.println("15");
188 | // playSimulation(node);
189 | // }
190 | // }
191 | // for(int i = 0; i < node.child.size(); i++){
192 | // System.out.println(node.child.get(i).win / (1.0*
193 | // node.child.get(i).visit) + " " + node.child.get(i).visit);
194 | // }
195 |
196 | // for(int i = 0; i < table.length; i++){
197 | // for(int j = 0; j < table[0].length; j++){
198 | // System.out.print(table[i][j] + " ");
199 | // }
200 | // System.out.println();
201 | // }
202 |
203 | System.out.println("first win: " + f + " second win: " + s);
204 | System.out.println("devX: " + devX + " devY: " + devY);
205 | System.out.println("all node " + count);
206 | System.out.println("win rate: " + node.win * 1.0 / node.visit);
207 | try {
208 | node.bestMove.x += devX;
209 | node.bestMove.y += devY;
210 | return node.bestMove;
211 | } catch (NullPointerException ex) {
212 | for (int i = 0; i < 11; i++) {
213 | for (int j = 0; j < 11; j++) {
214 | if (table[i][j] == 0) {
215 | return new Point(i, j);
216 | }
217 | }
218 | }
219 | throw new NullPointerException();
220 | }
221 | }
222 |
223 | private Point getRamdom() {
224 | int x = (int) (Math.random() * 1000) % (table.length);
225 | int y = (int) (Math.random() * 1000) % (table[0].length);
226 | return new Point(x, y);
227 | }
228 |
229 | boolean randomResult = false;
230 |
231 | /**
232 | *
233 | * @param node
234 | * uct节点
235 | * @param table
236 | * 棋盘
237 | * @param isFirst
238 | * 最后一次落子的先后手情况
239 | * @return
240 | */
241 | private void playSimulation(UctNode node) {
242 | int result = checkWin(table, node.lastMove);
243 | if (result != 0) {
244 | // System.out.println(node.lastMove);
245 | if (isFirst == (result == 1)) {
246 | randomResult = true;
247 | } else {
248 | randomResult = false;
249 | }
250 | } else if (node.visit == 0) {
251 | count++;
252 | result = randomMove(node);
253 | if (isFirst == (result == 1)) {
254 | randomResult = true;
255 | } else {
256 | randomResult = false;
257 | }
258 | } else {
259 | if (node.child.isEmpty()) {
260 | node.getAllChildren(table);
261 | }
262 | UctNode next = node.bestSelect(root, table[node.lastMove.x][node.lastMove.y] == 1, isFirst);
263 | // if(node.flag == 1){
264 | // System.out.println(next.lastMove);
265 | // }
266 | this.move(table[node.lastMove.x][node.lastMove.y] == 1, next.lastMove);
267 | playSimulation(next);
268 | this.unmove(next.lastMove);
269 | }
270 |
271 | node.visit++;
272 | updataWin(node);
273 | // if (node.child.size() != 0) {
274 | // setBest(node);
275 | // }
276 | }
277 |
278 | private void updataWin(UctNode node) {
279 | if (this.randomResult) {
280 | node.win++;
281 | }
282 | }
283 |
284 | private void setBest(UctNode node) {
285 | double max = -1;
286 | for (int i = 0; i < node.child.size(); i++) {
287 | UctNode tmp = node.child.get(i);
288 | if (tmp.win / (1.0 * tmp.visit) > max) {
289 | max = tmp.win * 1.0 / tmp.visit;
290 | node.bestMove = tmp.lastMove;
291 | // System.out.println(max);
292 | }
293 | }
294 | }
295 |
296 | /**
297 | * 随机模拟至棋局结束
298 | *
299 | * @param table
300 | * 当前棋盘
301 | * @param node
302 | * 模拟起始UCT节点
303 | * @return 先手胜返回1,后手胜返回-1
304 | */
305 | private int randomMove(UctNode node) {
306 | int t = this.checkWin(table, node.lastMove);
307 | boolean isFirst = false;
308 | if (table[node.lastMove.x][node.lastMove.y] == -1) {
309 | isFirst = true;
310 | }
311 | Stack history = new Stack<>();
312 | while (t == 0) {
313 | Point p = this.getRamdom();
314 | if (table[p.x][p.y] == 0) {
315 | history.push(p);
316 | if (isFirst) {
317 | table[p.x][p.y] = 1;
318 | } else {
319 | table[p.x][p.y] = -1;
320 | }
321 | t = this.checkWin(table, history.peek());
322 | isFirst = !isFirst;
323 | }
324 | }
325 | Point tmp = null;
326 | while (!history.isEmpty()) {
327 | tmp = history.pop();
328 | table[tmp.x][tmp.y] = 0;
329 | } // 恢复
330 | return t;
331 | }
332 |
333 | /**
334 | *
335 | * @param table
336 | * 当前棋盘
337 | * @param point
338 | * 上一手落子坐标
339 | * @return 先手胜利返回1,后手胜利返回-1,无结果返回0
340 | */
341 | private int checkWin(int[][] table, Point point) {
342 | if (point == null) {
343 | return 0;
344 | }
345 | boolean start = false;
346 | boolean end = false;
347 | boolean[][] tmpTable = new boolean[table.length][table[0].length];
348 | tmpTable[point.x][point.y] = true;
349 | List p = getNeighbor(table, tmpTable, point);
350 |
351 | if (table[point.x][point.y] == 1) { // 先手
352 | if (point.x == 0) {
353 | start = true;
354 | } else if (point.x == table.length - 1) {
355 | end = true;
356 | }
357 | while (!p.isEmpty()) {
358 | Point t = p.remove(p.size() - 1);
359 | if (t.x == 0) {
360 | start = true;
361 | } else if (t.x == table.length - 1) {
362 | end = true;
363 | }
364 | if (start && end) {
365 | f++;
366 | return 1;
367 | }
368 | List tmp = getNeighbor(table, tmpTable, t);
369 | p.addAll(tmp);
370 | }
371 | } else {
372 | if (point.y == 0) {
373 | start = true;
374 | } else if (point.y == table[0].length - 1) {
375 | end = true;
376 | }
377 | while (!p.isEmpty()) {
378 | Point t = p.remove(p.size() - 1);
379 | if (t.y == 0) {
380 | start = true;
381 | } else if (t.y == table[0].length - 1) {
382 | end = true;
383 | }
384 | if (start && end) {
385 | s++;
386 | return -1;
387 | }
388 | List tmp = getNeighbor(table, tmpTable, t);
389 | p.addAll(tmp);
390 | }
391 | }
392 | return 0;
393 | }
394 |
395 | // 从输入点开始向围绕点拓展
396 | private List getNeighbor(int[][] table, boolean[][] tmpTable, Point mid) {
397 | int m = mid.x;
398 | int n = mid.y;
399 | ArrayList allNeighbor = new ArrayList<>();
400 | allNeighbor.add(new Point(m - 1, n));
401 | allNeighbor.add(new Point(m - 1, n + 1));
402 | allNeighbor.add(new Point(m + 1, n - 1));
403 | allNeighbor.add(new Point(m + 1, n));
404 | allNeighbor.add(new Point(m, n - 1));
405 | allNeighbor.add(new Point(m, n + 1));
406 |
407 | int flag = 0;
408 | for (int i = 0; i < 6; i++) {
409 | if (!allNeighbor.get(i).outRange(table.length, table[0].length)) {
410 | if (!tmpTable[allNeighbor.get(i).x][allNeighbor.get(i).y]) {
411 | tmpTable[allNeighbor.get(i).x][allNeighbor.get(i).y] = true;
412 | if (table[mid.x][mid.y] == table[allNeighbor.get(i).x][allNeighbor.get(i).y]) {
413 | allNeighbor.set(flag++, allNeighbor.get(i));
414 | }
415 | }
416 | }
417 | }
418 | if (flag == 0) {
419 | return new ArrayList<>();
420 | } else {
421 | return allNeighbor.subList(0, flag); // 提出多余的点
422 | }
423 | }
424 |
425 | private boolean move(boolean isFirst, Point p) {
426 | if (!isFirst) {
427 | table[p.x][p.y] = 1;
428 | } else {
429 | table[p.x][p.y] = -1;
430 | }
431 | return true;
432 | }
433 |
434 | private void unmove(Point p) {
435 | table[p.x][p.y] = 0;
436 | }
437 | }
438 |
--------------------------------------------------------------------------------