Skip to content

Instantly share code, notes, and snippets.

@uwi
Last active June 30, 2016 18:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save uwi/5baad8805ff5e5e8763c30786ec04526 to your computer and use it in GitHub Desktop.
Save uwi/5baad8805ff5e5e8763c30786ec04526 to your computer and use it in GitHub Desktop.
chain_easyのAI. まだ改良の余地大有り。深さ上限と時間上限を適当に設定してSimulator.mainを実行。ローカルの色調少しいじっているので他のマシンだと色調変えないといけないかも。
public class Action {
public int r, c;
public long plus;
public int ercol;
public Action(int r, int c) {
this.r = r;
this.c = c;
this.plus = 0;
this.ercol = 0;
}
@Override
public String toString() {
return "Action [r=" + r + ", c=" + c + ", plus=" + plus + "]";
}
public static Action LEAF = new Action(-1, -1);
}
import java.awt.AWTException;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.util.Arrays;
public class Simulator {
public static int[][] capture()
{
try {
Robot r = new Robot();
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
Rectangle rect = env.getMaximumWindowBounds();
// Rectangle rect = new Rectangle(0, 200, 600, 600);
BufferedImage bi = r.createScreenCapture(rect);
// try {
// ImageIO.write(bi, "png", new File("c:\\temp\\ss.png"));
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
int[] data = bi.getData().getPixels(0, 0, rect.width, rect.height, (int[])null);
tr(data.length, rect.width*rect.height);
int[][] rs = new int[rect.height][rect.width];
int[][] gs = new int[rect.height][rect.width];
int[][] bs = new int[rect.height][rect.width];
for(int i = 0;i < rect.height;i++){
for(int j = 0;j < rect.width;j++){
rs[i][j] = data[(i*rect.width+j)*3];
gs[i][j] = data[(i*rect.width+j)*3+1];
bs[i][j] = data[(i*rect.width+j)*3+2];
}
}
// green : 71, 162, 26
// purple : 137, 57, 140
// light : 175, 203, 0
// Map<Integer, Integer> f = new HashMap<>();
// for(int i = 1;i < rect.height-1;i++){
// for(int j = 1;j < rect.width-1;j++){
// int color = rs[i][j]<<16|gs[i][j]<<8|bs[i][j];
// f.merge(color, 1, Integer::sum);
// }
// }
// f.forEach((k,v) -> {
// if(v >= 1000){
// tr(Integer.toString(k, 16), v);
// }
// });
int minr = 99999, maxr = 0;
int minc = 99999, maxc = 0;
int green = 71<<16|162<<8|26;
int purple = 137<<16|57<<8|140;
int light = 175<<16|203<<8|0;
int white = 255<<16|255<<8|255;
for(int i = 1;i < rect.height-1;i++){
inner:
for(int j = 1;j < rect.width-1;j++){
int color = rs[i][j]<<16|gs[i][j]<<8|bs[i][j];
for(int k = -1;k <= 1;k++){
for(int l = -1;l <= 1;l++){
if(
rs[i][j] != rs[i+k][j+l] ||
gs[i][j] != gs[i+k][j+l] ||
bs[i][j] != bs[i+k][j+l]
){
continue inner;
}
}
}
if(color == green || color == purple || color == light){
minr = Math.min(minr, i);
maxr = Math.max(maxr, i);
minc = Math.min(minc, j);
maxc = Math.max(maxc, j);
}
}
}
int ww = (maxc-minc+5)/8;
int[][] ret = new int[8][8];
for(int i = 0;i < 8;i++){
for(int j = 0;j < 8;j++){
int lr = maxr - (maxc - minc) + ww * i + ww/2;
int lc = minc + ww * j + ww/2;
int color = rs[lr][lc]<<16|gs[lr][lc]<<8|bs[lr][lc];
if(color == light){
ret[7-i][j] = 0;
}else if(color == green){
ret[7-i][j] = 1;
}else if(color == purple){
ret[7-i][j] = 2;
}else if(color == white){
ret[7-i][j] = -1;
}else{
throw new RuntimeException();
}
}
}
for(int[] row : ret){
tr(row);
}
tr(minr, maxr);
tr(minc, maxc);
return ret;
} catch (HeadlessException | AWTException e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
State s = new State(
capture()
);
// State s = new State(
// new int[][]{
// {0,1,1,1,2,0,2,0},
// {-1,-1,0,2,2,2,0,2},
// {-1,-1,-1,2,0,2,2,2},
// {-1,-1,-1,2,0,0,-1,2},
// {-1,-1,-1,-1,1,0,-1,2},
// {-1,-1,-1,-1,-1,2,-1,2},
// {-1,-1,-1,-1,-1,2,-1,2},
// {-1,-1,-1,-1,-1,-1,-1,2}
// }
// );
long S = System.currentTimeMillis();
int LIM = 10;
int depth = 1;
Action res = Action.LEAF;
while(System.currentTimeMillis() - S <= 2000 && depth <= LIM){
tr("depth", depth);
res = dfs(depth, s);
depth++;
}
long G = System.currentTimeMillis();
tr(res);
// s.act(res);
// s.pack();
// tr("\n" + s.toString());
// tr("\n" + s.toStringX());
tr((G-S) + "ms");
}
public static Action dfs(int rem, State s)
{
if(rem == 0)return Action.LEAF;
State[] nss = new State[s.H*s.W/2];
Action[] args = new Action[s.H*s.W/2];
long[] hs = new long[s.H*s.W/2];
int q = 0;
for(int i = 0;i < s.H;i++){
inner:
for(int j = 0;j < s.W;j++){
Action a = new Action(i, j);
State ns = new State(s);
long plus = ns.act(a);
if(plus == -1)continue;
long nh = ns.h();
for(int k = 0;k < q;k++){
if(hs[k] == nh){
if(plus > args[k].plus){
args[k] = a;
nss[k] = ns;
}
continue inner;
}
}
args[q] = a;
hs[q] = nh;
nss[q] = ns;
q++;
}
}
Action best = Action.LEAF;
for(int i = 0;i < q;i++){
Action a = args[i];
if(a.ercol == 0){
nss[i].pack();
Action res = dfs(rem-1, nss[i]);
a.plus += res.plus;
}else{
int NUM = 3;
long sum = 0;
for(int rep = 0;rep < NUM;rep++){
State ns = new State(nss[i]);
ns.pack();
Action res = dfs(rem-1, ns);
sum += res.plus;
}
a.plus += sum/NUM;
}
if(a.plus > best.plus){
best = a;
}
}
return best;
}
static void tr(Object... o) { System.out.println(Arrays.deepToString(o)); }
}
import java.util.Arrays;
import java.util.Random;
public class State {
public int[][] board;
public static final int W = 8, H = 8;
public static final int K = 3;
public Random gen = new Random();
public State(int[][] b)
{
this.board = b;
}
public long h()
{
long h = 0;
for(int i = 0;i < H;i++){
for(int j = 0;j < W;j++){
h = h * 1000000009 + board[i][j];
}
}
return h;
}
public State(State s)
{
this.board = new int[H][];
for(int i = 0;i < H;i++)this.board[i] = Arrays.copyOf(s.board[i], W);
}
static int[] dr = { 1, 0, -1, 0 };
static int[] dc = { 0, 1, 0, -1 };
static int[] q = new int[H*W];
public long act(Action a)
{
if(board[a.r][a.c] == -1)return -1;
int qh = 0;
q[qh++] = a.r<<3|a.c;
int color = board[a.r][a.c];
board[a.r][a.c] = -1;
long dsum = 0;
for(int qt = 0;qt < qh;qt++){
int r = q[qt]>>>3, c = q[qt]&7;
dsum += Math.abs(r-a.r) + Math.abs(c-a.c) + 1;
for(int k = 0;k < 4;k++){
int nr = r + dr[k], nc = c + dc[k];
if(nr >= 0 && nr < H && nc >= 0 && nc < W && board[nr][nc] == color){
board[nr][nc] = -1;
q[qh++] = nr<<3|nc;
}
}
}
if(dsum == 1){
board[a.r][a.c] = color;
return -1;
}
int ercol = 0;
outer:
for(int j = 0;j < W;j++){
for(int i = 0;i < H;i++){
if(board[i][j] != -1)continue outer;
}
ercol++;
}
a.ercol = ercol;
a.plus = ercol*ercol*100 + (dsum-1) * 10;
return a.plus;
}
public int pack()
{
int er = 0;
int c = 0;
for(int j = 0;j < W;j++){
int p = 0;
for(int i = 0;i < H;i++){
if(board[i][j] != -1){
int v = board[i][j];
board[i][j] = -1;
board[p][c] = v;
p++;
}
}
if(p == 0){
er++;
}else{
c++;
}
}
for(int j = c;j < W;j++){
for(int i = 0;i < H;i++){
board[i][j] = gen.nextInt(K);
}
}
return er;
}
public String toString()
{
StringBuilder sb = new StringBuilder();
for(int i = H-1;i >= 0;i--){
for(int j = 0;j < W;j++){
if(board[i][j] == -1){
sb.append('.');
}else{
sb.append((char)('A'+board[i][j]));
}
}
sb.append("\n");
}
return sb.toString();
}
public String toStringX()
{
StringBuilder sb = new StringBuilder();
for(int i = 0;i < H;i++){
sb.append("{");
for(int j = 0;j < W;j++){
if(j > 0)sb.append(",");
sb.append(board[i][j]);
}
sb.append("}");
if(i < H-1)sb.append(",");
sb.append("\n");
}
return sb.toString();
}
static void tr(Object... o) { System.out.println(Arrays.deepToString(o)); }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment