要做好一款小游戏,要的不仅是对游戏的理解,更是对于知识的应用,把所学到的知识融会贯通,下面要做的是一款简单的连连看小游戏。
一、我们先来分析一下这个项目
1.目的:这个项目的目的是找出两张相同的图片,然后再达到把这两张图片消除的效果。
2.首先做出一个界面框架,能够让图片存放的界面框架,做出界面框架之后,再写出一个面板来来存放这些图片,因为要把图片放入这个界面内,这是第一步。
3.第二步:图片的坐标和位置,用一个二维数组定义图片的大小,几行几列,然后再定义第一张图片的大小,放在左上角的位置,定义一个数组来存放需要显示在面板上所有的图片。
4.第三步:把图片存储到面板上的坐标内,首先应该要知道,图片的位置是要随机排列的,但是图片得是偶数,并且是两两对应的,这样最后才不会出现几张单独的图片,定义一个随机对象,用来随机图片,循环所需要图片个数的一半,每随机一张图片,就往队里中放两次,保证每一张图片都是两个。
5.第四步:消除两张相同的图片,先创建一个鼠标监听器,用来记录和点击图片位置的坐标,判断两张图片是否相同,再用remove方法移除两张相同图片的下标位置的元素。
下面是代码:
import java.awt.Color; import java.awt.Graphics; import java.util.ArrayList; import java.util.Random; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JPanel; /** * 连连看界面 * */ public class LLKFrame extends JFrame implements Config { /** * 初始化游戏图片的方法 */ 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(9); // 拼接图片路径字符串 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); } } } public static void main(String[] args) { LLKFrame llk = new LLKFrame(); // 调用方法初始化数据 llk.initPicData(); llk.initUI(); } public void initUI() { this.setTitle("连连看V1.0"); this.setSize(600, 400); this.setResizable(false); this.setDefaultCloseOperation(3); // 添加游戏区域面板 JPanel gamePanel = new MyPanel(); gamePanel.setBackground(Color.BLACK); this.add(gamePanel); this.setVisible(true); // 创建鼠标监听器 LLKListener lis = new LLKListener(); gamePanel.addMouseListener(lis); } 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); } } } } } }
import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.ImageIcon; import javax.swing.JPanel; /** * 游戏监听器,继承鼠标适配器类(实现鼠标监听器接口) * * */ public class LLKListener extends MouseAdapter implements Config { ImageIcon icon1, icon2;// 用来保存两次选中的图片对象 int i1, j1, i2, j2; int count = 0;// 计数器,用来记录点击次数 public void mouseReleased(MouseEvent e) { // 获得事件源对象:产生事件的对象,即为游戏面板 JPanel panel = (JPanel) e.getSource(); // 获得光标按下的位置 int x = e.getX(); int y = e.getY(); 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())) { System.out.println("相同,可消除"); ICONS[i1][j1] = null; ICONS[i2][j2] = null; // 刷新一下 panel.repaint(); } else { System.out.println("bu可消除"); } count--; } } 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; } }
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 = 10; // 定义一个数组来存放需要显示在面板上的所有图片 public static ImageIcon[][] ICONS = new ImageIcon[ROWS][COLS]; }