这是五子棋的最终效果图,棋盘以及棋子均是程序作图。下边奉献个人的源代码。
GoBangGUI.java 这个源文件主要是界面的实现
package game.gobang; import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.Box; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; public class GoBangGUI extends JFrame{ private JPanel mainframe; private GoBangBoard board; private JPanel control; private GridLayout grid; private BorderLayout border; private JButton start; private JButton end; private JLabel label; private int row; private int column; private Gobang gobang; private MouseAdapter mouselistener; private boolean flag; private boolean ok; private ActionListener actionlistener; public GoBangGUI(){ this("GoBang Game", 10, 10); } public GoBangGUI(String title, int row, int column){ super(title); // this.setUndecorated(true); this.row = row; this.column = column; this.flag = false; this.ok = false; initial(); setSize(600, 600); this.setResizable(false); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationByPlatform(true); this.setVisible(true); this.requestFocus(); } private void initial() { createComponent(); layOut(); listener(); } private void createComponent() { mainframe = new JPanel(); control = new JPanel(); border = new BorderLayout(); grid = new GridLayout(); start = new JButton("Start"); label = new JLabel(); gobang = new Gobang(row, column); board = new GoBangBoard(gobang, row, column); end = new JButton("Exit"); // gobang.getData()[0][0] = GobangColor.WHITE; } private void layOut() { this.getContentPane().add(mainframe); // setBackpicture(); // mainframe.setBackground(Color.yellow); mainframe.setLayout(border); mainframe.add(board, BorderLayout.CENTER); // board.setBounds(0, 0, 500, 500); mainframe.add(control, BorderLayout.EAST); Box ve = Box.createVerticalBox(); ve.add(start); ve.add(Box.createVerticalStrut(50)); end.setSize(start.getWidth(), start.getHeight()); ve.add(end); control.add(ve); } private void setBackpicture() { ImageIcon a = new ImageIcon("/home/qcq/1.jpg"); JLabel p = new JLabel(a); p.setBounds(0, 0, a.getIconWidth(), a.getIconHeight()); this.getLayeredPane().add(p, Integer.MIN_VALUE); } /* * 判断鼠标落入棋盘窗格的位置索引 (x, y)为当前鼠标的坐标。 */ private Place judgePlace(int indexx, int indexy, int x, int y, int squre){ for (int i = 0; i < row; i++){ for (int j = 0; j < column; j++){ if (x >= indexx + j * squre && x <= indexx + (j + 1) * squre &&y >= indexy + i * squre && y <= indexy + (i + 1) * squre){ return new Place(i, j); } } } return null; } private void listener() { mouselistener = new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { int x = e.getX(); int y = e.getY(); /* * (25, 10) is a special coordinate. the board draw begins here, * when the board added to the this JFrame the begin change to * (25, 10 + 25), However, I do not know why. just keep it; * */ if (ok){ Place temp = judgePlace(25, 10, x, y, board.getSqure()); System.out.println(temp); if (flag){ if (!gobang.check(temp.getX(), temp.getY())){ JOptionPane.showMessageDialog(mainframe, "Change another place"); } else { gobang.setChess(temp.getX(), temp.getY(), GobangColor.WHITE); repaint(); if (gobang.isSuccess(new Place(0, 0), new Place(row - 1, column - 1), GobangColor.WHITE)){ // JOptionPane.showMessageDialog(mainframe, "The white player is win"); int choice = JOptionPane.showConfirmDialog(mainframe, "The white player is win", "DO you want try again", JOptionPane.YES_NO_OPTION); if (choice == JOptionPane.YES_OPTION){ gobang.initial(); ok = false; repaint(); } } flag = false; } } else { if (!gobang.check(temp.getX(), temp.getY())){ JOptionPane.showMessageDialog(mainframe, "Change another place"); } else { gobang.setChess(temp.getX(), temp.getY(), GobangColor.BLACK); repaint(); if (gobang.isSuccess(new Place(0, 0), new Place(row - 1, column - 1), GobangColor.BLACK)){ // JOptionPane.showMessageDialog(mainframe, "The black player is win"); int choice = JOptionPane.showConfirmDialog(mainframe, "The black player is win", "DO you want try again", JOptionPane.YES_NO_OPTION); if (choice == JOptionPane.YES_OPTION){ gobang.initial(); ok = false; repaint(); } } flag = true; } } } else { JOptionPane.showMessageDialog(mainframe, "please start the game"); } } }; actionlistener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (((JButton)(e.getSource())).getText().equals("Start")){ ok = true; } else if (((JButton)(e.getSource())).getText().equals("Exit")){ System.exit(0); } } }; board.addMouseListener(mouselistener); start.addActionListener(actionlistener); end.addActionListener(actionlistener); } public static void main(String[] args) { GoBangGUI game = new GoBangGUI(null, 20, 20); } }
package game.gobang; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.LayoutManager; import javax.swing.JPanel; public class GoBangBoard extends JPanel { private Gobang gobang; private int row; private int column; private int squre; public GoBangBoard() { //this.setBounds(x, y, width, height); } public GoBangBoard(Gobang gobang, int row, int column){ this.gobang = gobang; this.column = column; this.row = row; } public int getSqure(){ return squre; } public void paint(Graphics g){ Graphics2D gg = (Graphics2D)g; squre = (this.getWidth() - 50) / Math.max(row, column); /** * from the point (25, 10) draw the game's background. * */ /* * below draw the background gird. * */ int x = 25; int y = 10; gg.setStroke(new BasicStroke(0.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1.0f,new float[]{5f, 5f},0f)); gg.setColor(Color.blue); for (int i = 0; i < row; i++){ for (int j = 0; j < column; j++){ gg.drawRect(x + j * squre, y + i * squre, squre, squre); } } for (int i = 0; i < gobang.getData().length; i++){ for (int j = 0; j < gobang.getData()[i].length; j++){ if (GobangColor.WHITE == gobang.getData()[i][j]){ gg.setColor(Color.blue); gg.fillOval(x + j * squre, y + i * squre, squre, squre); } else if (GobangColor.BLACK == gobang.getData()[i][j]){ gg.setColor(Color.BLACK); gg.fillOval(x + j * squre, y + i * squre, squre, squre); } } } gg.setStroke(new BasicStroke(5f)); gg.setColor(Color.blue); gg.drawRect(x - 1, y - 1, squre * column + 2, squre * row + 2); gg.dispose(); } }GobangColor.java 本文件是棋子颜色的枚举定义。
package game.gobang; public enum GobangColor { BLACK, WHITE, NULL }
package game.gobang; /** * here lays the snake's body coordinate information. * */ public class Place { private int x; private int y; public Place(){ this(0, 0); } public Place(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } @Override public String toString() { return "Place [x=" + x + ", y=" + y + "]"; } public void setY(int y) { this.y = y; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Place other = (Place) obj; if (x != other.x) return false; if (y != other.y) return false; return true; } }
package game.gobang; import java.util.Scanner; /** * Question 19、利用二维数组实现五子棋下棋功能 * */ public class Gobang { private GobangColor[][] data; private int row = 10; private int column = 10; public Gobang() { /* * The default checkerboard is 10 * 10 boxes; * */ this(10, 10); initial(); } /* * Initial the Game * */ public void initial(){ for (int i = 0; i < row; i++){ for (int j = 0; j < column; j++){ data[i][j] = GobangColor.NULL; } } } /* * The piece move * */ public void setChess(int row, int column,GobangColor color){ data[row][column] = color; } public Gobang(int row, int column){ /* * set the Chess squre to row * line * */ this.row = row; this.column = column; data = new GobangColor[row][]; for (int i = 0; i < row; i++){ data[i] = new GobangColor[column]; } initial(); } public GobangColor[][] getData() { return data; } public void setData(GobangColor[][] data) { this.data = data; } public int getRow() { return row; } public void setRow(int row) { this.row = row; } public int getColumn() { return column; } public void setColumn(int column) { this.column = column; } /* * print out the current checkerboard * */ public void printCheckerBoard(){ /* * print out the chessboard layout * */ for (GobangColor[] i: data){ for (GobangColor j : i){ System.out.print(j.toString() + " "); } System.out.println(); } } /* * verify the input data to insure the piece is in the range * and not put this piece in the history place * 验证棋子在合适的位置上 * */ public boolean check(int x, int y){ if (x < 0 || x >= row || y < 0 || y >= column){ System.out.println("The input is error"); System.out.println("The input should from(0, 0) to (" + (x - 1) + "," + (y - 1) + ")"); return false; } if (GobangColor.NULL != data[x][y]){ System.out.println("This place already has one piece!"); return false; } return true; } /* * judge if successed, The parameter x and y * is the range which need to be scanning. * The Scanning range can zoom in a range which is a circle(a square) * center in current move, radius is 5. * 扫描棋盘看是不是有棋子获胜,可以优化扫描方案,将扫描的范围局限于一个以落子处为中心 * 5为半径的棋盘(isSucess的重载方法实现这一个思想)。 */ public boolean isSuccess(Place x, Place y, GobangColor color){ boolean flag = false; int counter = 0; label: for (int i = (int) x.getX(); i <= (int)y.getX(); i++){ for (int j = (int)x.getY(); j <= (int)y.getY(); j++){ /* * scanning the [x,y] range in 4 directions. * */ // check the horizontal counter = 0; if (j + 4 <= (int)y.getY()){ for (int index = j; index <= j + 4; index++){ if (color == data[i][index]){ counter++; } } } if (5 == counter){ flag = true; break label; } // check the vertical counter = 0; if (i + 4 <= (int)y.getX()){ for (int index = i; index <= i + 4; index++){ if (color == data[index][j]){ counter++; } } } if (5 == counter){ flag = true; break label; } //check the dig line counter = 0; if ((i + 4 <= (int)y.getX()) && (j + 4 <= (int)y.getY())){ for (int indexX = i, indexY = j; indexX <= i + 4 ;indexX++, indexY++){ if (color == data[indexX][indexY]){ counter++; } } } if (5 == counter){ flag = true; break label; } //check the reverse dig line counter = 0; if ((i + 4 <= (int)y.getX()) && (j - 4 >= (int)x.getY())){ for (int indexX = i, indexY = j; indexX <= i + 4;indexX++, indexY--){ if (color == data[indexX][indexY]){ counter++; } } } if (5 == counter){ flag = true; break label; } } } return flag; } /* * 这是一个重载的方法,与上一个方法不同的是没有使用扫描来实现判定 * 而是基于落子的地方,来基于四个方向进行计数判断。 * */ public boolean isSuccess(Place x, GobangColor color){ boolean flag = false; /* * horizontal direction * */ int counter = 0; for (int i = x.getY(); i >= Math.min(x.getY() - 4, row); i--){ if (color == data[x.getX()][i]){ counter++; }else{ break; } } for (int i = x.getY() + 1; i <= Math.min(x.getY() + 4, column - 1); i++){ if (color == data[x.getX()][i]){ counter++; }else{ break; } } if (5 == counter){ flag = true; } /* * vertical direction * */ counter = 0; for (int i = x.getX(); i >= Math.min(x.getX() - 4, row); i--){ if (color == data[i][x.getY()]){ counter++; }else{ break; } } for (int i = x.getY() + 1; i <= Math.min(x.getY() + 4, column - 1); i++){ if (color == data[i][x.getY()]){ counter++; }else{ break; } } if (5 == counter){ flag = true; } /* * diagonal direction * */ counter = 0; for (int i = x.getX(), j = x.getY(); i >= Math.min(x.getX() - 4, row) && j >= Math.min(x.getY() - 4, row); i--, j--){ if (color == data[i][j]){ counter++; }else{ break; } } for (int i = x.getX() + 1, j = x.getY() + 1; i <= Math.min(x.getX() + 4, column - 1) && j <= Math.min(x.getY() + 4, column - 1); i++, j++){ if (color == data[i][j]){ counter++; }else{ break; } } if (5 == counter){ flag = true; } /* * reverse diagonal direction * */ counter = 0; for (int i = x.getX(), j = x.getY(); i <= Math.min(x.getX() + 4, column - 1) && j >= Math.min(x.getY() - 4, row); i++, j--){ if (color == data[i][j]){ counter++; }else{ break; } } for (int i = x.getX() + 1, j = x.getY() + 1; i >= Math.min(x.getX() - 4, row) && j <= Math.min(x.getY() + 4, column - 1); i--, j++){ if (color == data[i][j]){ counter++; }else{ break; } } if (5 == counter){ flag = true; } return flag; } /* * The actual game start here, where black first, white second, * we can optimize the game which do not call * the method isSuccess in the first segment. such as 8 moves. * and we can narrow the scanning the range to a square just talk above. * */ public void playChess(){ Scanner in = new Scanner(System.in); Place x = new Place(0, 0); Place y = new Place(row - 1, column - 1); label: while (true){ //The input should like 1,2 while (in.hasNext()){ String[] str = in.next().split(","); int indexX = Integer.valueOf(str[0]); int indexY = Integer.valueOf(str[1]); if (!check(indexX, indexY)){ System.out.println("please input again"); continue; }else{ setChess(indexX, indexY, GobangColor.BLACK); printCheckerBoard(); // if (isSuccess(x, y, GobangColor.BLACK)){ if (isSuccess(new Place(indexX, indexY), GobangColor.BLACK)){ System.out.println("The Black is win"); break label; } break; } } while (in.hasNext()){ String[] str = in.next().split(","); int indexX = Integer.valueOf(str[0]); int indexY = Integer.valueOf(str[1]); if (!check(indexX, indexY)){ System.out.println("please input again"); continue; }else{ setChess(indexX, indexY, GobangColor.WHITE); printCheckerBoard(); // if (isSuccess(x, y, GobangColor.WHITE)){ if (isSuccess(new Place(indexX, indexY), GobangColor.WHITE)){ System.out.println("The White is win"); break label; } break; } } } in.close(); } public static void main(String[] args) { Gobang chess = new Gobang(); chess.playChess(); } }