import java.applet.Applet; import java.awt.*; import java.util.*; public class Othello extends Applet implements Runnable { static final int BOXWID = 64; static final int PLAYER = 0; static final int COMPUTER = 1; MediaTracker mt; Image[] blackStone = new Image[8]; Image[] whiteStone = new Image[8]; Image offImage; Graphics offScreen; Graphics screen; Thread thread; int cursorX, cursorY; boolean[][] rotate = new boolean[8][8]; boolean[][] lastRotate = new boolean[8][8]; int count = 0; Dimension mySize; ControlPanel control; Kyokumen current; int[] player = new int[2]; Judge judge; int minX, minY, maxX, maxY; Player dummy; public void init() { mySize = size(); screen = getGraphics(); offImage = createImage(mySize.width, mySize.height); offScreen = offImage.getGraphics(); current = new Kyokumen(); mt = new MediaTracker(this); for (int n = 0; n < 8; n++) { whiteStone[n] = getImage(getCodeBase(), "image/25_0"+(n+1)+".GIF"); mt.addImage(whiteStone[n], 0); blackStone[n] = getImage(getCodeBase(), "image/26_0"+(n+1)+".GIF"); mt.addImage(blackStone[n], 0); } try { mt.waitForID(0); } catch (InterruptedException e) { e.printStackTrace(); } // only for loading dummy = new ComputerPlayer4(Kyokumen.BLACK); } synchronized void newGame(Player player1, Player player2) { if (judge.onGame() == false) { control.disable(); current.init(); updateOffScreen(); repaint(); control.setScore(current.countStone(Kyokumen.BLACK), current.countStone(Kyokumen.WHITE)); judge.newGame(player1, player2); } } void endGame() { control.enable(); control.toFront(); } public void paint(Graphics g) { g.drawImage(offImage, 0, 0, null); } public synchronized void update(Graphics g) { int state; if (thread != null) { for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { if ((state = current.getState(x, y)) != Kyokumen.NONE) { if (rotate[x][y]) { if (state == Kyokumen.BLACK) { offScreen.drawImage(blackStone[count], x*BOXWID, y*BOXWID, null); } else { offScreen.drawImage(whiteStone[count], x*BOXWID, y*BOXWID, null); } lastRotate[x][y] = true; } else if (lastRotate[x][y]) { if (state == Kyokumen.BLACK) { offScreen.drawImage(blackStone[0], x*BOXWID, y*BOXWID, null); } else { offScreen.drawImage(whiteStone[0], x*BOXWID, y*BOXWID, null); } lastRotate[x][y] = false; } } } } } paint(g); } public void start() { current.init(); cursorX = cursorY = -1; updateOffScreen(); repaint(); control = new ControlPanel(this, blackStone[0], whiteStone[0]); control.setScore(current.countStone(Kyokumen.BLACK), current.countStone(Kyokumen.WHITE)); control.show(); judge = new Judge(this, control, current); judge.start(); } public void stop() { control.dispose(); control = null; if (judge != null) { judge.stop(); } judge = null; if (thread != null) { thread.stop(); } thread = null; } synchronized void updateOffScreen() { offScreen.setColor(Color.black); offScreen.fillRect(0, 0, mySize.width, mySize.height); for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { if (current.getState(x, y) != Kyokumen.NONE) { if (current.getState(x, y) == Kyokumen.BLACK) { offScreen.drawImage(blackStone[0], x*BOXWID, y*BOXWID, null); } else { offScreen.drawImage(whiteStone[0], x*BOXWID, y*BOXWID, null); } } else if (x == cursorX && y == cursorY && judge.getThinkingPlayer() instanceof HumanPlayer) { offScreen.setColor(Color.darkGray); offScreen.fill3DRect(cursorX*BOXWID, cursorY*BOXWID, BOXWID, BOXWID, true); } } } } private void checkRotateRange() { minX = minY = 7; maxX = maxY = 0; for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { if (rotate[x][y]) { if (x < minX) minX = x; if (y < minY) minY = y; if (x > maxX) maxX = x; if (y > maxY) maxY = y; } } } } public void run() { checkRotateRange(); count = 0; if (judge.getThinkingPlayer() instanceof HumanPlayer) { while (true) { if (++count >= 8) count = 0; repaint(minX*BOXWID, minY*BOXWID, (maxX-minX+1)*BOXWID, (maxY-minY+1)*BOXWID); try { thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } else { for (int i = 0; i < 8; i++) { count = (i < 7)?(i + 1):0; repaint(minX*BOXWID, minY*BOXWID, (maxX-minX+1)*BOXWID, (maxY-minY+1)*BOXWID); try { thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized(this) { notify(); } thread = null; } } void rotateStone(int x, int y) { offScreen.setColor(Color.darkGray); offScreen.fill3DRect(x*BOXWID, y*BOXWID, BOXWID, BOXWID, true); screen.drawImage(offImage, 0, 0, null); rotate = current.getReversible(x, y); if (thread == null) { thread = new Thread(this); thread.start(); } synchronized(this) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public boolean mouseDown(Event evt, int x, int y) { Player player = judge.getThinkingPlayer(); if (judge.onGame() && player instanceof HumanPlayer) { int wx = x/BOXWID; int wy = y/BOXWID; if (current.isPosibleToPlace(wx, wy)) { ((HumanPlayer)player).decide(new Point(wx, wy)); if (thread != null) { thread.stop(); thread = null; } } } return true; } public synchronized boolean mouseMove(Event evt, int x, int y) { int wx = x/BOXWID; int wy = y/BOXWID; if (judge.getThinkingPlayer() instanceof HumanPlayer) { if (wx != cursorX || wy != cursorY) { if (current.getState(cursorX, cursorY) == Kyokumen.NONE) { offScreen.setColor(Color.black); offScreen.fillRect(cursorX*BOXWID, cursorY*BOXWID, BOXWID, BOXWID); } if (current.getState(wx, wy) == Kyokumen.NONE) { offScreen.setColor(Color.darkGray); offScreen.fill3DRect(wx*BOXWID, wy*BOXWID, BOXWID, BOXWID, true); } screen.drawImage(offImage, 0, 0, null); count = 0; cursorX = wx; cursorY = wy; if (thread != null) { if (current.isPosibleToPlace(wx, wy)) { rotate = current.getReversible(wx, wy); checkRotateRange(); } else { thread.stop(); thread = null; updateOffScreen(); repaint(); } } else if (current.isPosibleToPlace(wx, wy)) { rotate = current.getReversible(wx, wy); thread = new Thread(this); thread.start(); } } } else { cursorX = wx; cursorY = wy; } return true; } public synchronized boolean mouseExit(Event evt, int x, int y) { if (judge.getThinkingPlayer() instanceof HumanPlayer) { if (thread != null) { thread.stop(); thread = null; } if (current.getState(cursorX, cursorY) == Kyokumen.NONE) { offScreen.setColor(Color.black); offScreen.fillRect(cursorX*BOXWID, cursorY*BOXWID, BOXWID, BOXWID); } screen.drawImage(offImage, 0, 0, null); } cursorX = cursorY = -1; return true; } }