import java.applet.*; import java.awt.*; /* recursive call -> for statement */ public class Oth3D extends Applet { static final int KOMA_O = 2; static final int KOMA_N = 3; static final int KOMA_W = 0; static final int KOMA_B = 1; static final int NO_PLACE = -100; static final int ST = 1; static final int ED = 6; static final int DD = 40; static final int MD = 140; Rectangle tr = new Rectangle(65 * 8, 20 * 16, 16, 16), tl = new Rectangle(55 * 8, 20 * 16, 16, 16), tu = new Rectangle(60 * 8, 18 * 16, 16, 16), td = new Rectangle(60 * 8, 22 * 16, 16, 16), cr = new Rectangle(65 * 8, 12 * 16, 16, 16), cl = new Rectangle(55 * 8, 12 * 16, 16, 16), cu = new Rectangle(60 * 8, 10 * 16, 16, 16), cd = new Rectangle(60 * 8, 14 * 16, 16, 16), cf = new Rectangle(56 * 8 + 4, 13 * 16 + 4, 20, 20), cb = new Rectangle(63 * 8, 10 * 16 + 8, 20, 20), place = new Rectangle(70 * 8, 10 * 16, 42, 20), pass = new Rectangle(70 * 8, 13 * 16, 42, 20), res = new Rectangle(70 * 8, 16 * 16, 42, 20); double alpha, theta; int board[]; int advantage[]; int ix[], iy[]; int kaku1, kaku2, hankei; int cs_x, cs_y, cs_z; int sx, sy, sz; int n_white, n_black; int junban, player, taisen; boolean game_end; public void init() { board = new int[8 * 8 * 8]; advantage = new int[8 * 8 * 8]; ix = new int[8 * 8]; iy = new int[8 * 8 * 8]; setBackground(Color.black); init_game(); requestFocus(); } void init_param() { kaku1 = 5; kaku2 = 10; hankei = 5; cs_x = cs_y = cs_z = ST; game_end = false; taisen = 0; junban = player = KOMA_W; } public void destroy() { board = null; advantage = null; ix = null; iy = null; } void xycalc() { int i, j, k; double cva, sva, cvt, svt; double x, y, z, wx, wy; cva = Math.cos(alpha); sva = Math.sin(alpha); cvt = Math.cos(theta); svt = Math.sin(theta); for (i = ST; i <= ED; i++) { x = (double)(i * DD - MD); for (j = ST; j <= ED; j++) { y = (double)(j * DD - MD); wx = x * cvt - y * svt; ix[i * 8 + j] = 200 + (int)wx; for (k = ST; k <= ED; k++) { z = (double)(k * DD - MD); wy = z * cva - (x * svt + y * cvt) * sva; iy[i * 64 + j * 8 + k] = 200 - (int)wy; } } } } boolean do_reverse(int x, int y, int z, int i, int j, int k) { boolean d; d = false; if (board[(x + i)*64 + (y + j)*8 + z + k] == junban) d = true; else if (board[(x + i)*64 + (y + j)*8 + z + k] == (1 - junban)) d = do_reverse(x + i, y + j, z + k, i, j, k); if (d) board[x * 64 + y * 8 + z] = junban; return d; } boolean reverse(int x, int y, int z) { int i, j, k, b; boolean r; r = false; if (board[x * 64 + y * 8 + z] != KOMA_N) return false; for (i = -1; i <= 1; i++) for (j = -1; j <= 1; j++) for (k = -1; k <= 1; k++) if (i != 0 || j != 0 || k != 0) if (board[(x + i)*64 + (y + j)*8 + z + k] == (1 - junban)) if (do_reverse(x + i, y + j, z + k, i, j, k)) { board[x * 64 + y * 8 + z] = junban; ch_adv(x, y, z); r = true; } return r; } int do_count_rev(int x, int y, int z, int i, int j, int k) { int r; if (board[(x + i)*64 + (y + j)*8 + z + k] == junban) return 1; else if (board[(x + i)*64 + (y + j)*8 + z + k] == (1 - junban)) { r = do_count_rev(x + i, y + j, z + k, i, j, k); if (r > 0) return (r + 1); } return 0; } int count_rev(int x, int y, int z) { int i, j, k, s; if (board[x * 64 + y * 8 + z] != KOMA_N) return 0; s = 0; for (i = -1; i <= 1; i++) for (j = -1; j <= 1; j++) for (k = -1; k <= 1; k++) if (i != 0 || j != 0 || k != 0) if (board[(x + i)*64 + (y + j)*8 + z + k] == (1 - junban)) s += do_count_rev(x + i, y + j, z + k, i, j, k); return s; } void init_adv() { int i, j, k; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) for (k = 0; k < 8; k++) { if (i == ST || i == ED) { if (j == ST || j == ED) { if (k == ST || k == ED) { advantage[i * 64 + j * 8 + k] = 100; } else { advantage[i * 64 + j * 8 + k] = 3; } } else { if (k == ST || k == ED) { advantage[i * 64 + j * 8 + k] = 3; } else { advantage[i * 64 + j * 8 + k] = 1; } } } else { if (j == ST || j == ED) { if (k == ST || k == ED) { advantage[i * 64 + j * 8 + k] = 3; } else { advantage[i * 64 + j * 8 + k] = 1; } } else { if (k == ST || k == ED) { advantage[i * 64 + j * 8 + k] = 1; } else { advantage[i * 64 + j * 8 + k] = 0; } } } } for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) for (k =0; k < 2; k++) if (i != 0 || j != 0 || k != 0) { advantage[(ST + i)*64 + (ST + j)*8 + ST + k] = -5; advantage[(ST + i)*64 + (ST + j)*8 + ED - k] = -5; advantage[(ST + i)*64 + (ED - j)*8 + ST + k] = -5; advantage[(ST + i)*64 + (ED - j)*8 + ED - k] = -5; advantage[(ED - i)*64 + (ST + j)*8 + ST + k] = -5; advantage[(ED - i)*64 + (ST + j)*8 + ED - k] = -5; advantage[(ED - i)*64 + (ED - j)*8 + ST + k] = -5; advantage[(ED - i)*64 + (ED - j)*8 + ED - k] = -5; } } void ch_adv(int x, int y, int z) { int i, j, k; if ((x == ST || x == ED) && (y == ST || y == ED) && (z == ST || z == ED)) for (i = -1; i <= 1; i++) for (j = -1; j <= 1; j++) for (k = -1; k <= 1; k++) if (i == 0) { if (j == 0 || k == 0) { advantage[(x + i)*64 + (y + j)*8 + z + k] = 3; } else { advantage[(x + i)*64 + (y + j)*8 + z + k] = 1; } } else if (j == 0) { if (k == 0) { advantage[(x + i)*64 + (y + j)*8 + z + k] = 3; } else { advantage[(x + i)*64 + (y + j)*8 + z + k] = 1; } } else if (k == 0) { advantage[(x + i)*64 + (y + j)*8 + z + k] = 1; } else { advantage[(x + i)*64 + (y + j)*8 + z + k] = 0; } } void init_board() { int i, j, k; for (i = 0; i < 8; i++) for (j = 0; j < 8; j++) for (k = 0; k < 8; k++) if (i < ST || j < ST || k < ST || i > ED || j > ED || k > ED) board[i * 64 + j * 8 + k] = KOMA_O; else board[i * 64 + j * 8 + k] = KOMA_N; board[3 * 64 + 3 * 8 + 3] = board[4 * 64 + 4 * 8 + 3] = board[3 * 64 + 4 * 8 + 4] = board[4 * 64 + 3 * 8 + 4] = KOMA_W; board[3 * 64 + 3 * 8 + 4] = board[4 * 64 + 4 * 8 + 4] = board[3 * 64 + 4 * 8 + 3] = board[4 * 64 + 3 * 8 + 3] = KOMA_B; } int select() { int i, j, k, v, no, w; v = NO_PLACE; no = 1; for (i = ST; i <= ED; i++) for (j = ST; j <= ED; j++) for (k = ST; k <= ED; k++) if ((w = count_rev(i, j, k)) > 0) { w += advantage[i * 64 + j * 8 + k]; if (w > v) { v = w; sx = i; sy = j; sz = k; no = 1; } else if (w == v) { no++; if (Math.random() * (double)no < 1.0) { sx = i; sy = j; sz = k; } } } return v; } void com_play() { int x, y, z; x = y = z = 0; if (select() > NO_PLACE) { reverse(sx, sy, sz); } else { junban = 1 - junban; if (select() == NO_PLACE) { game_end = true; } junban = 1 - junban; } } public void paint(Graphics g) { int i, j, k; Color fill, draw; g.clearRect(0, 0, 640, 400); theta = Math.PI * (double)kaku1 / 180.0; alpha = Math.PI * (double)kaku2 / 180.0; xycalc(); n_white = n_black = 0; for (k = ST; k <= ED; k++) { for (j = ST; j <= ED; j++) { g.setColor(Color.blue); g.drawLine(ix[ST*8+j], iy[ST*64+j*8+k], ix[ED*8+j], iy[ED*64+j*8+k]); for (i = ST; i <= ED; i++) { g.setColor(Color.blue); if (k < 6) { g.drawLine(ix[i*8+j], iy[i*64+j*8+k], ix[i*8+j], iy[i*64+j*8+k+1]); } if (j < 6) { g.drawLine(ix[i*8+j], iy[i*64+j*8+k], ix[i*8+j+1], iy[i*64+(j+1)*8+k]); } if (board[i * 64 + j * 8 + k] == KOMA_W) { n_white++; fill = draw = Color.white; } else if (board[i * 64 + j * 8 + k] == KOMA_B) { n_black++; fill = draw = Color.red; } else { fill = Color.black; draw = Color.green; } if (i == cs_x && j == cs_y && k == cs_z) { draw = Color.yellow; if (board[i*64+j*8+k] == KOMA_N) fill = Color.yellow; if (board[i*64+j*8+k] == KOMA_W) draw = Color.magenta; } g.setColor(fill); g.fillArc(ix[i*8+j] - hankei, iy[i*64+j*8+k] - hankei, 2 * hankei, 2 * hankei, 0, 360); g.setColor(draw); g.drawArc(ix[i*8+j] - hankei, iy[i*64+j*8+k] - hankei, 2 * hankei, 2 * hankei, 0, 360); } } } g.setColor(Color.white); g.drawString("WHITE", 58 * 8, 3 * 16); g.drawString("RED", 58 * 8, 5 * 16); g.drawString(": " + Integer.toString(n_white, 10), 64 * 8, 3 * 16); g.drawString(": " + Integer.toString(n_black, 10), 64 * 8, 5 * 16); g.drawString(">>", 55 * 8, ((junban == KOMA_W) ? 3 : 5) * 16); if (game_end || n_white + n_black == 6 * 6 * 6) { if (n_white == n_black) g.drawString("Draw Game !", 60 * 8, 7 * 16); else if (n_white > n_black) if (player == KOMA_W) { if (taisen == 0) g.drawString("You Win !!", 60 * 8, 7 * 16); else g.drawString("White Win !!", 60 * 8, 7 * 16); } else { if (taisen == 0) g.drawString("You Lose !!", 60 * 8, 7 * 16); else g.drawString("Red Win !!", 60 * 8, 7 * 16); } } int xp[] = new int[3]; int yp[] = new int[3]; g.setColor(Color.cyan); g.drawString("VIEW", 59 * 8 + 2, 21 * 16 - 2); xp[0] = tr.x; yp[0] = tr.y; xp[1] = tr.x; yp[1] = tr.y + tr.height; xp[2] = tr.x + tr.width; yp[2] = tr.y + tr.height / 2; g.fillPolygon(xp, yp, 3); xp[0] = tl.x + tl.width; yp[0] = tl.y; xp[1] = tl.x + tl.width; yp[1] = tl.y + tl.height; xp[2] = tl.x; yp[2] = tl.y + tl.height / 2; g.fillPolygon(xp, yp, 3); xp[0] = tu.x + tu.width / 2; yp[0] = tu.y; xp[1] = tu.x; yp[1] = tu.y + tu.height; xp[2] = tu.x + tu.width; yp[2] = tu.y + tu.height; g.fillPolygon(xp, yp, 3); xp[0] = td.x; yp[0] = td.y; xp[1] = td.x + td.width; yp[1] = td.y; xp[2] = tu.x + td.width / 2; yp[2] = td.y + td.height; g.fillPolygon(xp, yp, 3); g.drawString("MOVE", 59 * 8 - 2, 13 * 16 - 2); xp[0] = cr.x; yp[0] = cr.y; xp[1] = cr.x; yp[1] = cr.y + cr.height; xp[2] = cr.x + cr.width; yp[2] = cr.y + tr.height / 2; g.fillPolygon(xp, yp, 3); xp[0] = cl.x + tl.width; yp[0] = cl.y; xp[1] = cl.x + tl.width; yp[1] = cl.y + cl.height; xp[2] = cl.x; yp[2] = cl.y + cl.height / 2; g.fillPolygon(xp, yp, 3); xp[0] = cu.x + cu.width / 2; yp[0] = cu.y; xp[1] = cu.x; yp[1] = cu.y + cu.height; xp[2] = cu.x + tu.width; yp[2] = cu.y + cu.height; g.fillPolygon(xp, yp, 3); xp[0] = cd.x; yp[0] = cd.y; xp[1] = cd.x + cd.width; yp[1] = cd.y; xp[2] = cd.x + cd.width / 2; yp[2] = cd.y + cd.height; g.fillPolygon(xp, yp, 3); xp[0] = cf.x; yp[0] = cf.y + cf.height; xp[1] = cf.x + cf.width / 2; yp[1] = cf.y; xp[2] = cf.x + cf.width; yp[2] = cf.y + cf.height / 2; g.fillPolygon(xp, yp, 3); xp[0] = cb.x + cb.width; yp[0] = cb.y; xp[1] = cb.x; yp[1] = cb.y + cb.height / 2; xp[2] = cb.x + cb.width / 2; yp[2] = cb.y + cb.height; g.fillPolygon(xp, yp, 3); g.drawRect(place.x, place.y, place.width, place.height); g.drawString("PLACE", place.x + 2, place.y + place.height - 3); g.drawRect(pass.x, pass.y, pass.width, pass.height); g.drawString("PASS", pass.x + 7, pass.y + pass.height - 3); g.drawRect(res.x, res.y, res.width, res.height); g.drawString("RESET", res.x + 2, res.y + res.height - 3); xp = null; yp = null; } public boolean keyDown(Event ev, int key) { boolean changed = false; switch (key) { case 'x': case 'X': turn_down(); changed = true; break; case 's': case 'S': turn_up(); changed = true; break; case 'z': case 'Z': turn_left(); changed = true; break; case 'c': case 'C': turn_right(); changed = true; break; case '+': hankei += 1; if (hankei > 18) hankei = 18; changed = true; break; case '-': hankei -= 1; if (hankei < 3) hankei = 3; changed = true; break; case '4': cs_left(); changed = true; break; case '6': cs_right(); changed = true; break; case '8': cs_up(); changed = true; break; case '2': cs_down(); changed = true; break; case '5': cs_back(); changed = true; break; case ',': cs_front(); changed = true; break; case 'q': case 'Q': view1(); changed = true; break; case 'w': case 'W': view2(); changed = true; break; case 'e': case 'E': view3(); changed = true; break; case 'r': case 'R': if (n_black == 4 && n_white == 4) { player = 1 - player; } else { play(getCodeBase(), "tone0.au"); } /* do not repaint (repainted in com_move()) */ break; case '\r': case ' ': do_place(); changed = true; break; case 'p': case 'P': do_pass(); changed = true; break; case 't': case 'T': if (n_black == 4 && n_white == 4) { taisen = 1 - taisen; } else { play(getCodeBase(), "tone0.au"); play(getCodeBase(), "tone0.au"); } /* do not repaint */ break; case '\033': init_game(); changed = true; break; } if (changed) repaint(); com_move(); return true; } public boolean mouseUp(Event ev, int mx, int my) { boolean changed = false; if (tr.inside(mx, my)) { turn_right(); changed = true; } else if (tl.inside(mx, my)) { turn_left(); changed = true; } else if (tu.inside(mx, my)) { turn_up(); changed = true; } else if (td.inside(mx, my)) { turn_down(); changed = true; } else if (cr.inside(mx,my)) { cs_right(); changed = true; } else if (cl.inside(mx,my)) { cs_left(); changed = true; } else if (cu.inside(mx,my)) { cs_up(); changed = true; } else if (cd.inside(mx,my)) { cs_down(); changed = true; } else if (cf.inside(mx,my)) { cs_front(); changed = true; } else if (cb.inside(mx,my)) { cs_back(); changed = true; } else if (pass.inside(mx,my)) { do_pass(); changed = true; } else if (res.inside(mx,my)) { init_game(); changed = true; } else if (place.inside(mx,my)) { do_place(); changed = true; } if (changed) repaint(); com_move(); return true; } void com_move() { if (taisen == 0 && junban != player) { com_play(); junban = 1 - junban; repaint(); } } void do_place() { if (reverse(cs_x, cs_y, cs_z)) junban = 1 - junban; else play(getCodeBase(), "tone0.au"); } void do_pass() { if (select() > NO_PLACE) { play(getCodeBase(), "tone0.au"); cs_x = sx; cs_y = sy; cs_z = sz; } else { junban = 1 - junban; } } void cs_right() { if (kaku1 > 45) { cs_y -= 1; if (cs_y < ST) cs_y = ST; } else { cs_x += 1; if (cs_x > ED) cs_x = ED; } } void cs_left() { if (kaku1 > 45) { cs_y += 1; if (cs_y > ED) cs_y = ED; } else { cs_x -= 1; if (cs_x < ST) cs_x = ST; } } void cs_up() { if (kaku2 > 45) { if (kaku1 > 45) { cs_x -= 1; if (cs_x < ST) cs_x = ST; } else { cs_y -= 1; if (cs_y < ST) cs_y = ST; } } else { cs_z += 1; if (cs_z > ED) cs_z = ED; } } void cs_down() { if (kaku2 > 45) { if (kaku1 > 45) { cs_x += 1; if (cs_x > ED) cs_x = ED; } else { cs_y += 1; if (cs_y > ED) cs_y = ED; } } else { cs_z -= 1; if (cs_z < ST) cs_z = ST; } } void cs_front() { if (kaku2 > 45) { cs_z += 1; if (cs_z > ED) cs_z = ED; } else if (kaku1 > 45) { cs_x += 1; if (cs_x > ED) cs_x = ED; } else { cs_y += 1; if (cs_y > ED) cs_y = ED; } } void cs_back() { if (kaku2 > 45) { cs_z -= 1; if (cs_z < ST) cs_z = ST; } else if (kaku1 > 45) { cs_x -= 1; if (cs_x < ST) cs_x = ST; } else { cs_y -= 1; if (cs_y < ST) cs_y = ST; } } void turn_right() { kaku1 += 5; if (kaku1 > 90) kaku1 = 90; } void turn_left() { kaku1 -= 5; if (kaku1 < 0) kaku1 = 0; } void turn_up() { kaku2 += 5; if (kaku2 > 90) kaku2 = 90; } void turn_down() { kaku2 -= 5; if (kaku2 < 0) kaku2 = 0; } void view1() { kaku1 = 5; kaku2 = 10; } void view2() { kaku1 = 15; kaku2 = 75; } void view3() { kaku1 = 85; kaku2 = 10; } void init_game() { init_board(); init_adv(); init_param(); } }