GOMOKU ( Source code )
Last-Modified: 2008-01-03 18:53:29
ちょっとした説明
この"GOMOKU"は以下の6つのクラスからできています。
- GoPanel
- 五目並べの盤を作っています。
- GoFrame
- GoPanelのサブクラス。メニューバーが追加されています。
- EvaluationWin
- 勝敗を判断するためのクラス。
- GoMouseEvent
- マウスによるイベントを処理するクラス。(クリックで石を置く)
- GoMenuEvent
- メニューバーのイベント処理
- GoApplet
- アプッレトです。
GoPanel
import java.awt.*; import javax.swing.*; import java.awt.event.*; public class GoPanel extends JPanel { /**フィールド*/ static final int MASUME = 10; //マス目の数 10×10 int gW, gH; //マス目の幅 private int panel[][] = new int[MASUME][MASUME]; //盤の状態を表す配列 static final int BLANK = 0, BSTONE = 1, WSTONE = -1; //panel[][]配列に入れる定数 static final int margin = 4; //石を描くときの余白 boolean isBlackTurn = true; //黒の番か MouseAdapter MouseAd; JLabel status; Image buf; Graphics ct; /**コンストラクタ*/ /**幅width,高さheightのGoPanelを作成 *@param width ウィンドウの幅 *@param height ウィンドウの高さ */ public GoPanel(int width, int height) { setBackground(new Color(238, 231, 191)); //背景色を設定 Dimension dim = new Dimension(width, height); setPreferredSize(dim); // パネルのサイズを設定 setMinimumSize(dim); setMaximumSize(dim); panelSet(); //盤上を初期化 MouseAd = new GoMouseEvent(this); //イベントリスナーを追加 this.addMouseListener(MouseAd); status = new JLabel(" "); //ステイタスバーを追加 } /**幅400,高さ400のGoPanelを作成*/ public GoPanel() { this(400, 400); } public void paintComponent(Graphics g) { buf = createImage(this.getWidth() , this.getHeight()); ct = buf.getGraphics(); super.paintComponent(ct); drawGrid(ct); //盤上に線を描く drawStone(ct); //石を描く statusOut(); //ステイタスバーに文字を入れる g.drawImage(buf , 0 , 0 ,this); } /**石が置けるかどうか *@param x 盤での列(row)の番号-1 *@param y 盤での行(column)の番号-1 *@return 置けるならtrueを返す */ boolean canPlace(int x, int y) { return panel[x][y] == BLANK; } /**黒石を置く *@param x 盤での列(row)の番号-1 *@param y 盤での行(column)の番号-1 */ void putDownB(int x, int y) { panel[x][y] = BSTONE; } /**白石を置く *@param x 盤での列(row)の番号-1 *@param y 盤での行(column)の番号-1 */ void putDownW(int x, int y) { panel[x][y] = WSTONE; } /** * 石を置く * @param x int 盤での列(row)の番号-1 * @param y int 盤での行(column)の番号-1 */ void putDown(int x, int y) { if (isBlackTurn) { putDownB(x, y); } else { putDownW(x, y); } } /** * 石を取り除く * @param x int 盤での列(row)の番号-1 * @param y int 盤での行(column)の番号-1 */ void removeStone(int x, int y) { if (!canPlace(x, y)) { panel[x][y] = BLANK; } else { System.out.println("(" + x + "," + y + ") から石を取り除こうとしましたがそこには石はありません");//test } } /** * パネルの状態を返す * @param x int 盤での列(row)の番号-1 * @param y int 盤での行(column)の番号-1 * @return int BLANK = 0, BSTONE = 1, WSTONE = -1 */ int getPanelState(int x,int y){ return panel[x][y]; } /**盤上の初期化*/ void panelSet() { for (int x = 0; x < panel.length; x++) { for (int y = 0; y < panel[x].length; y++) { panel[x][y] = BLANK; } } } /**盤上に石を置けるマスがない?*/ boolean noBlank(){ for (int x = 0; x < panel.length; x++) { for (int y = 0; y < panel[x].length; y++) { if(panel[x][y] == BLANK){ return false; } } } return true; } /**ステイタスバーに文字を表示*/ void statusOut() { if (isBlackTurn) { //黒の番のとき status.setText("Now is Black turn ."); } else { //白の番のとき status.setText("Now is White turn ."); } } /**盤上に線を描く *@param g Graphics class */ void drawGrid(Graphics g) { gW = getWidth() / MASUME; //マスの幅 gH = getHeight() / MASUME; g.setColor(Color.black); for (int i = 0; i <= MASUME; i++) { //横の線を引く g.drawLine(0, (int) ((0.5 + i) * gH), getWidth(), (int) ((0.5 + i) * gH)); } for (int i = 0; i <= MASUME; i++) { //縦の線を引く g.drawLine((int) ((0.5 + i) * gW), 0, (int) ((0.5 + i) * gW), getHeight()); } } /**石を描く *@param g Graphics class */ void drawStone(Graphics g) { for (int x = 0; x < panel.length; x++) { for (int y = 0; y < panel[x].length; y++) { if (panel[x][y] == BSTONE) { //該当箇所が黒い石 g.setColor(Color.black); g.drawOval(x * gW + margin, y * gH + margin, gW - 2 * margin, gH - 2 * margin); g.drawOval(x * gW + margin + 1, y * gH + margin + 1, gW - 2 * margin - 2, gH - 2 * margin - 2); g.fillOval(x * gW + margin, y * gH + margin, gW - 2 * margin, gH - 2 * margin); } if (panel[x][y] == WSTONE) { //該当箇所が白い石 g.setColor(Color.black); g.drawOval(x * gW + margin, y * gH + margin, gW - 2 * margin, gH - 2 * margin); g.drawOval(x * gW + margin + 1, y * gH + margin + 1, gW - 2 * margin - 2, gH - 2 * margin - 2); g.setColor(Color.white); g.fillOval(x * gW + margin + 1, y * gH + margin + 1, gW - 2 * margin - 2, gH - 2 * margin - 2); } } } } public static void main(String[] args) { JFrame frame = new JFrame("GOMOKU"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //ウィンドウを閉じたときプログラムを終了 Container cont = frame.getContentPane(); cont.setLayout(new BorderLayout()); GoPanel gop = new GoPanel(); cont.setBackground(Color.white); cont.add(gop, BorderLayout.CENTER); cont.add(gop.status, BorderLayout.SOUTH); frame.pack(); frame.setVisible(true); } }
GoFrame
import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import java.awt.Color; import java.awt.BorderLayout; import javax.swing.JFrame; import java.awt.Container; import java.util.ArrayList; public class GoFrame extends GoPanel { /**フィールド*/ JMenuBar menuBar; JMenu menu; JMenu help; JMenuItem item1, item2, item3, item4; GoMenuEvent gme; ArrayList history; /** * コンストラクタ * @param width int ウィンドウの幅 * @param height int ウィンドウの高さ */ public GoFrame(int width, int height) { super(width, height); gme=new GoMenuEvent(this); menuBar = new JMenuBar(); menu = new JMenu("Menu"); help = new JMenu("Help"); item1 = new JMenuItem("UnDo"); item1.setActionCommand("UnDo"); item1.addActionListener(gme); item2 = new JMenuItem("Restart"); item2.setActionCommand("Restart"); item2.addActionListener(gme); item3 = new JMenuItem("Version"); item3.setActionCommand("Version"); item3.addActionListener(gme); menu.add(item1); menu.add(item2); help.add(item3); menuBar.add(menu); menuBar.add(help); history = new ArrayList(); } public GoFrame() { this(400, 400); } void putDownB(int x, int y) { super.putDownB(x, y); history.add(new int[] {x, y}); } void putDownW(int x, int y) { super.putDownW(x, y); history.add(new int[] {x, y}); } void putDown(int x, int y) { super.putDown(x, y); history.add(new int[] {x, y}); } void panelSet() { super.panelSet(); if(history!=null){ history.clear(); } super.isBlackTurn=true; } void unDo(){ if(history.size()!=0){ int point[] = (int[]) history.get(history.size()-1); super.removeStone(point[0], point[1]); history.remove(history.size() - 1); history.remove(history.size() - 1); super.isBlackTurn=!super.isBlackTurn; } } public static void main(String[] args) { GoFrame gop = new GoFrame(); JFrame frame = new JFrame("GOMOKU"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //ウィンドウを閉じたときプログラムを終了 Container cont = frame.getContentPane(); cont.setLayout(new BorderLayout()); cont.setBackground(Color.white); cont.add(gop, BorderLayout.CENTER); cont.add(gop.status, BorderLayout.SOUTH); frame.setJMenuBar(gop.menuBar); frame.pack(); frame.setVisible(true); } }
EvaluationWin
public class EvaluationWin { GoPanel goPanel; static final int WIN = 1, NOT_WIN = 0; int stone; public EvaluationWin(GoPanel g) { this.goPanel = g; } void setForBlack() { //黒石評価の準備 stone = GoPanel.BSTONE; } void setForWhite() { //白石評価の準備 stone = GoPanel.WSTONE; } /** * * @param startX int 開始位置(X) * @param startY int 開始位置(Y) * @param dX int 変化量X * @param dY int 変化量Y * @param n int 評価するマスの数 * @return int 勝なら1、非勝なら0 */ int evaluateLine(int startX, int startY, int dX, int dY, int n) { int stoneNumber = 0; for (int i = 0; i < n; i++) { if (goPanel.getPanelState(startX-1 + i * dX,startY-1 + i * dY) == stone) {//石なら stoneNumber++; if(stoneNumber>=5){//5個以上連続なら return WIN; } } else{//石以外 stoneNumber=0; } } return NOT_WIN; } /** * 縦の列を評価 * @return int 勝なら1,2,3... , 非勝なら0 */ int evaluateRow(){ int sum=0; for(int row=1;row<=goPanel.MASUME;row++){ sum=sum+evaluateLine(row,1,0,1,goPanel.MASUME); } return sum; } /** * 横の行を評価 * @return int 勝なら1,2,3... , 非勝なら0 */ int evaluateColumn(){ int sum=0; for(int col=1;col<=goPanel.MASUME;col++){ sum=sum+evaluateLine(1,col,1,0,goPanel.MASUME); } return sum; } /** * 斜めの列を評価 * @return int 勝なら1,2,3... , 非勝なら0 */ int evaluateTilt(){ int sum=0; sum=sum+evaluateLine(1,1,1,1,GoPanel.MASUME); sum=sum+evaluateLine(GoPanel.MASUME,1,-1,1,GoPanel.MASUME); for(int k=2;k<=GoPanel.MASUME-4;k++){ sum=sum+evaluateLine(1,k,1,1,GoPanel.MASUME+1-k); sum=sum+evaluateLine(k,1,1,1,GoPanel.MASUME+1-k); sum=sum+evaluateLine(GoPanel.MASUME+1-k,1,-1,1,GoPanel.MASUME+1-k); sum=sum+evaluateLine(GoPanel.MASUME,k,-1,1,GoPanel.MASUME+1-k); } return sum; } /** * 黒石の勝ち、非勝を評価 * @return int 勝ちなら1,2,3,4... ,非勝なら0 */ int evaluateBlack(){ setForBlack(); return evaluateRow()+evaluateColumn()+evaluateTilt(); } /** * 白石の勝ち、非勝を評価 * @return int 勝ちなら1,2,3,4... ,非勝なら0 */ int evaluateWhite(){ setForWhite(); return evaluateRow()+evaluateColumn()+evaluateTilt(); } /**人の勝、非勝 *@return int 勝ちなら1,2,3,4... ,非勝なら0 */ int evaluateOnMan(){ return evaluateBlack(); } /**CPUの勝、非勝 *@return int 勝ちなら1,2,3,4... ,非勝なら0 */ int evaluateOnCPU(){ return evaluateWhite(); } }
GoMouseEvent
import java.awt.event.MouseAdapter; import java.awt.event.*; import javax.swing.*; public class GoMouseEvent extends MouseAdapter { /**フィールド*/ private GoPanel goPanel; GoCPU cpu; EvaluationWin ew; /**コンストラクタ * @param g GoMouseEventが参照するGoPanel */ public GoMouseEvent(GoPanel g) { this.goPanel = g; ew = new EvaluationWin(goPanel); } /**メソッド*/ /**マウスがクリックされたら *@param me MouseEvent */ public void mouseClicked(MouseEvent me) { int x = analyzeX(me.getX()); int y = analyzeY(me.getY()); if (goPanel.canPlace(x, y)) { //石置けるか goPanel.putDown(x, y); goPanel.repaint(); winCheck(); goPanel.isBlackTurn = !goPanel.isBlackTurn; } else { //石置けないとき dialog(new String[] {"You Can NOT ", "Put Down Stone There."}); goPanel.repaint(); } } /**勝敗、引き分けチェック*/ void winCheck() { if (ew.evaluateBlack() != 0) { dialog(new String[] {"BLACK WIN!!", "Congratulations!"}); goPanel.panelSet(); goPanel.isBlackTurn = false; goPanel.repaint(); } if (ew.evaluateWhite() != 0) { dialog(new String[] {"WHITE WIN!!", "Congratulations!"}); goPanel.panelSet(); goPanel.isBlackTurn = false; goPanel.repaint(); } if (goPanel.noBlank()) { dialog(new String[] {"DRAW."}); goPanel.panelSet(); goPanel.isBlackTurn = false; goPanel.repaint(); } } void dialog(String[] message) { JOptionPane.showMessageDialog(goPanel, message, "MESSAGE", JOptionPane.INFORMATION_MESSAGE); } /**座標をマス目にして返す(X) *@param x ウィンドウ上でのX座標 *@return 盤での列(row)の番号 */ int analyzeX(int x) { return x / goPanel.gW; } /**座標をマス目にして返す(Y) *@param y ウィンドウ上でのy座標 *@return 盤での行(column)の番号 */ int analyzeY(int y) { return y / goPanel.gH; } }
GoMenuEvent
import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JOptionPane; public class GoMenuEvent implements ActionListener { private GoFrame goFrame; public GoMenuEvent(GoFrame go) { goFrame = go; } /** * Invoked when an action occurs. * * @param e ActionEvent * @todo この java.awt.event.ActionListener メソッドを実装 */ public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if(command.equals("UnDo")){ goFrame.unDo(); } if(command.equals("Restart")){ goFrame.panelSet(); } if(command.equals("Version")){ JOptionPane.showMessageDialog(goFrame, new String[]{"五目並べ","Version 1.0","Author :Toru Mano"}, "MESSAGE",JOptionPane.INFORMATION_MESSAGE); } goFrame.repaint(); } }
GoApplet
import java.awt.*; import javax.swing.*; public class GoApplet extends JApplet { GoFrame goFrame; //アプレットの初期化 public void init() { goFrame=new GoFrame(); Container cont=this.getContentPane(); cont.setBackground(Color.white); setJMenuBar(goFrame.menuBar); cont.add(goFrame, BorderLayout.CENTER); cont.add(goFrame.status, BorderLayout.SOUTH); this.setVisible(true); } }