码迷,mamicode.com
首页 > 编程语言 > 详细

JAVA小项目之五子棋

时间:2015-09-06 12:35:59      阅读:294      评论:0      收藏:0      [点我收藏+]

标签:

  五子棋V1.0

  功能:

  1. 人人对战,人机对战(初级)
  2. 记录双方分数;

     主要知识点:

   二维坐标系中,各方向坐标的关系及规律。

效果图:

   "传不了图片?"

  • 主框架类:
技术分享
  1 package com.gxlee.wzq;
  2 
  3 /**
  4  *五子棋 Java版 V1.0
  5  *@author  http://www.cnblogs.com/HFLY
  6  *时间2005-8-20
  7  *功能:人机对战 人人对战
  8  */
  9 import java.awt.Color;
 10 import java.awt.Container;
 11 import java.awt.Font;
 12 import java.awt.Graphics;
 13 import java.awt.event.ActionEvent;
 14 import java.awt.event.ActionListener;
 15 import java.awt.event.MouseAdapter;
 16 import java.awt.event.MouseEvent;
 17 import java.awt.image.BufferedImage;
 18 import java.util.ArrayList;
 19 import java.util.List;
 20 
 21 import javax.swing.ButtonGroup;
 22 import javax.swing.JButton;
 23 import javax.swing.JComboBox;
 24 import javax.swing.JFrame;
 25 import javax.swing.JPanel;
 26 import javax.swing.JRadioButton;
 27 
 28 @SuppressWarnings("serial")
 29 public class MainFrame extends JFrame {
 30     private JButton btStart = new JButton("开始");
 31 
 32     private JComboBox model = new JComboBox(new Object[] { "人机对战", "人人对战" });
 33     private JRadioButton jr1 = new JRadioButton("电脑先下");
 34     private JRadioButton jr2 = new JRadioButton("自己先下");
 35     private JRadioButton level1 = new JRadioButton("难");
 36     private JRadioButton level2 = new JRadioButton("中");
 37     private JRadioButton level3 = new JRadioButton("易");
 38     private boolean myOrder = true;// false 对方,true 自己
 39     private boolean gameOver = true;// false 游戏结束
 40     private boolean win = false;
 41     private int advCouner;// 对方赢的次数
 42     private int myCouter;// 自己赢的次数
 43     private List<Chess> myChess = new ArrayList<Chess>();// 自己的棋
 44     private List<Chess> advChess = new ArrayList<Chess>();// 对方的棋
 45     private List<Chess> allChess = new ArrayList<Chess>();// 所有的棋
 46     private int gameModel = 0;// 0 人机模式,1人人模式
 47 
 48     public MainFrame() {
 49         // 构造函数
 50         this.setTitle("五子棋  v1.0");
 51         this.setSize(Utils.WIDTH, Utils.HEIGHT);
 52         this.setDefaultCloseOperation(EXIT_ON_CLOSE);
 53         this.setLocationRelativeTo(null);
 54         this.setResizable(false);
 55         Mypanel zb = new Mypanel();
 56         zb.setLayout(null);
 57 
 58         // 添加难易 人机模式时才可选
 59         level1.setBackground(new Color(224, 192, 0));
 60         level2.setBackground(new Color(224, 192, 0));
 61         level3.setBackground(new Color(224, 192, 0));
 62         level1.setBounds(Utils.IMAGE_WIDTH + (Utils.WIDTH - Utils.IMAGE_WIDTH)
 63                 / 2 - 53, Utils.HEIGHT - 290, 100, 30);
 64         level2.setBounds(Utils.IMAGE_WIDTH + (Utils.WIDTH - Utils.IMAGE_WIDTH)
 65                 / 2 - 53, Utils.HEIGHT - 260, 100, 30);
 66         level3.setBounds(Utils.IMAGE_WIDTH + (Utils.WIDTH - Utils.IMAGE_WIDTH)
 67                 / 2 - 53, Utils.HEIGHT - 230, 100, 30);
 68         level3.setSelected(true);
 69         zb.add(level1);
 70         zb.add(level2);
 71         zb.add(level3);
 72         ButtonGroup group1 = new ButtonGroup();
 73         group1.add(level1);
 74         group1.add(level2);
 75         group1.add(level3);
 76 
 77         // 添加模式
 78         model.setBounds(Utils.IMAGE_WIDTH + (Utils.WIDTH - Utils.IMAGE_WIDTH)
 79                 / 2 - 53, Utils.HEIGHT - 180, 100, 30);
 80         model.addActionListener(new ActionListener() {
 81 
 82             @Override
 83             public void actionPerformed(ActionEvent e) {
 84                 // String(model.getSelectedItem());
 85 
 86                 switch (model.getSelectedIndex()) {
 87                 case 0:
 88                     gameModel = 0;
 89                     jr1.setText("电脑先下");
 90                     break;
 91                 case 1:
 92                     gameModel = 1;
 93                     jr1.setText("对方先下");
 94                     break;
 95                 default:
 96                     break;
 97                 }
 98             }
 99 
100         });
101         zb.add(model);
102 
103         // 添加谁先下:
104         jr1.setBounds(Utils.IMAGE_WIDTH + (Utils.WIDTH - Utils.IMAGE_WIDTH) / 2
105                 - 53, Utils.HEIGHT - 150, 80, 30);
106         jr1.setBackground(new Color(224, 192, 0));
107         jr1.setForeground(Color.WHITE);
108         jr1.addActionListener(new ActionListener() {
109 
110             @Override
111             public void actionPerformed(ActionEvent e) {
112                 myOrder = false;// 轮到对方出棋
113             }
114 
115         });
116         zb.add(jr1);
117         jr2.setBounds(Utils.IMAGE_WIDTH + (Utils.WIDTH - Utils.IMAGE_WIDTH) / 2
118                 - 53, Utils.HEIGHT - 120, 80, 30);
119         jr2.setBackground(new Color(224, 192, 0));
120         jr2.setForeground(Color.WHITE);
121         jr2.addActionListener(new ActionListener() {
122 
123             @Override
124             public void actionPerformed(ActionEvent e) {
125                 myOrder = true;// 自己先下;
126             }
127 
128         });
129         jr2.setSelected(true);// 默认自己先下
130         zb.add(jr2);
131         ButtonGroup group2 = new ButtonGroup();
132         group2.add(jr1);
133         group2.add(jr2);
134         // 添加开始按钮
135         btStart.setBounds(Utils.IMAGE_WIDTH + (Utils.WIDTH - Utils.IMAGE_WIDTH)
136                 / 2 - 53, Utils.HEIGHT - 90, 100, 30);
137         btStart.addActionListener(new ActionListener() {
138 
139             @Override
140             public void actionPerformed(ActionEvent e) {
141                 // 复位
142                 gameOver = false;
143                 win = false;
144                 myChess.clear();
145                 advChess.clear();
146                 allChess.clear();
147                 // 其他复位的地方
148                 btStart.setText("再来一局");
149                 // 谁出?
150                 myOrder = jr1.isSelected() ? false : true;
151                 if (!myOrder) {
152                     computerGetNextChess();
153                     myOrder = true;
154                 }
155                 repaint();
156             }
157         });
158         zb.add(btStart);
159         zb.addMouseListener(new MouseClick());
160         Container c = this.getContentPane();
161         c.add(zb);
162 
163         this.setVisible(true);
164     }
165 
166     private class MouseClick extends MouseAdapter {
167 
168         @Override
169         public void mouseClicked(MouseEvent e) {
170 
171             // 如果是游戏结束状态
172             if (gameOver) {
173                 return;
174             }
175             // 若是人机模式,并且当前是对方出的时候
176             if (gameModel == 0 && !myOrder) {
177                 return;
178             }
179             if (e.getX() > 430) // 坐标越界
180                 return;
181 
182             int x = e.getX();
183             int y = e.getY() > 420 ? 420 : e.getY();
184             int xIndex = (x - 18) / 25 + ((x - 18) % 25 > 25 / 2 ? 1 : 0);
185             int yIndex = (y - 18) / 25 + ((y - 18) % 25 > 25 / 2 ? 1 : 0);
186 
187             boolean result = addChess(new Chess(xIndex, yIndex), myOrder);
188             if (result) {
189                 // 先绘画
190                 repaint();
191                 // 检查是否有输赢
192                 if (gameOver = checkResult(xIndex, yIndex)) {
193                     win = true;
194                     return;
195                 } else {
196                     // 交换顺序
197                     myOrder = !myOrder;
198                     // 如果没有赢的时候,人机模式需要调用电脑出棋
199                     if (gameModel == 0) {
200                         if (gameOver = computerGetNextChess()) {
201                             win = true;
202                             return;
203                         }
204                         myOrder = true;
205                     }
206                 }
207             }
208         }
209     }
210 
211     /**
212      * 电脑自动下棋的方法
213      * 
214      * @return
215      */
216     public boolean computerGetNextChess() {
217         // 电脑出 最大索引为 16;
218         int xIndex = Utils.r.nextInt(17);
219         int yIndex = Utils.r.nextInt(17);
220         // 如果没有棋 并且是电脑模式自己先出
221         if (myChess.size() == 0 && advChess.size() == 0) {// 这是表示是电脑先出
222             addChess(new Chess(xIndex, yIndex), advChess);
223             return false;
224         } else if (myChess.size() == 1 && advChess.size() == 0) {// 玩家先出
225             // 这个完全是多余的 纯粹增加花样
226             // 可以在玩的周边出一个
227             // 得到个随机数,在他的的哪个方向即偏移地址
228             Chess myCh = myChess.get(0);
229             int offset = 1;// Utils.r.nextInt(15)+1;//偏移距离
230             int rndX = Utils.r.nextInt(2);
231             int rndY = Utils.r.nextInt(2);
232             int rX = rndX == 0 ? -1 : 1;
233             int rY = rndY == 0 ? -1 : 1;
234             while (!addChess(new Chess(myCh.getxIndex() + rX * offset, myCh
235                     .getyIndex()
236                     + rY * offset), advChess)) {
237                 rndX = Utils.r.nextInt(2);
238                 rndY = Utils.r.nextInt(2);
239                 rX = rndX == 0 ? -1 : 1;
240                 rY = rndY == 0 ? -1 : 1;
241             }
242             return false;
243         }
244 
245         // 这时,如果自己要赢了就开始赢
246         Chess c = getBestChess(advChess, true);
247         if (checkResult(c.getxIndex(), c.getyIndex(), advChess)) {
248             return addChess(c, advChess);
249         }
250         // 电脑防御模式,如果玩家有只要放入一个棋可以达到4分,就要进行防御
251         Chess advC = getBestChess(myChess, false);
252         if (advC == null) {
253             advC = c;
254         }
255         addChess(advC, advChess);
256         return false;// checkResult(c.getxIndex(),c.getyIndex());//是否胜
257     }
258 
259     /**
260      * 得到玩家可能要赢了的点 玩家4分的点也要控制 得到一个可以最大分数的点 最佳的点
261      * 
262      * @param playerChess
263      * @param flag
264      *            标示电脑的棋还是玩家的棋 玩家的话 如果分数小于4则不要
265      * @return
266      */
267     public Chess getBestChess(List<Chess> playerChess, boolean flag) {
268         int maxScore = -1;
269         int score = -1;
270         int maxScoreX = -1;
271         int maxScoreY = -1;
272         int xIndex = -1, yIndex = -1;
273         geted: for (Chess c : playerChess) {
274             xIndex = c.getxIndex();
275             yIndex = c.getyIndex();
276             // 左边 {-1,0},右边{1,0},左上角的{-1,-1}....
277             for (int i = -1; i <= 1; i++) {
278                 for (int j = -1; j <= 1; j++) {
279                     // 不能同时为零0
280                     if (i == j && i == 0)
281                         continue;
282                     score = Utils.getBestPointScore(xIndex + i, yIndex + j,
283                             allChess, playerChess);
284                     if (score >= maxScore) {
285                         maxScore = score;
286                         maxScoreX = xIndex + i;
287                         maxScoreY = yIndex + j;
288                         if (maxScore >= 5)
289                             break geted;
290                     }
291                 }
292             }
293         }
294         // 如果此时再判断玩家的棋
295         if (!flag) {
296             if (maxScore < 4)
297                 return null;
298         }
299         return new Chess(maxScoreX, maxScoreY, true);
300     }
301 
302     public boolean checkResult(int x, int y, List<Chess> playerChess) {
303         int scorePre = 0; // 这个点的左,左上,上 ,左下能得分
304         int socreNext = 0;// 这个点的 右,右下,下,右上
305         int score = 0;
306         int maxScore = 0;
307         int offsetX, offsetY;
308         /**
309          * 前半段 后半段 X Y X Y 横 向 -1 0 1 0 竖 向 0 -1 0 1 下上斜 -1 1 1 -1 上下斜 -1 -1 1 1
310          */
311         for (int i = -1; i <= 0; i++) {
312             for (int j = -1; j <= 1; j++) {
313                 if (i == j && i == 0)
314                     continue;
315                 if (0 == 0 && y == 1)
316                     continue;// 不判断也可以
317                 // 前半段
318                 offsetX = i;
319                 offsetY = j;
320                 scorePre = Utils.getPointScore(x, y, offsetX, offsetY,
321                         playerChess);
322                 // 后半段
323                 offsetX = -i;
324                 offsetY = -j;
325                 socreNext = Utils.getPointScore(x, y, offsetX, offsetY,
326                         playerChess);
327                 score = scorePre + socreNext + 1;
328                 maxScore = score >= maxScore ? score : maxScore;
329                 if (maxScore >= 5)
330                     return true;
331             }
332         }
333         return false;
334     }
335 
336     /**
337      * 重载,检查是否赢了
338      * 
339      * @param x
340      * @param y
341      * @return
342      */
343     public boolean checkResult(int x, int y) {
344         List<Chess> playerChess = myOrder ? myChess : advChess;
345         return checkResult(x, y, playerChess);
346     }
347 
348     /**
349      * 添加棋的方法
350      * 
351      * @param chess
352      * @param playerChess
353      * @return
354      */
355     public boolean addChess(Chess chess, List<Chess> playerChess) {
356         // 判断是否越界
357         if (chess.getxIndex() < 0)
358             return false;
359         if (chess.getxIndex() > 16)
360             return false;
361         if (chess.getyIndex() < 0)
362             return false;
363         if (chess.getyIndex() > 16)
364             return false;
365         // 重载
366         if (allChess.contains(chess)) {
367             return false;
368         }
369         Chess c = new Chess(chess);
370         // 没有被占用的话
371         allChess.add(c);
372         return playerChess.add(c);
373     }
374 
375     //
376     /**
377      * 重载 添加棋的方法
378      * 
379      * @param chess
380      * @param myOrder
381      * @return
382      */
383     public boolean addChess(Chess chess, boolean myOrder) {
384         List<Chess> playerChess = myOrder ? myChess : advChess;
385         return addChess(chess, playerChess);
386     }
387 
388     /**
389      * 画图容器
390      * 
391      * @author
392      * 
393      */
394     public class Mypanel extends JPanel {
395 
396         @Override
397         protected void paintComponent(Graphics g) {
398 
399             // 画背景
400             g.drawImage(Utils.images.get("Board.gif"), 0, 0, this);
401             g.setColor(new Color(224, 192, 0));
402             g.fillRect(Utils.IMAGE_WIDTH, 0, Utils.WIDTH - Utils.IMAGE_WIDTH,
403                     Utils.HEIGHT);
404             g.setColor(Color.WHITE);
405             g.setFont(new Font("隶书", Font.PLAIN, 20));
406             // 画图标
407             g.drawString("当前:", Utils.IMAGE_WIDTH + 10, 52);// 让电脑延时几秒再出其
408             BufferedImage img = Utils.images.get("white.gif");
409             if (!myOrder) {
410                 img = Utils.images.get("black.gif");
411             }
412             g.drawImage(img, Utils.IMAGE_WIDTH + 70, 35, this);
413 
414             // 画框
415             g.drawRect(Utils.IMAGE_WIDTH, 20, Utils.WIDTH - Utils.IMAGE_WIDTH
416                     - 10, Utils.HEIGHT - 68);
417             // 画自己的棋
418             img = Utils.images.get("white.gif");
419             for (Chess c : myChess) {
420                 g.drawImage(img, c.getX(), c.getY(), this);
421             }
422             // 画对方的棋
423             img = Utils.images.get("black.gif");
424             for (Chess c : advChess) {
425                 g.drawImage(img, c.getX(), c.getY(), this);
426             }
427             // 画赢了
428             if (gameOver && win) {
429                 // 谁赢了?
430                 String name = "";
431                 if (myOrder) {
432                     myCouter++;
433                     name = (gameModel == 1) ? "白方" : "我";
434                 } else {
435                     advCouner++;
436                     name = (gameModel == 0) ? "电脑" : "黑方";// 电脑模式
437                 }
438                 g.setFont(new Font("隶书", Font.BOLD, 65));
439                 g.setColor(Color.WHITE);
440                 g.drawString(name + "赢了!", 100, 200);
441                 g.setFont(new Font("隶书", Font.BOLD, 65));
442                 g.setColor(Color.RED);
443                 g.drawString(name + "赢了!", 100, 202);
444             }
445             // 画战绩:
446             g.setFont(new Font("楷体", Font.PLAIN, 15));
447             g.setColor(Color.WHITE);
448             g.drawString(((gameModel == 1) ? "黑方(赢):" : "电脑(赢):") + advCouner,
449                     Utils.IMAGE_WIDTH + 10, 100);
450             g.drawString(((gameModel == 1) ? "白方(赢):" : "  我(赢):") + myCouter,
451                     Utils.IMAGE_WIDTH + 10, 120);
452 
453         }
454     }
455 
456     public static void main(String[] args) {
457         new MainFrame();
458     }
459 
460 }
View Code
  • 棋子类:
技术分享
 1 package com.gxlee.wzq;
 2 
 3 /**
 4  * 棋
 5  * @author http://www.cnblogs.com/HFLY
 6  *
 7  */
 8 public class Chess {
 9     private int x;// x坐标
10     private int y;// y 坐标
11     private int xIndex;
12     private int yIndex;
13 
14     // 构造函数
15     public Chess(int xIndex, int yIndex) {
16         super();
17         this.xIndex = xIndex;
18         this.yIndex = yIndex;
19         this.x = xIndex * 25 + 18 - 12;// 通过格子求出十字架的位置 12 是棋子的一半
20         this.y = yIndex * 25 + 20 - 12;
21     }
22 
23     public Chess(Chess c) {
24         this.xIndex = c.getxIndex();
25         this.yIndex = c.getyIndex();
26         this.x = xIndex * 25 + 18 - 12;// 
27         this.y = yIndex * 25 + 20 - 12;
28     }
29 
30     public Chess(int xIndex, int yIndex, boolean checkFlag) {
31         super();
32         this.xIndex = xIndex;
33         this.yIndex = yIndex;
34     }
35 
36     @Override
37     public boolean equals(Object obj) {
38         if (obj instanceof Chess) {
39             Chess c = (Chess) obj;
40             if (c.xIndex == this.xIndex && c.yIndex == this.yIndex) {
41                 return true;
42             }
43         }
44         return false;
45     }
46 
47     public int getxIndex() {
48         return xIndex;
49     }
50 
51     public void setxIndex(int xIndex) {
52         this.xIndex = xIndex;
53     }
54 
55     public int getyIndex() {
56         return yIndex;
57     }
58 
59     public void setyIndex(int yIndex) {
60         this.yIndex = yIndex;
61     }
62 
63     public int getX() {
64         return x;
65     }
66 
67     public void setX(int x) {
68         this.x = x;
69     }
70 
71     public int getY() {
72         return y;
73     }
74 
75     public void setY(int y) {
76         this.y = y;
77     }
78 
79 }
View Code
  • 工具类:
技术分享
  1 package com.gxlee.wzq;
  2 
  3 import java.awt.image.BufferedImage;
  4 import java.io.File;
  5 import java.io.IOException;
  6 import java.util.HashMap;
  7 import java.util.List;
  8 import java.util.Map;
  9 import java.util.Random;
 10 
 11 import javax.imageio.ImageIO;
 12 
 13 /**
 14  * 工具类
 15  * @author http://www.cnblogs.com/HFLY
 16  *
 17  */
 18 public class Utils {
 19     public static Random r = new Random();
 20     public static Map<String,BufferedImage> images = new HashMap<String,BufferedImage>();
 21     public static final int WIDTH = 560;//游戏界面的宽
 22     public static final int IMAGE_WIDTH = 437;
 23     public static final int HEIGHT = 465;//游戏界面的高
 24     static{
 25         File dir = new File("src/img");
 26         File[] files = dir.listFiles();
 27         for (File file : files) {
 28             BufferedImage img;
 29             try {
 30                 img = ImageIO.read(file);
 31                 images.put(file.getName(), img);
 32             } catch (IOException e) {
 33                 e.printStackTrace();
 34             }
 35         }
 36         
 37     }
 38 
 39 
 40 /**电脑出棋时判断双方最佳点的方法
 41  * @param x
 42  * @param y
 43  * @param allChess
 44  * @param playerChess 传入哪方就得出哪方最佳点
 45  * @return
 46  
 47  */
 48 public static int getBestPointScore(int x,int y,List<Chess> allChess,List<Chess> playerChess){
 49     //坐标越界
 50     if(x<0) return -1;
 51     if(x>16) return -1;
 52     if(y<0) return -1;
 53     if(y>16) return -1;
 54     //如果这个点被电脑占用了 则不能使用
 55     if(allChess.contains(new Chess(x,y))) return -1;
 56     // 向前延伸得分加上向后加当前1分为总得分
 57     int scorePre=0; //这个点的左,左上,上 ,左下能得分
 58     int socreNext=0;//这个点的 右,右下,下,右上
 59     int score = 0 ;
 60     int maxScore = 0;
 61     int offsetX,offsetY;
 62     /**
 63      *         前半段    后半段    
 64              X    Y    X    Y
 65     横      向    -1     0    1    0
 66      竖     向    0    -1    0    1
 67     下上斜    -1     1    1    -1
 68     上下斜    -1    -1    1    1
 69      */
 70     geted:for (int i = -1; i <=0; i++) {
 71         for(int j = -1;j<=1;j++){
 72             if(i==j && i==0) continue;
 73             //前半段
 74             offsetX = i;offsetY = j;
 75             scorePre = getPointScore(x,y,offsetX,offsetY,playerChess);
 76             //后半段
 77             offsetX = i*(-1);offsetY = j*(-1);
 78             socreNext = getPointScore(x,y,offsetX,offsetY,playerChess);
 79             score = scorePre+socreNext+1;
 80             maxScore = score>=maxScore?score:maxScore;
 81             if (maxScore>=5) break geted;
 82         }
 83     }
 84     return maxScore;
 85 }
 86 
 87 /**每一点的得分
 88  * @param x
 89  * @param y
 90  * @param offsetX
 91  * @param offsetY
 92  * @param playerChess
 93  * @return
 94  */
 95 public static int getPointScore(int x,int y,int offsetX,int offsetY,List<Chess> playerChess){
 96     int score = 0;
 97     int xAdd = offsetX;
 98     int yAdd = offsetY;
 99     while (playerChess.contains(new Chess(x+offsetX,y+offsetY))) {
100          score ++;
101          offsetX += xAdd;
102          offsetY += yAdd;
103     } 
104     return score;
105 }
106 }
View Code
  •  素材
  1. 棋盘
  2. 黑棋
  3. 白棋

JAVA小项目之五子棋

标签:

原文地址:http://www.cnblogs.com/Hfly/p/4770644.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!