Skip to content

Instantly share code, notes, and snippets.

@catupper
Created August 22, 2019 05:03
Show Gist options
  • Save catupper/d60e7bd3cf3cb35e9b9494aae4dc59d2 to your computer and use it in GitHub Desktop.
Save catupper/d60e7bd3cf3cb35e9b9494aae4dc59d2 to your computer and use it in GitHub Desktop.
pdes
int[][] open_field = new int[4][4];
int[][] tmp_field = new int[4][4];
int[] direction_x = {0, 1, 0, -1};
int[] direction_y = {1, 0, -1, 0};
int[] prob = {0, 9, 1};
boolean AI_play = false;
int[][] num_color = {
{0, 0, 0},
{238, 228, 218},
{237, 224,200},
{242,177,121},
{245,149,99},
{246,124,95},
{246,94,59},
{237,207,114},
{237,204,97},
{237,200,80},
{237,197,63},
{237,194,46},
{138, 228, 218},
{137, 224,200},
{142,177,121},
{145,149,99},
{146,124,95},
{146,94,59},
{137,207,114},
{137,204,97},
{137,200,80},
{137,197,63},
{137,194,46},
};
int turn;
//0 -> Player
//1 -> generate new number
void copy_field(int[][] from, int[][] to) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
to[i][j] = from[i][j];
}
}
}
void setup() {
size(640, 640);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
open_field[i][j] = 0;
}
}
textSize(40);
turn = 1;
}
void draw_field() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
fill(num_color[open_field[i][j]][0], num_color[open_field[i][j]][1], num_color[open_field[i][j]][2]);
rect(i * 160, j * 160, 160, 160);
fill(0);
if (open_field[i][j] != 0) {
text(str(1 << open_field[i][j]), i*160, j * 160 + 80);
}
}
}
}
int calc_score(int[][] field, int x, int y, int val) {
int ret = -123456789;
if (field[x][y] != 0)return ret;
for (int i = 0; i < prob[val]; i++) {
ret = max(ret, int(random(0, 1000000)));
}
return ret;
}
void gen_num(int[][] field) {
int nx = 0, ny = 0, val = 1, max_score = -123456789;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
for (int v = 1; v <= 2; v++) {
int new_score = calc_score(field, i, j, v);
if (new_score > max_score) {
max_score = new_score;
nx = i;
ny = j;
val = v;
}
}
}
}
field[nx][ny] = val;
}
boolean game_over(int[][] field) {
if (valid_move(field, -1, 0))return false;
if (valid_move(field, 1, 0))return false;
if (valid_move(field, 0, -1))return false;
if (valid_move(field, 0, 1))return false;
return true;
}
int field_score(int[][] field) {
int score = 0;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
if (field[i][j] != 0)
score += 1 << field[i][j];
return score;
}
int calc_AI_score(int[][] field) {
return int(random(0, 10000));
}
boolean valid_move(int[][] field, int dx, int dy) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (field[i][j] != 0 && on_field(i + dx, j + dy) && (field[i+dx][j+dy] == 0 || field[i+dx][j+dy] == field[i][j]))return true;
}
}
return false;
}
void AI(int[][] field) {
int nx = 0, ny = 0, max_score = -123456789, tmp_score;
int[][] tmp_field = new int[4][4];
for(int i = 0;i < 4;i++){
int dx = direction_x[i];
int dy = direction_y[i];
if (valid_move(field, dx, dy)) {
copy_field(field, tmp_field);
move(tmp_field, dx, dy);
tmp_score = calc_AI_score(tmp_field);
if (tmp_score > max_score) {
max_score = tmp_score;
nx = dx;
ny = dy;
}
}
}
move(field, nx, ny);
}
void draw() {
draw_field();
if (field_score(open_field)!=0&& game_over(open_field)) {
println(field_score(open_field));
} else if (turn == 1) {
gen_num(open_field);
turn = 1 - turn;
} else if (turn == 0 && AI_play) {
AI(open_field);
turn = 1 - turn;
}
}
boolean on_field(int x, int y) {
return 0 <= x && x < 4 && 0 <= y && y < 4;
}
void push(int[][] field, int dx, int dy) {
for (int trial = 0; trial < 4; trial++) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
int nx = i + dx;
int ny = j + dy;
if (!on_field(nx, ny))continue;
if (field[nx][ny] != 0)continue;
field[nx][ny] = field[i][j];
field[i][j] = 0;
}
}
}
}
void move(int[][] field, int dx, int dy) {
push(field, dx, dy);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (field[i][j] == 0)continue;
int nx = i, ny = j;
while (on_field(nx+dx, ny+dy) && field[nx][ny] == field[nx+dx][ny+dy]) {
nx += dx;
ny += dy;
}
if (nx == i && ny == j)continue;
field[nx][ny]++;
field[nx][ny] *= -1;
field[nx-dx][ny-dy] = 0;
}
}
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
if (field[i][j] < 0)
field[i][j] *= -1;
push(field, dx, dy);
}
void keyPressed() {
if (AI_play)return;
if (turn != 0)return;
if (key == CODED) {
if (keyCode == UP && valid_move(open_field, 0, -1)) {
move(open_field, 0, -1);
turn = 1 - turn;
} else if (keyCode == DOWN && valid_move(open_field, 0, 1)) {
move(open_field, 0, 1);
turn = 1 - turn;
} else if (keyCode == LEFT && valid_move(open_field, -1, 0)) {
move(open_field, -1, 0);
turn = 1 - turn;
} else if (keyCode == RIGHT && valid_move(open_field, 1, 0)) {
move(open_field, 1, 0);
turn = 1 - turn;
}
}
}
int[][] open_field = new int[8][8];
int[][] tmp_field = new int[8][8];
int turn;
int[] token_color = {0, 0, 255};
int[] direction_x = {0, 1, 1, 1, 0, -1, -1, -1};
int[] direction_y = {1, 1, 0, -1, -1, -1, 0, 1};
void copy_field(int[][] from, int[][] to) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
to[i][j] = from[i][j];
}
}
}
void setup() {
size(640, 750);
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
open_field[i][j] = 0;
}
}
open_field[3][3] = 1;
open_field[3][4] = 2;
open_field[4][3] = 2;
open_field[4][4] = 1;
turn = 1;
}
void draw_field() {
background(0, 255, 0);
for (int i = 0; i <= 8; i++) {
line(80 * i, 0, 80 * i, 640);
line(0, 80 * i, 640, 80 * i);
}
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (open_field[i][j] != 0) {
fill(token_color[open_field[i][j]]);
ellipse(i * 80 + 40, j * 80 + 40, 70, 70);
}
}
}
fill(token_color[turn]);
ellipse(320, 680, 70, 70);
}
boolean on_field(int x, int y) {
return 0 <= x && x < 8 && 0 <= y && y < 8;
}
boolean available(int[][] field, int x, int y, int turn) {
if (field[x][y] != 0)return false;
for (int i = 0; i < 8; i++) {
int dx = direction_x[i];
int dy = direction_y[i];
int edgex = x + dx;
int edgey = y + dy;
int flip_cnt = 0;
while (on_field(edgex, edgey) && field[edgex][edgey] == 3 - turn) {
edgex += dx;
edgey += dy;
flip_cnt += 1;
}
if (on_field(edgex, edgey) && field[edgex][edgey] == turn && flip_cnt > 0)return true;
}
return false;
}
void flip(int[][] field, int x, int y, int turn) {
field[x][y] = turn;
for (int i = 0; i < 8; i++) {
int dx = direction_x[i];
int dy = direction_y[i];
int edgex = x + dx;
int edgey = y + dy;
while (on_field(edgex, edgey) && field[edgex][edgey] == 3 - turn) {
edgex += dx;
edgey += dy;
}
if (on_field(edgex, edgey) && field[edgex][edgey] == turn) {
while (edgex != x || edgey != y) {
field[edgex][edgey] = turn;
edgex -= dx;
edgey -= dy;
}
}
}
}
boolean pass(int[][] field, int turn) {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (available(field, i, j, turn))return false;
}
}
return true;
}
int[] result(int[][] field) {
int[] cnt = {0, 0, 0};
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
cnt[field[i][j]] += 1;
}
}
return cnt;
}
int calc_score(int[][] field, int x, int y, int turn){
if(!available(field, x, y, turn))return -123456789;
return int(random(0, 1000));
}
void AI(int[][] field, int turn) {
int nx = 0, ny = 0, max_score = -123456789;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
int new_score = calc_score(field, i, j, turn);
if (new_score > max_score) {
max_score = new_score;
nx = i;
ny = j;
}
}
}
flip(open_field, nx, ny, turn);
}
void draw() {
draw_field();
if(pass(open_field,turn)){
turn = 3 - turn;
if(pass(open_field, turn)){
println(result(open_field));
turn = 3 - turn;
return;
}
}
if (turn == 2) {
AI(open_field, turn);
turn = 3 - turn;
}
}
void mousePressed() {
if (turn != 1)return;
int x = mouseX / 80;
int y = mouseY / 80;
if (available(open_field, x, y, turn)) {
flip(open_field, x, y, turn);
turn = 3 - turn;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment