介绍
井字棋,英文名叫Tic-Tac-Toe,是一种在3*3格子上进行的连珠游戏,和五子棋类似,由于棋盘一般不画边框,格线排成井字故得名。游戏需要的工具仅为纸和笔,然后由分别代表O和X的两个游戏者轮流在格子里留下标记(一般来说先手者为X),任意三个标记形成一条直线,则为获胜。
训练AI
主要思路是保存每次失败的局,下次不在走类似的局,这样经过长期训练,AI会越来越聪明
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* TicTacToe
*
* @author your name
*/
public class TicTacToe {
// member variables
private static final String[][] table = new String[3][3];
private static final CopyOnWriteArrayList<String> success = new CopyOnWriteArrayList<String>();
private static final CopyOnWriteArrayList<String> pStrings = new CopyOnWriteArrayList<String>();
private static final CopyOnWriteArrayList<String> cStrings = new CopyOnWriteArrayList<String>();
private static final CopyOnWriteArrayList<String> losingStrings = new CopyOnWriteArrayList<String>();
// main
public static void main(String[] args) {
// initial
initSuccess();
// loop
do {
System.out.println("start game!");
test();
} while (true);
}
@SuppressWarnings("resource")
// test
public static void test() {
Scanner sc = new Scanner(System.in);
CopyOnWriteArrayList<String> losingList = new CopyOnWriteArrayList<String>();
int index = 0;
do {
System.out.println("input anything");
sc.next();
System.out.println("your input position 1: (range 0 from 2)");
int p1 = sc.nextInt();
System.out.println("your input position 2: (range 0 from 2)");
int p2 = sc.nextInt();
table[p1][p2] = "p";
pStrings.add(p1 + "" + p2);
index++;
int a1 = 0;
int a2 = 0;
if (index == 5) ;
else {
do {
// call computer
int[] cs = computerTurn();
table[cs[0]][cs[1]] = "c";
boolean fs = false;
String temp = print();
for (int i = 0; i < losingStrings.size(); i++) {
if (temp.equals(losingStrings.get(i))) {
fs = true;
}
}
if (fs) {
table[cs[0]][cs[1]] = null;
continue;
} else {
a1 = cs[0];
a2 = cs[1];
break;
}
} while (true);
cStrings.add(a1 + "" + a2);
}
// print
System.err.println(print());
// record
losingList.add(print());
// judge
boolean[] flag = judge();
if (flag[0] | flag[1]) {
// clear table
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
table[i][j] = null;
}
}
// print result
if (flag[1]) {
System.err.println("person wins!");
losingStrings.add(losingList.get(losingList.size() - 2));
System.err.println(printLosing());
pStrings.clear();
cStrings.clear();
break;
} else {
System.err.println("computer wins!");
cStrings.clear();
pStrings.clear();
break;
}
}
// is tie
if (isTie()) {
break;
}
} while (true);
}
// printLosing
public static String printLosing() {
String outString = "";
for (int i = 0; i < losingStrings.size(); i++) {
outString += "losing:\n" + losingStrings.get(i) + "\n";
}
return outString;
}
// isTie
public static boolean isTie() {
int idxs = 0;
// valid of table
for (int i = 0; i < table.length; i++) {
for (int j = 0; j < 3; j++) {
if (table[i][j] != null) idxs++;
}
}
if (idxs == 9) {
System.err.println("equal or tie");
cStrings.clear();
pStrings.clear();
// clear table
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
table[i][j] = null;
}
}
return true;
}
return false;
}
public static boolean[] judge() {
// judge success
boolean fc = false;
boolean fp = false;
for (int i = 0; i < success.size(); i++) {
int b = 0;
for (int j = 0; j < pStrings.size(); j++) {
int f = 0;
if (success.get(i).substring(0, 2).equals(pStrings.get(j))) {
f = 1;
}
if (success.get(i).substring(2, 4).equals(pStrings.get(j))) {
f = 1;
}
if (success.get(i).substring(4, 6).equals(pStrings.get(j))) {
f = 1;
}
if (f == 1) {
b++;
}
}
if (b == 3) {
fp = true;
break;
}
}
for (int i = 0; i < success.size(); i++) {
int a = 0;
for (int j = 0; j < cStrings.size(); j++) {
int f = 0;
if (success.get(i).substring(0, 2).equals(cStrings.get(j))) {
f = 1;
}
if (success.get(i).substring(2, 4).equals(cStrings.get(j))) {
f = 1;
}
if (success.get(i).substring(4, 6).equals(cStrings.get(j))) {
f = 1;
}
if (f == 1) {
a++;
}
}
if (a == 3) {
fc = true;
break;
}
}
System.out.println("cs=" + cStrings.toString());
System.out.println("ps=" + pStrings.toString());
return new boolean[]{fc, fp};
}
public static String print() {
// print
String tableString = "";
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (table[i][j] == null) {
tableString += " \t";
} else if (table[i][j].equals("c")) {
tableString += "c\t";
} else {
tableString += "p\t";
}
}
tableString += "\n";
}
return tableString;
}
// computer turn
public static int[] computerTurn() {
int[] res = new int[2];
int c1 = 0;
int c2 = 0;
do {
c1 = new Random().nextInt(3);
c2 = new Random().nextInt(3);
if (table[c1][c2] == null) {
break;
}
} while (true);
res[0] = c1;
res[1] = c2;
return res;
}
// initSuccess
public static void initSuccess() {
final String[] items = {
"00", "01", "02",
"10", "11", "12",
"20", "21", "22"
};
final int[][] combination = {
{0, 4, 8},
{2, 4, 6},
{0, 1, 2},
{3, 4, 5},
{6, 7, 8},
{0, 3, 6},
{1, 4, 7},
{2, 5, 8}
};
for (int i = 0; i < combination.length; i++) {
int[] temp = combination[i];
String t1 = items[temp[0]] + items[temp[1]] + items[temp[2]];
success.add(t1);
String t4 = items[temp[2]] + items[temp[1]] + items[temp[0]];
success.add(t4);
String t2 = items[temp[1]] + items[temp[0]] + items[temp[2]];
success.add(t2);
String t5 = items[temp[2]] + items[temp[0]] + items[temp[1]];
success.add(t5);
String t3 = items[temp[0]] + items[temp[2]] + items[temp[1]];
success.add(t3);
String t6 = items[temp[1]] + items[temp[2]] + items[temp[0]];
success.add(t6);
}
}
}
效果
启动后和AI进行对局,AI每次会将失败的路数记录下来,下次不再走重复的路径,训练久了AI就会越来越聪明