转自:http://blog.csdn.net/cnlht/article/details/8176130
package com.cctvjiatao.FiveChess; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RadialGradientPaint; import java.awt.RenderingHints; import java.awt.Toolkit; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.geom.Ellipse2D; import javax.swing.JOptionPane; import javax.swing.JPanel; /** * 五子棋--棋盘类 * * @author keletao * @date 2016-1-30 上午6:53:05 */ public class ChessBoard extends JPanel implements MouseListener { public static final int MARGIN = 30;// 边距 public static final int GRID_SPAN = 35;// 网格间距 public static final int ROWS = 15;// 棋盘行数 public static final int COLS = 15;// 棋盘列数 Point[] chessList = new Point[(ROWS + 1) * (COLS + 1)];// 初始每个数组元素为null boolean isBlack = true;// 默认开始是黑棋先 boolean gameOver = false;// 游戏是否结束 int chessCount;// 当前棋盘棋子的个数 int xIndex, yIndex;// 当前刚下棋子的索引 Image img; Image shadows; Color colortemp; public ChessBoard() { // setBackground(Color.blue);//设置背景色为橘黄色 img = Toolkit.getDefaultToolkit().getImage("board.jpg"); shadows = Toolkit.getDefaultToolkit().getImage("shadows.jpg"); addMouseListener(this); addMouseMotionListener(new MouseMotionListener() { public void mouseDragged(MouseEvent e) { } public void mouseMoved(MouseEvent e) { // 将鼠标点击的坐标位置转成网格索引 int x1 = (e.getX() - MARGIN + GRID_SPAN / 2) / GRID_SPAN; int y1 = (e.getY() - MARGIN + GRID_SPAN / 2) / GRID_SPAN; // 游戏已经结束不能下 // 落在棋盘外不能下 // x,y位置已经有棋子存在,不能下 if (x1 < 0 || x1 > ROWS || y1 < 0 || y1 > COLS || gameOver || findChess(x1, y1)){ setCursor(new Cursor(Cursor.DEFAULT_CURSOR));// 设置成默认状态 }else setCursor(new Cursor(Cursor.HAND_CURSOR)); } }); } // 绘制 public void paintComponent(Graphics g) { super.paintComponent(g);// 画棋盘 int imgWidth = img.getWidth(this); int imgHeight = img.getHeight(this);// 获得图片的宽度与高度 int FWidth = getWidth(); int FHeight = getHeight();// 获得窗口的宽度与高度 int x = (FWidth - imgWidth) / 2; int y = (FHeight - imgHeight) / 2; g.drawImage(img, x, y, null); for (int i = 0; i <= ROWS; i++) {// 画横线 g.drawLine(MARGIN, MARGIN + i * GRID_SPAN, MARGIN + COLS * GRID_SPAN, MARGIN + i * GRID_SPAN); } for (int i = 0; i <= COLS; i++) {// 画竖线 g.drawLine(MARGIN + i * GRID_SPAN, MARGIN, MARGIN + i * GRID_SPAN, MARGIN + ROWS * GRID_SPAN); } // 画棋子 for (int i = 0; i < chessCount; i++) { // 网格交叉点x,y坐标 int xPos = chessList[i].getX() * GRID_SPAN + MARGIN; int yPos = chessList[i].getY() * GRID_SPAN + MARGIN; g.setColor(chessList[i].getColor());// 设置颜色 colortemp = chessList[i].getColor(); if (colortemp == Color.black) { RadialGradientPaint paint = new RadialGradientPaint( xPos - Point.DIAMETER / 2 + 25, yPos - Point.DIAMETER / 2 + 10, 20, new float[] { 0f, 1f }, new Color[] { Color.WHITE, Color.BLACK }); ((Graphics2D) g).setPaint(paint); ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT); } else if (colortemp == Color.white) { RadialGradientPaint paint = new RadialGradientPaint( xPos - Point.DIAMETER / 2 + 25, yPos - Point.DIAMETER / 2 + 10, 70, new float[] { 0f, 1f }, new Color[] { Color.WHITE, Color.BLACK }); ((Graphics2D) g).setPaint(paint); ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT); } Ellipse2D e = new Ellipse2D.Float(xPos - Point.DIAMETER / 2, yPos - Point.DIAMETER / 2, 34, 35); ((Graphics2D) g).fill(e); // 标记最后一个棋子的红矩形框 if (i == chessCount - 1) {// 如果是最后一个棋子 g.setColor(Color.red); g.drawRect(xPos - Point.DIAMETER / 2, yPos - Point.DIAMETER / 2, 34, 35); } } } public void mousePressed(MouseEvent e) {// 鼠标在组件上按下时调用 // 游戏结束时,不再能下 if (gameOver){ return; } String colorName = isBlack ? "黑棋" : "白棋"; // 将鼠标点击的坐标位置转换成网格索引 xIndex = (e.getX() - MARGIN + GRID_SPAN / 2) / GRID_SPAN; yIndex = (e.getY() - MARGIN + GRID_SPAN / 2) / GRID_SPAN; // 落在棋盘外不能下 if (xIndex < 0 || xIndex > ROWS || yIndex < 0 || yIndex > COLS){ return; } // 如果x,y位置已经有棋子存在,不能下 if (findChess(xIndex, yIndex)){ return; } // 可以进行时的处理 Point ch = new Point(xIndex, yIndex, isBlack ? Color.black : Color.white); chessList[chessCount++] = ch; repaint();// 通知系统重新绘制 // 如果胜出则给出提示信息,不能继续下棋 if (isWin()) { String msg = String.format("恭喜,%s赢了!", colorName); JOptionPane.showMessageDialog(this, msg); gameOver = true; } isBlack = !isBlack; } // 覆盖mouseListener的方法 public void mouseClicked(MouseEvent e) { // 鼠标按键在组件上单击时调用 } public void mouseEntered(MouseEvent e) { // 鼠标进入到组件上时调用 } public void mouseExited(MouseEvent e) { // 鼠标离开组件时调用 } public void mouseReleased(MouseEvent e) { // 鼠标按钮在组件上释放时调用 } // 在棋子数组中查找是否有索引为x,y的棋子存在 private boolean findChess(int x, int y) { for (Point c : chessList) { if (c != null && c.getX() == x && c.getY() == y){ return true; } } return false; } private boolean isWin() { int continueCount = 1;// 连续棋子的个数 // 横向向西寻找 for (int x = xIndex - 1; x >= 0; x--) { Color c = isBlack ? Color.black : Color.white; if (getChess(x, yIndex, c) != null) { continueCount++; }else{ break; } } // 横向向东寻找 for (int x = xIndex + 1; x <= COLS; x++) { Color c = isBlack ? Color.black : Color.white; if (getChess(x, yIndex, c) != null) { continueCount++; }else{ break; } } if (continueCount >= 5) { return true; }else{ continueCount = 1; } // 继续另一种搜索纵向 // 向上搜索 for (int y = yIndex - 1; y >= 0; y--) { Color c = isBlack ? Color.black : Color.white; if (getChess(xIndex, y, c) != null) { continueCount++; }else{ break; } } // 纵向向下寻找 for (int y = yIndex + 1; y <= ROWS; y++) { Color c = isBlack ? Color.black : Color.white; if (getChess(xIndex, y, c) != null){ continueCount++; }else{ break; } } if (continueCount >= 5){ return true; }else{ continueCount = 1; } // 继续另一种情况的搜索:斜向 // 东北寻找 for (int x = xIndex + 1, y = yIndex - 1; y >= 0 && x <= COLS; x++, y--) { Color c = isBlack ? Color.black : Color.white; if (getChess(x, y, c) != null) { continueCount++; }else{ break; } } // 西南寻找 for (int x = xIndex - 1, y = yIndex + 1; x >= 0 && y <= ROWS; x--, y++) { Color c = isBlack ? Color.black : Color.white; if (getChess(x, y, c) != null) { continueCount++; }else{ break; } } if (continueCount >= 5){ return true; }else{ continueCount = 1; } // 继续另一种情况的搜索:斜向 // 西北寻找 for (int x = xIndex - 1, y = yIndex - 1; x >= 0 && y >= 0; x--, y--) { Color c = isBlack ? Color.black : Color.white; if (getChess(x, y, c) != null){ continueCount++; }else{ break; } } // 东南寻找 for (int x = xIndex + 1, y = yIndex + 1; x <= COLS && y <= ROWS; x++, y++) { Color c = isBlack ? Color.black : Color.white; if (getChess(x, y, c) != null){ continueCount++; }else{ break; } } if (continueCount >= 5){ return true; }else{ continueCount = 1; } return false; } private Point getChess(int xIndex, int yIndex, Color color) { for (Point p : chessList) { if (p != null && p.getX() == xIndex && p.getY() == yIndex && p.getColor() == color) return p; } return null; } public void restartGame() { // 清除棋子 for (int i = 0; i < chessList.length; i++) { chessList[i] = null; } // 恢复游戏相关的变量值 isBlack = true; gameOver = false; // 游戏是否结束 chessCount = 0; // 当前棋盘棋子个数 repaint(); } // 悔棋 public void goback() { if (chessCount == 0){ return; } chessList[chessCount - 1] = null; chessCount--; if (chessCount > 0) { xIndex = chessList[chessCount - 1].getX(); yIndex = chessList[chessCount - 1].getY(); } isBlack = !isBlack; repaint(); } // 矩形Dimension public Dimension getPreferredSize() { return new Dimension(MARGIN * 2 + GRID_SPAN * COLS, MARGIN * 2 + GRID_SPAN * ROWS); } }
package com.cctvjiatao.FiveChess; import java.awt.Color; /** * 棋子类 * * @author keletao * @date 2016-1-30 上午6:53:21 */ public class Point { private int x;// 棋盘中的x索引 private int y;// 棋盘中的y索引 private Color color;// 颜色 public static final int DIAMETER = 30;// 直径 public Point(int x, int y, Color color) { this.x = x; this.y = y; this.color = color; } public int getX() {// 拿到棋盘中x的索引 return x; } public int getY() { return y; } public Color getColor() {// 获得棋子的颜色 return color; } }
package com.cctvjiatao.FiveChess; import java.awt.BorderLayout; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; /** * 五子棋主框架类,程序启动类 * * @author keletao * @date 2016-1-30 上午6:53:38 */ public class StartChessJFrame extends JFrame { private ChessBoard chessBoard; private JPanel toolbar; private JButton startButton, backButton, exitButton; private JMenuBar menuBar; private JMenu sysMenu; private JMenuItem startMenuItem, exitMenuItem, backMenuItem; // 重新开始,退出,和悔棋菜单项 public StartChessJFrame() { setTitle("单机版五子棋");// 设置标题 chessBoard = new ChessBoard(); Container contentPane = getContentPane(); contentPane.add(chessBoard); chessBoard.setOpaque(true); // 创建和添加菜单 menuBar = new JMenuBar();// 初始化菜单栏 sysMenu = new JMenu("系统");// 初始化菜单 // 初始化菜单项 startMenuItem = new JMenuItem("重新开始"); exitMenuItem = new JMenuItem("退出"); backMenuItem = new JMenuItem("悔棋"); // 将三个菜单项添加到菜单上 sysMenu.add(startMenuItem); sysMenu.add(exitMenuItem); sysMenu.add(backMenuItem); // 初始化按钮事件监听器内部类 MyItemListener lis = new MyItemListener(); // 将三个菜单注册到事件监听器上 this.startMenuItem.addActionListener(lis); backMenuItem.addActionListener(lis); exitMenuItem.addActionListener(lis); menuBar.add(sysMenu);// 将系统菜单添加到菜单栏上 setJMenuBar(menuBar);// 将menuBar设置为菜单栏 toolbar = new JPanel();// 工具面板实例化 // 三个按钮初始化 startButton = new JButton("重新开始"); exitButton = new JButton("退出"); backButton = new JButton("悔棋"); // 将工具面板按钮用FlowLayout布局 toolbar.setLayout(new FlowLayout(FlowLayout.LEFT)); // 将三个按钮添加到工具面板 toolbar.add(startButton); toolbar.add(exitButton); toolbar.add(backButton); // 将三个按钮注册监听事件 startButton.addActionListener(lis); exitButton.addActionListener(lis); backButton.addActionListener(lis); // 将工具面板布局到界面”南方“也就是下方 add(toolbar, BorderLayout.SOUTH); add(chessBoard);// 将面板对象添加到窗体上 // 设置界面关闭事件 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // setSize(800,800); pack();// 自适应大小 } private class MyItemListener implements ActionListener { public void actionPerformed(ActionEvent e) { Object obj = e.getSource();// 获得事件源 if (obj == StartChessJFrame.this.startMenuItem || obj == startButton) { // 重新开始 // JFiveFrame.this内部类引用外部类 System.out.println("重新开始"); chessBoard.restartGame(); } else if (obj == exitMenuItem || obj == exitButton) System.exit(0); else if (obj == backMenuItem || obj == backButton) { System.out.println("悔棋..."); chessBoard.goback(); } } } public static void main(String[] args) { StartChessJFrame f = new StartChessJFrame();// 创建主框架 f.setVisible(true);// 显示主框架 } }