Fork me on GitHub

五子棋

一、实践目标:

       1.掌握JavaGUI界面设计

       2.掌握鼠标事件的监听(MouseListener,MouseMotionListener)

二、实践内容:

      设计一个简单的五子棋程序,能够实现五子棋下棋过程。如下图所示

 

 

五子棋运行界面

  1 package cn.edu.ouc.fiveChess;
  2 
  3 import java.awt.Color;
  4 import java.awt.Cursor;
  5 import java.awt.Dimension;
  6 import java.awt.Graphics;
  7 import java.awt.Graphics2D;
  8 import java.awt.Image;
  9 import java.awt.RadialGradientPaint;
 10 import java.awt.RenderingHints;
 11 import java.awt.Toolkit;
 12 import java.awt.event.MouseEvent;
 13 import java.awt.event.MouseListener;
 14 import java.awt.event.MouseMotionListener;
 15 import java.awt.geom.Ellipse2D;
 16 
 17 import javax.swing.*;
 18 /**
 19  * 五子棋--棋盘类 
 20  */
 21 
 22 public class ChessBoard extends JPanel implements MouseListener {
 23    public static final int MARGIN=30;//边距
 24    public static final int GRID_SPAN=35;//网格间距
 25    public static final int ROWS=15;//棋盘行数
 26    public static final int COLS=15;//棋盘列数
 27    
 28    Point[] chessList=new Point[(ROWS+1)*(COLS+1)];//初始每个数组元素为null
 29    boolean isBlack=true;//默认开始是黑棋先
 30    boolean gameOver=false;//游戏是否结束
 31    int chessCount;//当前棋盘棋子的个数
 32    int xIndex,yIndex;//当前刚下棋子的索引
 33    
 34    Image img;
 35    Image shadows;
 36    Color colortemp;
 37    public ChessBoard(){
 38       
 39       // setBackground(Color.blue);//设置背景色为橘黄色
 40        img=Toolkit.getDefaultToolkit().getImage("board.jpg");
 41        shadows=Toolkit.getDefaultToolkit().getImage("shadows.jpg");
 42        addMouseListener(this);
 43        addMouseMotionListener(new MouseMotionListener(){
 44            public void mouseDragged(MouseEvent e){
 45                
 46            }
 47            
 48            public void mouseMoved(MouseEvent e){
 49              int x1=(e.getX()-MARGIN+GRID_SPAN/2)/GRID_SPAN;
 50              //将鼠标点击的坐标位置转成网格索引
 51              int y1=(e.getY()-MARGIN+GRID_SPAN/2)/GRID_SPAN;
 52              //游戏已经结束不能下
 53              //落在棋盘外不能下
 54              //x,y位置已经有棋子存在,不能下
 55              if(x1<0||x1>ROWS||y1<0||y1>COLS||gameOver||findChess(x1,y1))
 56                  setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
 57              //设置成默认状态
 58              else setCursor(new Cursor(Cursor.HAND_CURSOR));
 59              
 60            }
 61        });
 62    } 
 63    
 64   
 65 
 66 //绘制
 67    public void paintComponent(Graphics g){
 68      
 69        super.paintComponent(g);//画棋盘
 70      
 71        int imgWidth= img.getWidth(this);
 72        int imgHeight=img.getHeight(this);//获得图片的宽度与高度
 73        int FWidth=getWidth();
 74        int FHeight=getHeight();//获得窗口的宽度与高度
 75        int x=(FWidth-imgWidth)/2;
 76        int y=(FHeight-imgHeight)/2;
 77        g.drawImage(img, x, y, null);
 78     
 79        
 80        for(int i=0;i<=ROWS;i++){//画横线
 81            g.drawLine(MARGIN, MARGIN+i*GRID_SPAN, MARGIN+COLS*GRID_SPAN, MARGIN+i*GRID_SPAN);
 82        }
 83        for(int i=0;i<=COLS;i++){//画竖线
 84            g.drawLine(MARGIN+i*GRID_SPAN, MARGIN, MARGIN+i*GRID_SPAN, MARGIN+ROWS*GRID_SPAN);
 85            
 86        }
 87        
 88        //画棋子
 89        for(int i=0;i<chessCount;i++){
 90            //网格交叉点x,y坐标
 91            int xPos=chessList[i].getX()*GRID_SPAN+MARGIN;
 92            int yPos=chessList[i].getY()*GRID_SPAN+MARGIN;
 93            g.setColor(chessList[i].getColor());//设置颜色
 94           // g.fillOval(xPos-Point.DIAMETER/2, yPos-Point.DIAMETER/2,
 95                            //Point.DIAMETER, Point.DIAMETER);
 96            //g.drawImage(shadows, xPos-Point.DIAMETER/2, yPos-Point.DIAMETER/2, Point.DIAMETER, Point.DIAMETER, null);
 97            colortemp=chessList[i].getColor();
 98            if(colortemp==Color.black){
 99                RadialGradientPaint paint = new RadialGradientPaint(xPos-Point.DIAMETER/2+25, yPos-Point.DIAMETER/2+10, 20, new float[]{0f, 1f}
100                , new Color[]{Color.WHITE, Color.BLACK});
101                ((Graphics2D) g).setPaint(paint);
102                ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
103                ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT);
104 
105            }
106            else if(colortemp==Color.white){
107                RadialGradientPaint paint = new RadialGradientPaint(xPos-Point.DIAMETER/2+25, yPos-Point.DIAMETER/2+10, 70, new float[]{0f, 1f}
108                , new Color[]{Color.WHITE, Color.BLACK});
109                ((Graphics2D) g).setPaint(paint);
110                ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
111                ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT);
112 
113            }
114          
115            Ellipse2D e = new Ellipse2D.Float(xPos-Point.DIAMETER/2, yPos-Point.DIAMETER/2, 34, 35);
116            ((Graphics2D) g).fill(e);
117            //标记最后一个棋子的红矩形框
118            
119            if(i==chessCount-1){//如果是最后一个棋子
120                g.setColor(Color.red);
121                g.drawRect(xPos-Point.DIAMETER/2, yPos-Point.DIAMETER/2,
122                            34, 35);
123            }
124        }
125    }
126    
127    public void mousePressed(MouseEvent e){//鼠标在组件上按下时调用
128        
129        //游戏结束时,不再能下
130        if(gameOver) return;
131        
132        String colorName=isBlack?"黑棋":"白棋";
133        
134        //将鼠标点击的坐标位置转换成网格索引
135        xIndex=(e.getX()-MARGIN+GRID_SPAN/2)/GRID_SPAN;
136        yIndex=(e.getY()-MARGIN+GRID_SPAN/2)/GRID_SPAN;
137        
138        //落在棋盘外不能下
139        if(xIndex<0||xIndex>ROWS||yIndex<0||yIndex>COLS)
140            return;
141        
142        //如果x,y位置已经有棋子存在,不能下
143        if(findChess(xIndex,yIndex))return;
144        
145        //可以进行时的处理
146        Point ch=new Point(xIndex,yIndex,isBlack?Color.black:Color.white);
147        chessList[chessCount++]=ch;
148         repaint();//通知系统重新绘制
149       
150        
151        //如果胜出则给出提示信息,不能继续下棋
152        
153        if(isWin()){
154            String msg=String.format("恭喜,%s赢了!", colorName);
155            JOptionPane.showMessageDialog(this, msg);
156            gameOver=true;
157        }
158        isBlack=!isBlack;
159      }
160    //覆盖mouseListener的方法
161    public void mouseClicked(MouseEvent e){
162        //鼠标按键在组件上单击时调用
163    }
164    
165    public void mouseEntered(MouseEvent e){
166        //鼠标进入到组件上时调用
167    }
168    public void mouseExited(MouseEvent e){
169        //鼠标离开组件时调用
170    }
171    public void mouseReleased(MouseEvent e){
172        //鼠标按钮在组件上释放时调用
173    }
174    //在棋子数组中查找是否有索引为x,y的棋子存在
175    private boolean findChess(int x,int y){
176        for(Point c:chessList){
177            if(c!=null&&c.getX()==x&&c.getY()==y)
178                return true;
179        }
180        return false;
181    }
182    
183    
184    private boolean isWin(){
185        int continueCount=1;//连续棋子的个数
186       
187        //横向向西寻找
188        for(int x=xIndex-1;x>=0;x--){
189            Color c=isBlack?Color.black:Color.white;
190            if(getChess(x,yIndex,c)!=null){
191                continueCount++;
192            }else
193                break;
194        }
195       //横向向东寻找
196        for(int x=xIndex+1;x<=COLS;x++){
197           Color c=isBlack?Color.black:Color.white;
198           if(getChess(x,yIndex,c)!=null){
199              continueCount++;
200           }else
201              break;
202        }
203        if(continueCount>=5){
204              return true;
205        }else 
206        continueCount=1;
207        
208        //继续另一种搜索纵向
209        //向上搜索
210        for(int y=yIndex-1;y>=0;y--){
211            Color c=isBlack?Color.black:Color.white;
212            if(getChess(xIndex,y,c)!=null){
213                continueCount++;
214            }else
215                break;
216        }
217        //纵向向下寻找
218        for(int y=yIndex+1;y<=ROWS;y++){
219            Color c=isBlack?Color.black:Color.white;
220            if(getChess(xIndex,y,c)!=null)
221                continueCount++;
222            else
223               break;
224        
225        }
226        if(continueCount>=5)
227            return true;
228        else
229            continueCount=1;
230        
231        
232        //继续另一种情况的搜索:斜向
233        //东北寻找
234        for(int x=xIndex+1,y=yIndex-1;y>=0&&x<=COLS;x++,y--){
235            Color c=isBlack?Color.black:Color.white;
236            if(getChess(x,y,c)!=null){
237                continueCount++;
238            }
239            else break;
240        }
241        //西南寻找
242        for(int x=xIndex-1,y=yIndex+1;x>=0&&y<=ROWS;x--,y++){
243            Color c=isBlack?Color.black:Color.white;
244            if(getChess(x,y,c)!=null){
245                continueCount++;
246            }
247            else break;
248        }
249        if(continueCount>=5)
250            return true;
251        else continueCount=1;
252        
253        
254        //继续另一种情况的搜索:斜向
255        //西北寻找
256        for(int x=xIndex-1,y=yIndex-1;x>=0&&y>=0;x--,y--){
257            Color c=isBlack?Color.black:Color.white;
258            if(getChess(x,y,c)!=null)
259                continueCount++;
260            else break;
261        }
262        //东南寻找
263        for(int x=xIndex+1,y=yIndex+1;x<=COLS&&y<=ROWS;x++,y++){
264            Color c=isBlack?Color.black:Color.white;
265            if(getChess(x,y,c)!=null)
266                continueCount++;
267            else break;
268        }
269        if(continueCount>=5)
270            return true;
271        else continueCount=1;
272        
273        return false;
274      }
275    
276    
277    private Point getChess(int xIndex,int yIndex,Color color){
278        for(Point p:chessList){
279            if(p!=null&&p.getX()==xIndex&&p.getY()==yIndex
280                    &&p.getColor()==color)
281                return p;
282        }
283        return null;
284    }
285    
286    
287    public void restartGame(){
288        //清除棋子
289        for(int i=0;i<chessList.length;i++){
290            chessList[i]=null;
291        }
292        //恢复游戏相关的变量值
293        isBlack=true;
294        gameOver=false; //游戏是否结束
295        chessCount =0; //当前棋盘棋子个数
296        repaint();
297    }
298    
299    //悔棋
300    public void goback(){
301        if(chessCount==0)
302            return ;
303        chessList[chessCount-1]=null;
304        chessCount--;
305        if(chessCount>0){
306            xIndex=chessList[chessCount-1].getX();
307            yIndex=chessList[chessCount-1].getY();
308        }
309        isBlack=!isBlack;
310        repaint();
311    }
312    
313    //矩形Dimension
314 
315    public Dimension getPreferredSize(){
316        return new Dimension(MARGIN*2+GRID_SPAN*COLS,MARGIN*2
317                             +GRID_SPAN*ROWS);
318    }
319    
320    
321    
322 }

   2.棋子类

 1 package cn.edu.ouc.fiveChess;
 2 
 3 import java.awt.Color;
 4 /**
 5  * 棋子类
 6  */
 7 public class Point {
 8   private int x;//棋盘中的x索引
 9   private int y;//棋盘中的y索引
10   private Color color;//颜色
11   public static final int DIAMETER=30;//直径
12   
13   public Point(int x,int y,Color color){
14       this.x=x;
15       this.y=y;
16       this.color=color;
17   } 
18   
19   public int getX(){//拿到棋盘中x的索引
20       return x;
21   }
22   public int getY(){
23       return y;
24   }
25   public Color getColor(){//获得棋子的颜色
26       return color;
27   }
28 }

 3.五子棋主框架类

 1 package cn.edu.ouc.fiveChess;
 2 import java.awt.event.*;
 3 import java.awt.*;
 4 
 5 import javax.swing.*;
 6 /*
 7  五子棋主框架類,程序啟動類
 8  */
 9 public class StartChessJFrame extends JFrame {
10   private ChessBoard chessBoard;
11   private JPanel toolbar;
12   private JButton startButton,backButton,exitButton;
13   
14   private JMenuBar menuBar;
15   private JMenu sysMenu;
16   private JMenuItem startMenuItem,exitMenuItem,backMenuItem;
17   //重新开始,退出,和悔棋菜单项
18   public StartChessJFrame(){
19       setTitle("单机版五子棋");//设置标题
20       chessBoard=new ChessBoard();
21     
22       
23       Container contentPane=getContentPane();
24       contentPane.add(chessBoard);
25       chessBoard.setOpaque(true);
26       
27       
28       //创建和添加菜单
29       menuBar =new JMenuBar();//初始化菜单栏
30       sysMenu=new JMenu("系统");//初始化菜单
31       //初始化菜单项
32       startMenuItem=new JMenuItem("重新开始");
33       exitMenuItem =new JMenuItem("退出");
34       backMenuItem =new JMenuItem("悔棋");
35       //将三个菜单项添加到菜单上
36       sysMenu.add(startMenuItem);
37       sysMenu.add(exitMenuItem);
38       sysMenu.add(backMenuItem);
39       //初始化按钮事件监听器内部类
40       MyItemListener lis=new MyItemListener();
41       //将三个菜单注册到事件监听器上
42       this.startMenuItem.addActionListener(lis);
43       backMenuItem.addActionListener(lis);
44       exitMenuItem.addActionListener(lis);
45       menuBar.add(sysMenu);//将系统菜单添加到菜单栏上
46       setJMenuBar(menuBar);//将menuBar设置为菜单栏
47       
48       toolbar=new JPanel();//工具面板实例化
49       //三个按钮初始化
50       startButton=new JButton("重新开始");
51       exitButton=new JButton("退出");
52       backButton=new JButton("悔棋");
53       //将工具面板按钮用FlowLayout布局
54       toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));
55       //将三个按钮添加到工具面板
56       toolbar.add(startButton);
57       toolbar.add(exitButton);
58       toolbar.add(backButton);
59       //将三个按钮注册监听事件
60       startButton.addActionListener(lis);
61       exitButton.addActionListener(lis);
62       backButton.addActionListener(lis);
63       //将工具面板布局到界面”南方“也就是下方
64       add(toolbar,BorderLayout.SOUTH);
65       add(chessBoard);//将面板对象添加到窗体上
66       //设置界面关闭事件
67       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
68       //setSize(800,800);
69       pack();//自适应大小
70       
71   }
72   
73   private class MyItemListener implements ActionListener{
74       public void actionPerformed(ActionEvent e){
75           Object obj=e.getSource();//获得事件源
76           if(obj==StartChessJFrame.this.startMenuItem||obj==startButton){
77               //重新开始
78               //JFiveFrame.this内部类引用外部类
79               System.out.println("重新开始");
80               chessBoard.restartGame();
81           }
82           else if (obj==exitMenuItem||obj==exitButton)
83               System.exit(0);
84           else if (obj==backMenuItem||obj==backButton){
85               System.out.println("悔棋...");
86               chessBoard.goback();
87           }
88       }
89   }
90   
91   
92   
93   public static void main(String[] args){
94       StartChessJFrame f=new StartChessJFrame();//创建主框架
95       f.setVisible(true);//显示主框架
96       
97   }
98 }

 

posted @ 2015-12-30 00:15  伊甸一点  阅读(572)  评论(0编辑  收藏  举报