本文介绍用swing编写连连看的基本思路,代码是交叉编的,写的太零碎的话不方便拷贝运行就写一起了。
程序组成:UI 基本数据 算法
一、数据
常量数据部分:
1.玩过连连看的都知道,连连看基本都是网格结构,每个格子里面都存放着图片、位置和图片存在对应关系,适合这个顺序结构的适合用数组来处理。所以我们需要一个数组来存放图片,数组的下标与该数组元素 的图片的这种对应关系很重要!
2.我们为了方便修改数组的大小来方便以后定义游戏难度什么的,需要将数组的大小设置一个常量。
3.图片的大小这个经常会用也设置成常量。
**在写算法的时候我们需要一些队列来保存一些需要跨类使用的点。
为方便使用,我们将这些常量定义成接口,方便使用,代码如下:
package fly; import java.awt.Point; import java.util.ArrayList; import javax.swing.ImageIcon; /** * 用来定义常量的接口 */ public interface Config { // 游戏中可能使用到的数据 // 开始放置图片的左上角的位置 public static final int X0 = 60; public static final int Y0 = 30; // 图片的大小 public static final int SIZE = 30; // 总行数和列数 public static final int ROWS = 8; public static final int COLS = 12; // 定义一个数组来存放需要显示在面板上的所有图片 public static ImageIcon[][] ICONS = new ImageIcon[ROWS][COLS]; //定义一个数组用来保存被消除的格子的中心点坐标和转折点的坐标 //当消除的时候可以使用连线提示被消除的格子经过的线路 public static ArrayList<Point> list = new ArrayList<Point>(); //选择的时候的提示框 public static ArrayList<Point> list2 = new ArrayList<Point>(); }
二、UI制作
UI分为图片、面板、窗体这三部分
窗体好解决用JFrame添加一些组件,做好布局即可;面板差不多使用JPanel,不过可能要重写paint方法。解决好图片的摆放、绘制问题
这个UI就好办了。
关于图片有一个不好处理的地方:1、要保证随机的每种图片是偶数张。
解决这个问题有2个办法:a.由系统自由随机图片 然后检查图片是否能保证偶数张。
b.一次随机得到图片后将图片保存2次,再随机位置
由于a方法可能造成程序死循环、效率比较低,我们一般采用b方法。
代码如下:
//装载图片 public void initPicData() { // 用来存储图片的临时队列 ArrayList<ImageIcon> iconList = new ArrayList<ImageIcon>(); // 定义随机数对象,随机图片 Random rd = new Random(); // 循环所需图片个数的一半,每随机一张图片,就往队列中放两次 // 结果是:队列中的图片总数就是所需要的图片数,保证每张图片都是偶数个 for (int i = 0; i < ROWS * COLS / 2; i++) { int num = rd.nextInt(10); // 拼接图片路径字符串(我的图片都是0.gif这种用数字命名的方便随机) String url = "imgs/" + num + ".gif"; // 创建图片对象 ImageIcon icon = new ImageIcon(url); // 将图片放入队列中,每张图片装两次 iconList.add(icon); iconList.add(icon); } // 将队列中的图片随机取出,放入二维数组 for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { // 从队列中随机取一个下标 int index = rd.nextInt(iconList.size()); // 根据下标取得队列中的一张图片 // remove方法是取出并移除该下标位置的元素 ICONS[i][j] = iconList.remove(index); } } }
注意:由于我们的游戏面板是动态变化的,需要不停刷新,所以我们需要重写JPanel的paint方法!
class MyPanel extends JPanel { @Override public void paint(Graphics g) { super.paint(g); // 循环取出二维数组中的图片,绘制出来 for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { ImageIcon img = ICONS[i][j]; if (img != null) { // 计算图片的下标 g.drawImage(img.getImage(), X0 + SIZE * j, Y0 + SIZE * i, SIZE, SIZE, null); } } } } }
由于我们是通过鼠标点击面板玩游戏,所以需要给面板添加鼠标监听器。
代码如下:
// 绘窗体 public void initUI() { // 设置窗体标题 this.setTitle("连连看"); // 设置窗体大小 this.setSize(600, 400); // 设置窗体不可更改大小 this.setResizable(false); // 设置关闭窗体后结束窗体这个线程 this.setDefaultCloseOperation(3); // 添加游戏区域面板(这个Mypanel后面会有) JPanel gamePanel = new MyPanel(); gamePanel.setBackground(Color.BLACK); // 将面板添加到窗体 this.add(gamePanel); // 设置窗体可见 this.setVisible(true); // 得到画布,Graphics2D有比Graphics更多的方法 Graphics2D g = (Graphics2D) gamePanel.getGraphics(); // 创建鼠标监听器 LLKListener lis = new LLKListener(g); // 给面板添加鼠标监听器 gamePanel.addMouseListener(lis); }
然后在添加上main方法
public static void main(String[] args) { //创建窗体对象 LlkFrame llk = new LlkFrame(); // 调用方法初始化数据 //装载图片 llk.initPicData(); //绘制窗体、面板 llk.initUI(); }
查看已经初始化的界面,可以发现图片完全满足要求
三、算法部分
用来处理监听器传来的鼠标对应的位置的数组下标判断两个图片是否能够消除。
这里我们主要考虑3种情况:
A.2张图片不转折直接就可以消除,这又有2种情况,a.2张图片同一行时;b.2张图片同一列时
代码如下:
// 检测一行是否连通 public static boolean checkRow(int r1, int c1, int r2, int c2) { // 只考虑同行的情况 if (r1 == r2) { int min = Math.min(c1, c2); int max = Math.max(c1, c2); // 不要包含c1,c2两个位置 for (int i = min + 1; i < max; i++) { if (ICONS[r1][i] != null) { return false; } } list.add(new Point(r1, c1)); list.add(new Point(r2, c2)); // 如果for循环执行完了,还没有false,则证明中间都是null return true; } else { return false; } } // 检测一列是否连通 public static boolean checkCol(int r1, int c1, int r2, int c2) { if (c1 == c2) { int min = Math.min(r1, r2); int max = Math.max(r1, r2); for (int i = min + 1; i < max; i++) { if (ICONS[i][c1] != null) { return false; } } list.add(new Point(r1, c1)); list.add(new Point(r2, c2)); return true; } else { return false; } }
B.2张图片通过线段连线转折一次直接就可以消除,这又有2种情况,a.转折点为转折点为r1c2;b 转折点为r2c1
代码如下:
// 有一个转折点的 public static boolean onePoint(int r1, int c1, int r2, int c2) { // 转折点为r1c2 if (ICONS[r1][c2] == null) { if (checkRow(r1, c1, r1, c2) && checkCol(r2, c2, r1, c2)) { return true; } } // 转折点为r2c1 if (ICONS[r2][c1] == null) { if (checkRow(r2, c2, r2, c1) && checkCol(r1, c1, r2, c1)) { return true; } } return false; }
C.2张图片通过线段连线转折二次直接就可以消除,这又有2种情况,a.先往水平方向连线,恰好2个转折点在同列;
b.先往垂直方向连线,恰好2个转折点在同一行
代码如下:
// 水平移动 public static boolean twoPointH(int r1, int c1, int r2, int c2) { // 定义一个变量表示两个转折点的列下标 for (int i = 0; i < COLS; i++) { // 转折点为r1,i和r2,i if (ICONS[r1][i] == null && ICONS[r2][i] == null) { if (checkRow(r1, i, r1, c1) && checkRow(r2, i, r2, c2) && checkCol(r1, i, r2, i)) { return true; } } } return false; } // 垂直移动 public static boolean twoPointV(int r1, int c1, int r2, int c2) { for (int i = 0; i < ROWS; i++) { if (ICONS[i][c1] == null && ICONS[i][c2] == null) { if (checkRow(i, c1, i, c2) && checkCol(r1, c1, i, c1) && checkCol(r2, c2, i, c2)) { return true; } } } return false; }
四、监听器部分
我们需要通过鼠标点击玩游戏,做一些动态交互。主要是得到鼠标点的坐标后做一系列的判断操作。
将鼠标所在位置对应图片:
private ImageIcon getIconByLocation(int x, int y) { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { // 获得该图片左上角的坐标 int x1 = X0 + SIZE * j; int y1 = Y0 + SIZE * i; // 如果在范围内,表示当次选中的是,i,j位置的数据 if (x - x1 < SIZE && y - y1 < SIZE) { // 取出数组中ij位置的数据 ImageIcon icon = ICONS[i][j]; return icon; } } } return null; }
要想在连连看的面板上绘图需要从外部传入画布(一般通过构造方法最方便)
public LLKListener(Graphics2D g) { this.g = g; // 设置线条的粗细 this.g.setStroke(new BasicStroke(5)); this.g.setColor(Color.RED); }
监听器mouseReleased方法(用来得到鼠标释放时所在的点,并进行相应处理)
public void mouseReleased(MouseEvent e) { // 获得事件源对象:产生事件的对象,即为游戏面板 JPanel panel = (JPanel) e.getSource(); // 获得光标按下的位置 int x = e.getX(); int y = e.getY(); // 保存坐标,用于绘制提示框 int r = (y - Y0) / SIZE; int c = (x - X0) / SIZE; int xp = X0 + c * SIZE; int yp = Y0 + r * SIZE; //将这个点添加进提示框点的队列中 list2.add(new Point(xp, yp)); //在点击的点所在的图片位置绘制矩形 g.drawRect(xp, yp, SIZE, SIZE); if (count == 0) { icon1 = getIconByLocation(x, y); // 根据坐标计算下标 i1 = (y - Y0) / SIZE; j1 = (x - X0) / SIZE; System.out.println(i1 + " " + j1); count++; } else { icon2 = getIconByLocation(x, y); i2 = (y - Y0) / SIZE; j2 = (x - X0) / SIZE; // 当第二次点击完毕,就开始判断两次选中的图片是不是一样的 // System.out.println(icon1 + "<>" + icon2); // 都不为空,且不是同一个位置,且图片名称相同 if (icon1 != null && icon2 != null && (i1 != i2 || j1 != j2) && icon1.toString().equals(icon2.toString())) { if (SuanFa.checkRow(i1, j1, i2, j2) || SuanFa.checkCol(i1, j1, i2, j2) || SuanFa.onePoint(i1, j1, i2, j2) || SuanFa.twoPointH(i1, j1, i2, j2) || SuanFa.twoPointV(i1, j1, i2, j2)) { // 先绘制提示线 for (int i = 0; i < list.size(); i += 2) { Point p1 = list.get(i); Point p2 = list.get(i + 1); // 将下标转成坐标 int x1 = X0 + p1.y * SIZE + SIZE / 2; int y1 = Y0 + p1.x * SIZE + SIZE / 2; int x2 = X0 + p2.y * SIZE + SIZE / 2; int y2 = Y0 + p2.x * SIZE + SIZE / 2; g.drawLine(x1, y1, x2, y2); } // 清空队列 list.clear(); //添加一下延迟,方便查看画出来的线条 try { Thread.sleep(1000); } catch (Exception e1) { e1.printStackTrace(); } // g.draw ICONS[i1][j1] = null; ICONS[i2][j2] = null; System.out.println("相同,可消除"); } } // 刷新一下 panel.repaint(); count--; } }
相关推荐
java小游戏 (源码+视频+文档+ppt) swing连连看游戏java小游戏 (源码+视频+文档+ppt) swing连连看游戏java小游戏 (源码+视频+文档+ppt) swing连连看游戏java小游戏 (源码+视频+文档+ppt) swing连连看游戏java小游戏 ...
使用java的swing框架实现连连看小游戏,带图片,可以自定义标题等。 使用java的swing框架实现连连看小游戏,带图片,可以自定义标题等。
用java做的一个连连看,绝对是你在校学习的好老师,居家旅行的好朋友!具体代码可见空间博客
java游戏 连连看 游戏开发 源代码
java swing实现的连连看小程序,导入eclipse即可运行,程序入口在com.lianliankan.setup.Setup.java
资源名字:基于java+swing+GUL的连连看游戏设计与实现(源码+文档)_JAVA_swing_GUL_连连看游戏.zip 资源类型:项目全套源码+文档+辅导视频 源码说明: 全部项目源码都是经过测试校正后百分百成功运行。 适合场景:...
这个是我参照网上自己写的连连看。代码写的不是特别好。很简单的,仅供新手学习。。。
NULL博文链接:https://wwwcomy.iteye.com/blog/2124789
这段代码实现了连连看游戏的 Swing UI。点击相同的方块可以消除它们。游戏面板是一个 8x8 的网格,其中每个方格都显示一个数字按钮。游戏开始时,随机生成两个不同的方块,并将其放置在网格中的两个不同位置。每次...
压缩包内容是自己制作的连连看游戏完整源码以及素材,按素材使用说明导入Eclipse运行即可。 Swing 连连看 源码 素材 游戏开发
Java Swing写的小游戏连连看的源代码。代码很简练。
NULL 博文链接:https://leiwuluan.iteye.com/blog/362623
一个简易连连看游戏, 主要是设计数据结构相关的知识, swing, 线程 等等
swing连连看例子,源自iteye,版权为原作者所有,仅共享学习 对于初学swing的同学还是很有启发的。不妨下一个学习一下
使用Java Swing组件设计,对于正在学习Java Swing组件或者对Java Gui技术感兴趣的同学,是很不错的练手项目,敲代码的同时又找到曾经儿时的游戏回忆。
JAVA 课程设计源码 连连看 SWING 完整代码 经典!!完美JAVA 课程设计源码 连连看 SWING 完整代码 经典!!完美JAVA 课程设计源码 连连看 SWING 完整代码 经典!!完美JAVA 课程设计源码 连连看 SWING 完整代码 经典...
完成连连看游戏中,将游戏中未消除的图片个数记录并重新随机放置等数量图片的功能模块。 (4)选择难度模块: 完成游戏中切换游戏难度并开始新一局游戏的模块。 (5)计时模块: 完成游戏中倒计时并显示提示...
java+swing水果连连看小游戏.zip
连连看游戏用Java Swing所写后,生成的EXE文件。双击就可以直接运行。
SWING图形界面。有声音。水果图片。只有一关