import java.awt.*; import java.awt.event.*; class Reversi { final int GRIDSIZE = 40; final int STONESIZE = 32; final String turnBlackDisc = "Black"; final String turnWhiteDisc = "White"; final String playerDisc[] = {"Human", "Computer Level 0", "Computer Level 1", "Computer Level 2", "Computer Level 3", "Computer Level 4"}; private int turn; private int playerBlack = 0; private int playerWhite = 3; private Image img; private ReversiStones rs; private final Frame f = new Frame("Reversi"); private final MenuBar mb = new MenuBar(); private final Menu m = new Menu("Game"); private final MenuItem miStart = new MenuItem("Start ..."); private final MenuItem miFinish = new MenuItem("Finish"); private final Canvas c = new Canvas() { public void paint(Graphics g) { Dimension d = getSize(); g.setColor(new Color(0.25f, 0.5f ,0.25f)); g.fillRect(0, 0, d.width, d.height); if (img == null) updateImage(); g.drawImage(img, 0, 0, 400, 400, this); } }; private final Label labelStatus = new Label("Welcome."); private void updateImage() { img = f.createImage(GRIDSIZE * 10, GRIDSIZE * 10); Graphics g = img.getGraphics(); g.setColor(new Color(0.25f, 0.5f ,0.25f)); g.fillRect(0, 0, 400, 400); g.setColor(new Color(0.75f, 0.5f, 0.25f)); for (int i = 1; i <= 9; i++) { g.drawLine(GRIDSIZE, GRIDSIZE * i, GRIDSIZE * 9, GRIDSIZE * i); g.drawLine(GRIDSIZE * i, GRIDSIZE, GRIDSIZE * i, GRIDSIZE * 9); } for (int x = 1; x < 9; x++) { for (int y = 1; y < 9; y++) { if (rs != null && rs.get(x, y) != 0) { g.setColor(Color.GRAY); g.fillOval(GRIDSIZE * x + (GRIDSIZE - STONESIZE) / 2 + 1, GRIDSIZE * y + (GRIDSIZE - STONESIZE) / 2 + 1, STONESIZE, STONESIZE); g.setColor(rs.get(x, y) == 1 ? Color.BLACK : Color.WHITE); g.fillOval(GRIDSIZE * x + (GRIDSIZE - STONESIZE) / 2, GRIDSIZE * y + (GRIDSIZE - STONESIZE) / 2, STONESIZE, STONESIZE); } } } } private int computeGrade(ReversiStones basers, int x, int y, int defaultgrade, int depth) { ReversiStones rs = new ReversiStones(basers); if (rs.put(x, y)) { if (depth != 0) { int testgrade; int bestgrade = - 1024 * rs.turn(); for (x = 1; x < 9; x++) { for (y = 1; y < 9; y++) { if (rs.test(x, y)) { testgrade = computeGrade(rs, x, y, bestgrade, depth - 1); if ((testgrade - bestgrade) * rs.turn() > 0) { if (basers != null && (testgrade - defaultgrade) * basers.turn() < 0) { return testgrade; } bestgrade = testgrade; } } } } return bestgrade; } else { int grade = 0; for (x = 1; x < 9; x++) { for (y = 1; y < 9; y++) { if ((x == 1 || x == 8) & (y == 1 || y == 8)) { if (rs.get(x, y) == 0) { if (rs.test(x, y, rs.turn())) grade += rs.turn() * 64; else if (rs.test(x, y, (byte)(rs.turn() * -1))) grade -= rs.turn() * 64; else if (rs.get(x == 1 ? 2 : 7, y == 1 ? 2 : 7) == rs.turn()) grade -= rs.turn() * 64; else if (rs.get(x == 1 ? 2 : 7, y == 1 ? 2 : 7) == (byte)(rs.turn() * -1)) grade += rs.turn() * 64; } else if (rs.get(x, y) == rs.turn()) grade += rs.turn() * 64; else grade -= rs.turn() * 64; } if (rs.test(x, y, rs.turn())) grade += rs.turn(); else if (rs.test(x, y, (byte)(rs.turn() * -1))) grade -= rs.turn(); } } return grade; } } int grade = 0; for (x = 1; x < 9; x++) { for (y = 1; y < 9; y++) { if (rs.get(x, y) == rs.turn()) grade += rs.turn(); else if (rs.get(x, y) != 0) grade -= rs.turn(); } } if (grade > 0) grade += 512; else if (grade < 0) grade -= 512; return grade; } private void advanceStateByHuman() { c.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { int x = e.getX() / GRIDSIZE; int y = e.getY() / GRIDSIZE; if (rs.test(x, y)) { c.removeMouseListener(this); advanceState(x, y); } } }); return; } private void advanceStateByComputer(final int level) { (new Thread() { public void run() { int xc = -1, yc = -1; int testgrade; int bestgrade = -1024 * rs.turn(); int depth = level; if (rs.count() >= 63 - level * 3) depth = level * 3; for (int x = 1; x < 9; x++) { for (int y = 1; y < 9; y++) { if (rs.test(x, y)) { if (((testgrade = computeGrade(rs, x, y, bestgrade, depth)) - bestgrade) * rs.turn() > 0) { bestgrade = testgrade; xc = x; yc = y; } } } } advanceState(xc, yc); } }).start(); } private void advanceState() { updateImage(); c.repaint(); int player = turn == 1 ? playerBlack : playerWhite; int depth; switch (player) { case 0: advanceStateByHuman(); return; case 1: advanceStateByComputer(0); return; case 2: advanceStateByComputer(1); return; case 3: advanceStateByComputer(2); return; case 4: advanceStateByComputer(3); return; case 5: advanceStateByComputer(4); return; } } private void advanceState(int x, int y) { if (rs.put(x, y)) { turn *= -1; if (turn != rs.turn()) { labelStatus.setText((turn == 1 ? turnBlackDisc : turnWhiteDisc) + " : Pass"); turn *= -1; try { Thread.sleep(1000); } catch (InterruptedException e) { } } labelStatus.setText((turn == 1 ? turnBlackDisc : turnWhiteDisc) + ": "); advanceState(); } else { updateImage(); c.repaint(); int stoneBlack = 0; int stoneWhite = 0; for (x = 1; x < 9; x++) { for (y = 1; y < 9; y++) { if (rs.get(x, y) == 1) { stoneBlack++; } else if (rs.get(x, y) != 0) { stoneWhite++; } } } final Dialog dialog = new Dialog(f, "Game Over", true); final Button button = new Button("OK"); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dialog.dispose(); } }); if (stoneBlack > stoneWhite) dialog.add(new Label(turnBlackDisc + " defeated " + turnWhiteDisc + " by " + (stoneBlack - stoneWhite) + " stones.")); else if (stoneBlack != stoneWhite) dialog.add(new Label(turnWhiteDisc + " defeated " + turnBlackDisc + " by " + (stoneWhite - stoneBlack) + " stones.")); else dialog.add(new Label("draw.")); dialog.add(button, BorderLayout.SOUTH); dialog.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dialog.dispose(); } }); dialog.setSize(320, 160); dialog.show(); miStart.setEnabled(true); } } Reversi() { miStart.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ final Dialog dialog = new Dialog(f, "Game Player", true); final Panel panelParameter = new Panel(); final Panel panelBlack = new Panel(); final List listBlack = new List(8); final Panel panelWhite = new Panel(); final List listWhite = new List(8); final Panel panelCommand = new Panel(); final Button buttonOk = new Button("OK"); final Button buttonCancel = new Button("Cancel"); panelParameter.setLayout(new GridLayout(1,2)); panelBlack.add(new Label(turnBlackDisc)); for (int i = 0; i < playerDisc.length; i++) listBlack.add(playerDisc[i]); panelBlack.add(listBlack); panelWhite.add(new Label(turnWhiteDisc)); for (int i = 0; i < playerDisc.length; i++) listWhite.add(playerDisc[i]); panelWhite.add(listWhite); panelParameter.add(panelBlack); panelParameter.add(panelWhite); dialog.add(panelParameter, BorderLayout.CENTER); buttonOk.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (listBlack.getSelectedIndex() != -1 && listBlack.getSelectedIndex() != -1) { turn = 1; playerBlack = listBlack.getSelectedIndex(); playerWhite = listWhite.getSelectedIndex(); rs = new ReversiStones(); miStart.setEnabled(false); advanceState(); dialog.dispose(); } } }); panelCommand.add(buttonOk); buttonCancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dialog.dispose(); } }); panelCommand.add(buttonCancel); dialog.add(panelCommand, BorderLayout.SOUTH); dialog.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dialog.dispose(); } }); dialog.setSize(320, 240); dialog.show(); } }); miFinish.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e){ System.exit(0); } }); m.add(miStart); m.add(miFinish); mb.add(m); f.setMenuBar(mb); f.add(c, BorderLayout.CENTER); f.add(labelStatus, BorderLayout.SOUTH); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.setSize(480, 480); f.setVisible(true); } public static void main(String args[]) { new Reversi(); } }