猿创征文|JAVA 实现《连连看》游戏

您所在的位置:网站首页 连连看游戏玩家 猿创征文|JAVA 实现《连连看》游戏

猿创征文|JAVA 实现《连连看》游戏

2024-02-02 02:25| 来源: 网络整理| 查看: 265

前言

连连看游戏顾名思义就是找出具有关联关系的事物并进行相应处理,经历了从桌面游戏、在线游戏再到社交游戏三个过程,形式多种多样。游戏的核心要求是将两个能用三根以内的直线连接的关联事物(相同事物)消除(或进行其他处理)。一般的连连看小游戏规则和操作都简单明了易上手,但也有很多新版本的连连看游戏加入了各类道具和游戏模式来丰富游戏内容,很好地增强了游戏的娱乐性,也带给玩家长期的挑战性和新鲜感。

《连连看》游戏用java语言实现,采用了swing技术进行了界面化处理,设计思路用了面向对象思想。

主要需求

在业务需求方面,第一,具备连连看基本游戏功能。选择两个图形,判断是否满足一定条件,条件即两个图形一致且二者之间存在转弯少于3的路径。当判定满足这一条件后,两张图片被消除。第二,具备附加功能:计时功能、重新开始功能、刷新当前界面功能等。 在用户需求有两个方面,一方面,要求游戏界面整齐美观,长时间使用也应尽可能的减小对游戏的审美疲劳。另一方面,要求游戏体验良好。在运行游戏的过程中,能保证数据安全,游戏能稳定、高速地运行。对于游戏本身,用户往往要求游戏功能相对完善,游戏具备可娱乐性,并且游戏规则易理解,游戏操作既要简单同时也应有难度,在保证游戏操作顺滑、响应快速的情况下,游戏能具有一定的挑战性。

主要设计

1、界面设计 游戏主界面以窗口形式给出,用户操作的游戏功能部分由各个组件构成,通过弹出的提示框开始游戏活动,用户通过点击窗口上的各个组件完成操作。 在游戏的界面上,还有一个特殊的面板,漏斗面板,漏斗面板上绘制了一个沙漏状的倒计时装置,该装置通过线程控制,时间变量每更新一次,漏斗面上重新绘制一次,每次绘制的线条通过判断条件设置摆放位置,随着时间的递增,沙漏状的倒计时装置就动态的开始倒计时,直至最后五秒,显示提示信息,倒计时结束后,弹出游戏失败提示框。 2、游戏执行的实现 因为每一次选择难度模式后、每通过一关游戏后都将开始一局新游戏。最终状态有两种,游戏失败和游戏结束。 3、记分、记关数的实现 游戏过程中,每消除一对相同图片,得分10,8×8格式的二维图片集,一共64张图片,共计32对,所以每过一关得分是320分,消除34对后的得分。在每一难度下的每一关通过后,记分不清0,继续记分。但切换到不同难度时,得分会清0 4、刷新功能的实现 游戏中每一关只有一次使用刷新功能的机会,此功能键触发的响应事件,会调用chongzai()方法,按照当前状态未消除的图片个数重新在二维按钮排列的其他位置排放其他图片。 5、重新开始游戏功能的实现 重新开始游戏功能实际也是开始新游戏功能,重新开始布局的过程。将图片成对的显示在场景中,并打乱调用的是newMap()方法。在该方法中,用了一个数组以数字标记的形式来记录加载的图片是哪种图片,在每次加载图片的时候是一张图片连续加载两次,以保证加载图片成对。然后用数组的随机方法将数组打乱。 6、游戏的连接算法 连连看游戏中对于用户来说最简单的呈现,就是单击两个连在一起的相同的图像时,这两个图像就会消去,但是在Java代码中是如何实现的呢?连连看游戏的联通算法一般包括回溯法和堆栈实现的迷宫算法。 根据游戏规则能知道,即使不是紧邻的两个相同的图像块消去时也不能超过两次转弯。

功能截图

游戏开始主界面: 这是简单模式: 在这里插入图片描述

中等模式: 在这里插入图片描述 困难模式: 在这里插入图片描述 变态模式: 在这里插入图片描述

代码实现 public class LianLianKan extends JFrame { private static final long serialVersionUID = 1L; public LianLianKan() { LianLianKanJPanel llk = new LianLianKanJPanel(); add(llk); } class LianLianKanJPanel extends JPanel implements ActionListener,ItemListener { private static final long serialVersionUID = 1L;//序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性。 private int[][] map = new int[8][8];//8*8的正方形 private int kind, randomx, randomy, randomx1, randomy1; // 种类,随机x private int coordinatex, coordinatey, coordinatex1, coordinatey1; // 坐标X private Point lineStart = new Point(0, 0); private int clicktimes; private int jishushengyu;//计数剩余 private int Kinds = 4; private int score; private int guanshu;//关数 loudou ld = new loudou();// 漏斗 JButton BlockButton[][] = new JButton[8][8];// Choice difficultChoice = new Choice(); JButton newgameButton = new JButton("重新开始"); JButton reLoad = new JButton("刷新"); ImageIcon ii = new ImageIcon("src/im/bk.jpg"); ImageIcon aIcon = new ImageIcon("src/im/1.gif"); ImageIcon bIcon = new ImageIcon("src/im/2.gif"); ImageIcon cIcon = new ImageIcon("src/im/3.gif"); ImageIcon dIcon = new ImageIcon("src/im/4.gif"); ImageIcon eIcon = new ImageIcon("src/im/5.gif"); ImageIcon fIcon = new ImageIcon("src/im/6.gif"); ImageIcon gIcon = new ImageIcon("src/im/7.gif"); ImageIcon hIcon = new ImageIcon("src/im/8.gif"); ImageIcon iIcon = new ImageIcon("src/im/9.gif"); ImageIcon jIcon = new ImageIcon("src/im/10.gif"); ImageIcon kIcon = new ImageIcon("src/im/11.gif"); ImageIcon lIcon = new ImageIcon("src/im/12.gif"); ImageIcon mIcon = new ImageIcon("src/im/13.gif"); ImageIcon nIcon = new ImageIcon("src/im/14.gif"); ImageIcon oIcon = new ImageIcon("src/im/15.gif"); public LianLianKanJPanel() { this.setLayout(null); newMap(); for (int i = 0; i BlockButton[i][j] = new JButton(); add(BlockButton[i][j]); BlockButton[i][j].addActionListener(this);//监听器 BlockButton[i][j].setBounds(30 + j * 40, 30 + i * 40, 31,34); // BlockButton[i][j].setBorderPainted(false); // BlockButton[i][j].setVisible(true); } } difficultChoice.add("简单"); difficultChoice.add("中等"); difficultChoice.add("困难"); difficultChoice.add("变态"); newgameButton.setBounds(map[0].length * 40 + 80, 40, 100, 20); newgameButton.setBackground(Color.white); newgameButton.setBorderPainted(false); //去边框 reLoad.setBounds(map[0].length * 40 + 100, 80, 60, 20); reLoad.setBackground(Color.white); reLoad.setBorderPainted(false); difficultChoice.setBounds(map[0].length * 40 + 100, 120, 60, 20); difficultChoice.addItemListener(this); newgameButton.addActionListener(this); reLoad.addActionListener(this); this.add(newgameButton); this.add(reLoad); this.add(difficultChoice); // /-------------------------漏斗 ld.setBounds(map[0].length * 40 + 100, 200, 70, 150);// 漏斗 ld.setBackground(Color.black); this.add(ld); } class loudou extends JPanel implements Runnable { private static final long serialVersionUID = 1L; private int dijiguan; int remainTimes = 0; // 时间 int x1 = 0; int y1 = 30; int x2 = 60; int y2 = 150; Thread nThread1;//线程 JLabel overJLabel = new JLabel(); JDialog dialog = new JDialog(); public loudou() { nThread1 = new Thread(this); nThread1.start(); this.setLayout(null); this.add(overJLabel); overJLabel.setBounds(0, 0, 200, 50); overJLabel.setForeground(Color.white); } public void setdijiguan(int x) { this.dijiguan = x; } public void paintComponent(Graphics g) // 画画函数 { super.paintComponent(g); g.setColor(Color.green); for (int i = 0; i for (int i = 0; i g.drawLine(x1 + i / 2 + 2, y1 + i, x2 - i / 2 - 2, y1 + i);//覆盖上边的倒三角 } } if (remainTimes >= 50 && remainTimes return remainTimes; } public void run() { while (dijiguan JOptionPane.showMessageDialog(null, "游戏开始?"); } if (remainTimes == 56) { JOptionPane.showMessageDialog(null, "时间到!游戏结束!"); } remainTimes++; repaint(); try { if (dijiguan = 6 && dijiguan 8) Thread.sleep(850 - (dijiguan - 8) * 20); } catch (InterruptedException e) { e.printStackTrace(); } } } } public void paintComponent(Graphics g) { super.paintComponent(g); //是父类JPanel里的方法,会把整个面板用背景色重画一遍,起到清屏的作用 g.drawImage(ii.getImage(), 0, 0, this); //绘制两个文本字符串 g.setColor(Color.white); g.drawString("得分: " + score, 430, 165); g.drawString("第 " + (guanshu + 1) + " 关", 430, 190); for (int i = 0; i switch (map[i][j]) { case 0: BlockButton[i][j].setVisible(false); break; case 1: BlockButton[i][j].setIcon(aIcon); break; case 2: BlockButton[i][j].setIcon(bIcon); break; case 3: BlockButton[i][j].setIcon(cIcon); break; case 4: BlockButton[i][j].setIcon(dIcon); break; case 5: BlockButton[i][j].setIcon(eIcon); break; case 6: BlockButton[i][j].setIcon(fIcon); break; case 7: BlockButton[i][j].setIcon(gIcon); break; case 8: BlockButton[i][j].setIcon(hIcon); break; case 9: BlockButton[i][j].setIcon(iIcon); break; case 10: BlockButton[i][j].setIcon(jIcon); break; case 11: BlockButton[i][j].setIcon(kIcon); break; case 12: BlockButton[i][j].setIcon(lIcon); break; case 13: BlockButton[i][j].setIcon(mIcon); break; case 14: BlockButton[i][j].setIcon(nIcon); break; case 15: BlockButton[i][j].setIcon(oIcon); break; default: break; } } } } //重载 public void chongzai() { jishushengyu = 0; for (int i = 0; i if (map[i][j] > 0) { jishushengyu++; } } } int[][] map1 = new int[8][8]; this.map = map1; Random random = new Random(); for (int i = 0; i randomx1 = random.nextInt(8);//0-8随机数 randomy1 = random.nextInt(8); } while (map[randomy1][randomx1] > 0); map[randomy1][randomx1] = kind; do { randomx = random.nextInt(8); randomy = random.nextInt(8); } while (map[randomy][randomx] > 0); map[randomy][randomx] = kind; } repaint(); for (int i = 0; i BlockButton[i][j].setVisible(true); } } } public void newGame() { // JOptionPane.showMessageDialog(null,"你按了开始按钮"); for (int i = 0; i BlockButton[i][j].setEnabled(true); BlockButton[i][j].setVisible(true); } } int[][] map = new int[8][8]; this.map = map; newMap(); ld.setTimes(0); score = 0; guanshu = 0; ld.setdijiguan(guanshu); } public void guoguan() { int jishushengyu2 = 0; for (int i = 0; i if (map[i][j] > 0) { jishushengyu2++; } } } if (jishushengyu2 == 0) { for (int i = 0; i BlockButton[i][j].setEnabled(true); BlockButton[i][j].setVisible(true); } } int[][] map = new int[8][8]; this.map = map; newMap(); ld.setTimes(0); guanshu++; ld.setdijiguan(guanshu); reLoad.setEnabled(true); } } public void newMap() { ArrayList numbers = new ArrayList();//链表 for (int i = 0; i temp = random.nextInt(Kinds) + 1;//0~kinds-1之间的随机数在加1 numbers.add(temp); numbers.add(temp); } Collections.shuffle(numbers);//随机打乱原来的顺序 map = new int[8][8]; temp = 0; for (int i = 0; i //JOptionPane.showMessageDialog(null, numbers.get(temp)); map[i][j] = numbers.get(temp++).intValue();//get方法返回第i个元素,intvalue 返回int类型 } } } public void itemStateChanged(ItemEvent e) { // TODO 自动生成的方法存根 if (e.getSource() == difficultChoice) { String selected = difficultChoice.getSelectedItem(); if (selected == "简单") { Kinds = 4; newGame(); repaint(); } else if (selected == "中等") { Kinds = 8; newGame(); repaint(); } else if (selected == "困难") { Kinds = 12; newGame(); repaint(); } else if (selected == "变态") { Kinds = 15; newGame(); repaint(); } } } public void actionPerformed(ActionEvent e) { // TODO 自动生成的方法存根 if (ld.getTimes() >56) { for (int i = 0; i BlockButton[j][i].setEnabled(false); } } } if (e.getSource() == reLoad) { chongzai(); reLoad.setEnabled(false); } if (e.getSource() == newgameButton) { newGame(); reLoad.setEnabled(true); } for (int i = 0; i if (e.getSource() == BlockButton[j][i]) { clicktimes++; // 点击的次数 lineStart.move(i, j); if (clicktimes % 2 == 1) { coordinatex1 = i; coordinatey1 = j; BlockButton[coordinatey1][coordinatex1].setEnabled(false); BlockButton[coordinatey][coordinatex].setEnabled(true); // BlockButton[j][i].setEnabled(false); } if (clicktimes % 2 == 0) { coordinatex = i; coordinatey = j; BlockButton[coordinatey][coordinatex].setEnabled(false); BlockButton[coordinatey1][coordinatex1].setEnabled(true); } } } } this.requestFocus(); clearBlock(); /* * for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { * BlockButton[j][i].setEnabled(true); } * * } */ repaint(); } // -------------------------------------------------------------------------- // 判断在一列之内两图片之间是否全部是空白或直接相邻 private boolean containsAllOrNoneZeroInColumn(int posX1, int posY1, int posX2, int posY2) { // 直接相连,因而不包含空白 if (Math.abs(posY1 - posY2) == 0) { return true; } int a = posY1 return false; } } return true; } // 判断在一行之内两图片之间是否全部是空白或直接相邻 private boolean containsAllOrNoneZeroInRow(int posX1, int posY1, int posX2, int posY2) { // 直接相连,因而不包含空白 if (Math.abs(posX1 - posX2) == 0) { return true; } int a = posX1 return false; } } return true; } // 是否可以一直线相连 private boolean isLinkByOneLine(int posX1, int posY1, int posX2, int posY2) { if (posX1 != posX2 && posY1 != posY2) { return false; } if (posX1 == posX2) { if (containsAllOrNoneZeroInColumn(posX1, posY1, posX2, posY2)) { return true; } } if (posY1 == posY2) { if (containsAllOrNoneZeroInRow(posX1, posY1, posX2, posY2)) { return true; } } return false; } // 是否可以两直线相连 private boolean isLinkByTwoLines(int posX1, int posY1, int posX2, int posY2) { if (posX1 != posX2 && posY1 != posY2) { // x1,y1 to x2,y1 to x2,y2 if (containsAllOrNoneZeroInRow(posX1, posY1, posX2, posY1) && map[posX2][posY1] == 0 && containsAllOrNoneZeroInColumn(posX2, posY1, posX2, posY2)) { return true; } // x1,y1 to x1,y2 to x2,y2 if (containsAllOrNoneZeroInColumn(posX1, posY1, posX1, posY2) && map[posX1][posY2] == 0 && containsAllOrNoneZeroInRow(posX1, posY2, posX2, posY2)) { return true; } } return false; } // 是否可以三直线相连 private boolean isLinkByThreeLines(int posX1, int posY1, int posX2, int posY2) { if (isOnSameEdge(posX1, posY1, posX2, posY2)) { return true; } if (isOnThreeLinesLikeArc(posX1, posY1, posX2, posY2)) { return true; } if (isOnThreeLinesLikeZigzag(posX1, posY1, posX2, posY2)) { return true; } return false; } // 是否可以三直线相连,似U形 private boolean isOnThreeLinesLikeArc(int posX1, int posY1, int posX2, int posY2) { if (isOnUpArc(posX1, posY1, posX2, posY2)) { return true; } if (isOnDownArc(posX1, posY1, posX2, posY2)) { return true; } if (isOnLeftArc(posX1, posY1, posX2, posY2)) { return true; } if (isOnRightArc(posX1, posY1, posX2, posY2)) { return true; } return false; } // ∪ private boolean isOnUpArc(int posX1, int posY1, int posX2, int posY2) { // Y --> 0 int lessY = posY1 = 0; j--) { if (containsAllOrNoneZeroInRow(posX1, j, posX2, j) && containsAllOrNoneZeroInColumn(posX1, posY1, posX1, j) && containsAllOrNoneZeroInColumn(posX2, posY2, posX2, j) && map[posX1][j] == 0 && map[posX2][j] == 0) { return true; } } if (isOnSameEdge(posX1, 0, posX2, 0) && containsAllOrNoneZeroInColumn(posX1, posY1, posX1, 0) && containsAllOrNoneZeroInColumn(posX2, posY2, posX2, 0) && (map[posX1][0] == 0 && map[posX2][0] == 0 || map[posX1][0] == 0 && map[posX2][0] == map[posX2][posY2] || map[posX1][0] == map[posX1][posY1] && map[posX2][0] == 0)) { return true; } return false; } // ∩ private boolean isOnDownArc(int posX1, int posY1, int posX2, int posY2) { int moreY = posY1 return true; } } if (isOnSameEdge(posX1, 8 - 1, posX2, 8 - 1) && containsAllOrNoneZeroInColumn(posX1, posY1, posX1, 8 - 1) && containsAllOrNoneZeroInColumn(posX2, posY2, posX2, 8 - 1) && (map[posX1][8 - 1] == 0 && map[posX2][8 - 1] == 0 || map[posX1][8 - 1] == map[posX1][posY1] && map[posX2][8 - 1] == 0 || map[posX1][8 - 1] == 0 && map[posX2][8 - 1] == map[posX2][posY2])) { return true; } return false; } // ﹚ private boolean isOnLeftArc(int posX1, int posY1, int posX2, int posY2) { int lessX = posX1 = 0; i--) { if (containsAllOrNoneZeroInColumn(i, posY1, i, posY2) && containsAllOrNoneZeroInRow(i, posY1, posX1, posY1) && containsAllOrNoneZeroInRow(i, posY2, posX2, posY2) && map[i][posY1] == 0 && map[i][posY2] == 0) { return true; } } if (isOnSameEdge(0, posY1, 0, posY2) && containsAllOrNoneZeroInRow(0, posY1, posX1, posY1) && containsAllOrNoneZeroInRow(0, posY2, posX2, posY2) && (map[0][posY1] == 0 && map[0][posY2] == 0 || map[0][posY1] == map[posX1][posY1] && map[0][posY2] == 0 || map[0][posY1] == 0 && map[0][posY2] == map[posX2][posY2])) { return true; } return false; } // ( private boolean isOnRightArc(int posX1, int posY1, int posX2, int posY2) { int moreX = posX1 return true; } } if (isOnSameEdge(8 - 1, posY1, 8 - 1, posY2) && containsAllOrNoneZeroInRow(posX1, posY1, 8 - 1, posY1) && containsAllOrNoneZeroInRow(posX2, posY2, 8 - 1, posY2) && (map[8 - 1][posY1] == 0 && map[8 - 1][posY2] == 0 || map[8 - 1][posY1] == map[posX1][posY1] && map[8 - 1][posY2] == 0 || map[8 - 1][posY1] == 0 && map[8 - 1][posY2] == map[posX2][posY2])) { return true; } return false; } // 是否可以三直线相连,似之字形N private boolean isOnThreeLinesLikeZigzag(int posX1, int posY1, int posX2, int posY2) { if (isOnZigzagWith1Row2Cols(posX1, posY1, posX2, posY2)) { return true; } if (isOnZigzagWith2Rows1Col(posX1, posY1, posX2, posY2)) { return true; } return false; } // 是否可以三直线相连,似之字形, 两行一列 Z private boolean isOnZigzagWith2Rows1Col(int posX1, int posY1, int posX2, int posY2) { int moreX = posX1 return true; } } return false; } // 是否可以三直线相连,似之字形, 一行两列 private boolean isOnZigzagWith1Row2Cols(int posX1, int posY1, int posX2, int posY2) { int moreY = posY1 return true; } } return false; } // 是否处于游戏区域的4条边的同一边上 private boolean isOnSameEdge(int posX1, int posY1, int posX2, int posY2) { if ((posY1 == posY2 && posY2 == 0) || (posY1 == posY2 && posY2 == 8 - 1) || (posX1 == posX2 && posX2 == 0) || (posX1 == posX2 && posX2 == 8 - 1)) { return true; } return false; } // -------------------------------------------------------------------------- public boolean ifcanTouch(int posX1, int posY1, int posX2, int posY2) { if (isLinkByOneLine(posX1, posY1, posX2, posY2)) { return true; } // 是否可以两直线相连 if (isLinkByTwoLines(posX1, posY1, posX2, posY2)) { return true; } // 是否可以三直线相连 if (isLinkByThreeLines(posX1, posY1, posX2, posY2)) { return true; } return false; } public void clearBlock() { if (clicktimes >=2) { if (map[coordinatey1][coordinatex1] == map[coordinatey][coordinatex] && !((coordinatex1 == coordinatex) && (coordinatey1 == coordinatey))) { if (ifcanTouch(coordinatey1, coordinatex1, coordinatey, coordinatex)) { if (map[coordinatey1][coordinatex1] > 0) score = score + 10; map[coordinatey1][coordinatex1] = 0; map[coordinatey][coordinatex] = 0; guoguan(); } } } } } public static void main(String[] args) { String lookAndFeel ="javax.swing.plaf.metal.MetalLookAndFeel";//swing 外观和感觉 try { UIManager.setLookAndFeel(lookAndFeel); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (UnsupportedLookAndFeelException e) { // TODO Auto-generated catch block e.printStackTrace(); } LianLianKan frame = new LianLianKan(); frame.setTitle("连连看"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setBounds(100, 100, 560, 430); frame.setLocation(440, 100); // frame.setSize(600, 500); frame.setSize(540, 440); frame.setVisible(true); } } 总结

通过此次的《连连看》游戏实现,让我对swing的相关知识有了进一步的了解,对java这门语言也有了比以前更深刻的认识。

java的一些基本语法,比如数据类型、运算符、程序流程控制和数组等,理解更加透彻。java最核心的核心就是面向对象思想,对于这一个概念,终于悟到了一些。

源码获取

可关注博主后,私聊博主免费获取 需要技术指导,写项目程序,等更多服务请联系博主

今天是持续写作的第 30 / 100 天。 可以关注我,点赞我、评论我、收藏我啦。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3