- 博客有时间就写写,所以一篇可能会拆成很多篇,写完后计划再合在一起。
- 首先肯定是要实现连连看的界面。
- 先准备连连看要的图片。、
- “LianLianKan”就是项目名称。
- 当然,如果小白看我的博客想学到什么,我会说还是放弃,因为文字描述会忽视很多细节,而细节决定bug……
- 所以,包括以前的和以后的,博文都会是给自己看看或者内行触类旁通的,也就是——笔记。
- 我也是今天才明白博文的真正意义吧,所以以后的博文风格会大改……尽量会用自己语言风格来描述以便自己能看懂。
- 废话少说,现在的第2步:
- 创建数组,一个持久化存储的容器:存储连连看的图片 迷宫寻路
- 2.有图像在数组看得到,先秀一下看看,免得一开始代码就错了,后面还写个毛。
- 到这一步,主函数基本没什么变化。TableFrame.java
1 package com.edp.impl; 2 3 4 import java.awt.FlowLayout; 5 6 import javax.swing.JFrame; 7 import javax.swing.JTable; 8 9 /** 10 * 11 * @author Administrator 12 * 13 */ 14 @SuppressWarnings("serial") 15 public class TableFrame extends JFrame{ 16 public static void main(String[] args) { 17 new TableFrame().initFrame(); 18 } 19 20 private void initFrame() { 21 this.setSize(800,600); 22 this.setDefaultCloseOperation(3); 23 this.setLayout(new FlowLayout()); 24 //设置窗体不能改变大小 25 this.setResizable(false); 26 this.setLocationRelativeTo(null); 27 28 MyTableModel mtm = new MyTableModel(); 29 JTable table = new JTable(mtm); 30 this.add(table); 31 this.setVisible(true); 32 33 } 34 }
- 说明在代码里面写清楚了 。
1 package com.edp.impl; 2 3 import java.util.Random; 4 5 import javax.swing.event.TableModelListener; 6 import javax.swing.table.TableModel; 7 8 public class MyTableModel implements TableModel { 9 //1.创建数组,一个持久化存储的容器:存储连连看的图片 迷宫寻路 10 private String[][] saveDB = new String[13][13]; 11 //2.有图像在数组看得到 12 //2_2在存的时候想到图片最好随机 13 private Random ran = new Random();//创建随机对象 14 //2_1 把图片存到数组 15 public MyTableModel() { 16 int value; 17 for(int i = 0;i<saveDB.length;i++){ 18 for (int j = 0; j < saveDB[i].length; j++) { 19 value = ran.nextInt(13)+1; 20 saveDB[i][j] = "image/lianliankanimage/"+value+".jpg"; 21 } 22 } 23 } 24 25 //获取列类型 26 public Class<?> getColumnClass(int columnIndex) { 27 return String.class; 28 } 29 //获取总行数 30 public int getRowCount() { 31 return saveDB.length; 32 } 33 //获取总列数 34 public int getColumnCount() { 35 return saveDB[0].length; 36 } 37 //获取表格列名 38 public String getColumnName(int columnIndex) { 39 //连连看游戏没必要出现表格列名呀,反正不需要 40 //实现列名可以通过switch语句,最适合实现。然后在TableFrame类里面实现 41 //不过想要实现得这样(用到JScrollPane): 42 // JTable table = new JTable(mtm); 43 // //把JTable对象加载到JScrollPane 44 // JScrollPane jsp = new JScrollPane(table); 45 // this.add(jsp); 46 //JScrollPane到底是个什么玩意,请自己去查java API说明书。 47 return null; 48 } 49 //设置单元格数据 50 public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 51 } 52 //获得单元格数据 53 public Object getValueAt(int rowIndex, int columnIndex) { 54 return 0; 55 } 56 //单元格是否编辑 57 public boolean isCellEditable(int rowIndex, int columnIndex) { 58 //连连看游戏肯定不需要对单元格进行修改或删除,游戏逻辑自会处理相关格子内的东西。 59 return false; 60 } 61 public void removeTableModelListener(TableModelListener l) {} 62 public void addTableModelListener(TableModelListener l) {} 63 }
- 运行结果是这样子的
- 然后开始插入图片看看。
- TableFrame.java
1 package com.edp.impl; 2 3 4 import java.awt.FlowLayout; 5 6 import javax.swing.JFrame; 7 import javax.swing.JTable; 8 import javax.swing.table.TableColumnModel; 9 10 /** 11 * 12 * @author Administrator 13 * 14 */ 15 @SuppressWarnings("serial") 16 public class TableFrame extends JFrame{ 17 public static void main(String[] args) { 18 new TableFrame().initFrame(); 19 } 20 21 private void initFrame() { 22 this.setSize(800,600); 23 this.setDefaultCloseOperation(3); 24 this.setLayout(new FlowLayout()); 25 //设置窗体不能改变大小 26 this.setResizable(false); 27 this.setLocationRelativeTo(null); 28 29 MyTableModel mtm = new MyTableModel(); 30 JTable table = new JTable(mtm); 31 this.add(table); 32 //设置显示样式 33 //列宽 34 table.setRowHeight(35); 35 //获取列模型 36 TableColumnModel columnModel = table.getColumnModel(); 37 for (int i = 0; i < columnModel.getColumnCount(); i++) { 38 columnModel.getColumn(i).setPreferredWidth(35); 39 } 40 //设置行列都不能被选中 41 table.setRowSelectionAllowed(false); 42 table.setColumnSelectionAllowed(false); 43 this.setVisible(true); 44 45 } 46 }
- MyTableModel.java
1 package com.edp.impl; 2 3 import java.util.Random; 4 5 import javax.swing.ImageIcon; 6 import javax.swing.event.TableModelListener; 7 import javax.swing.table.TableModel; 8 9 public class MyTableModel implements TableModel { 10 //1.创建数组,一个持久化存储的容器:存储连连看的图片 迷宫寻路 11 private String[][] saveDB = new String[13][13]; 12 //2.有图像在数组看得到 13 //2_2在存的时候想到图片最好随机 14 private Random ran = new Random();//创建随机对象 15 //2_1 把图片存到数组 16 public MyTableModel() { 17 int value; 18 for(int i = 0;i<saveDB.length;i++){ 19 for (int j = 0; j < saveDB[i].length; j++) { 20 value = ran.nextInt(13)+1; 21 saveDB[i][j] = "image/"+value+".jpg"; 22 } 23 } 24 } 25 26 //获取列类型 27 public Class<?> getColumnClass(int columnIndex) { 28 return javax.swing.ImageIcon.class; 29 } 30 //获取总行数 31 public int getRowCount() { 32 return saveDB.length; 33 } 34 //获取总列数 35 public int getColumnCount() { 36 //这里考虑一个bug:如果连列数都没有,这行代码就会报出异常 37 if(saveDB.length>0){ 38 return saveDB[0].length; 39 } 40 return 0; 41 } 42 //获取表格列名 43 public String getColumnName(int columnIndex) { 44 //连连看游戏没必要出现表格列名呀,反正不需要 45 //实现列名可以通过switch语句,最适合实现。然后在TableFrame类里面实现 46 //不过想要实现得这样(用到JScrollPane): 47 // JTable table = new JTable(mtm); 48 // //把JTable对象加载到JScrollPane 49 // JScrollPane jsp = new JScrollPane(table); 50 // this.add(jsp); 51 //JScrollPane到底是个什么玩意,请自己去查java API说明书。 52 return null; 53 } 54 //设置单元格数据 55 public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 56 saveDB[rowIndex][columnIndex] = (String)aValue; 57 } 58 //获得单元格数据 59 public Object getValueAt(int rowIndex, int columnIndex) { 60 //返回图片 61 ImageIcon icon = new ImageIcon(saveDB[rowIndex][columnIndex]); 62 return icon; 63 64 } 65 //单元格是否编辑 66 public boolean isCellEditable(int rowIndex, int columnIndex) { 67 //连连看游戏肯定不需要对单元格进行修改或删除,游戏逻辑自会处理相关格子内的东西。 68 return false; 69 } 70 public void removeTableModelListener(TableModelListener e) {} 71 public void addTableModelListener(TableModelListener e) {} 72 }
- 运行后,什么都出来了。
- 接下来是实现连连看游戏的消除。
- 消除肯定要用鼠标点呀点的。而实现鼠标操作,肯定是要监控。
- 监控插哪呢,肯定要是面板创建完,就监控。
-
回顾一下处理连连看消除逻辑(算法实现)
-
相同图片能够消除
-
在同一行或者同一列无障碍物可消除
-
一个拐点可消除
-
两个拐点可消除
-
- TableFrame.java
1 package com.edp.impl; 2 3 4 import java.awt.FlowLayout; 5 6 import javax.swing.JFrame; 7 import javax.swing.JTable; 8 import javax.swing.table.TableColumnModel; 9 10 /** 11 * 12 * @author Administrator 13 * 14 */ 15 @SuppressWarnings("serial") 16 public class TableFrame extends JFrame{ 17 public static void main(String[] args) { 18 new TableFrame().initFrame(); 19 } 20 21 private void initFrame() { 22 this.setSize(800,600); 23 this.setDefaultCloseOperation(3); 24 this.setLayout(new FlowLayout()); 25 //设置窗体不能改变大小 26 this.setResizable(false); 27 this.setLocationRelativeTo(null); 28 29 MyTableModel mtm = new MyTableModel(); 30 JTable table = new JTable(mtm); 31 this.add(table); 32 //设置显示样式 33 //列宽 34 table.setRowHeight(35); 35 //获取列模型 36 TableColumnModel columnModel = table.getColumnModel(); 37 for (int i = 0; i < columnModel.getColumnCount(); i++) { 38 columnModel.getColumn(i).setPreferredWidth(35); 39 } 40 //设置行列都不能被选中 41 table.setRowSelectionAllowed(false); 42 table.setColumnSelectionAllowed(false); 43 this.setVisible(true); 44 45 //添加监听器 46 LLKMouseListener llkListener = new LLKMouseListener(mtm); 47 table.addMouseListener(llkListener); 48 } 49 }
- MyTableModel.java
1 package com.edp.impl; 2 3 import java.util.Random; 4 5 import javax.swing.ImageIcon; 6 import javax.swing.event.TableModelListener; 7 import javax.swing.table.TableModel; 8 9 public class MyTableModel implements TableModel { 10 //1.创建数组,一个持久化存储的容器:存储连连看的图片 迷宫寻路 11 private String[][] saveDB = new String[13][13]; 12 //2.有图像在数组看得到 13 //2_2在存的时候想到图片最好随机 14 private Random ran = new Random();//创建随机对象 15 //2_1 把图片存到数组 16 //3.消除肯定要用鼠标点呀点的。而实现鼠标操作,肯定是要监控。 17 public MyTableModel() { 18 int value; 19 for(int i = 0;i<saveDB.length;i++){ 20 for (int j = 0; j < saveDB[i].length; j++) { 21 value = ran.nextInt(13)+1; 22 saveDB[i][j] = "image/"+value+".jpg"; 23 } 24 } 25 } 26 27 //获取列类型 28 public Class<?> getColumnClass(int columnIndex) { 29 return javax.swing.ImageIcon.class; 30 } 31 //获取总行数 32 public int getRowCount() { 33 return saveDB.length; 34 } 35 //获取总列数 36 public int getColumnCount() { 37 //这里考虑一个bug:如果连列数都没有,这行代码就会报出异常 38 if(saveDB.length>0){ 39 return saveDB[0].length; 40 } 41 return 0; 42 } 43 //获取表格列名 44 public String getColumnName(int columnIndex) { 45 //连连看游戏没必要出现表格列名呀,反正不需要 46 //实现列名可以通过switch语句,最适合实现。然后在TableFrame类里面实现 47 //不过想要实现得这样(用到JScrollPane): 48 // JTable table = new JTable(mtm); 49 // //把JTable对象加载到JScrollPane 50 // JScrollPane jsp = new JScrollPane(table); 51 // this.add(jsp); 52 //JScrollPane到底是个什么玩意,请自己去查java API说明书。 53 return null; 54 } 55 //设置单元格数据 56 public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 57 saveDB[rowIndex][columnIndex] = (String)aValue; 58 } 59 //获得单元格数据 60 public Object getValueAt(int rowIndex, int columnIndex) { 61 //返回图片 62 ImageIcon icon = new ImageIcon(saveDB[rowIndex][columnIndex]); 63 return icon; 64 65 } 66 //单元格是否编辑 67 public boolean isCellEditable(int rowIndex, int columnIndex) { 68 //连连看游戏肯定不需要对单元格进行修改或删除,游戏逻辑自会处理相关格子内的东西。 69 return false; 70 } 71 public void removeTableModelListener(TableModelListener e) {} 72 public void addTableModelListener(TableModelListener e) {} 73 74 public String[][] getSaveDB() { 75 return saveDB; 76 } 77 }
这一部分和之前没有多大变动,加了一个数组输入输出存储,eclipse自动报错加上去的。(74-76行)
- LLKMouseListener.java
1 package com.edp.impl; 2 3 import java.awt.event.MouseAdapter; 4 import java.awt.event.MouseEvent; 5 6 import javax.swing.JTable; 7 8 public class LLKMouseListener extends MouseAdapter{ 9 /** 10 1.相同图片能够消除 11 2.在同一行或者同一列无障碍物可消除 12 3.一个拐点可消除 13 4.两个拐点可消除 14 */ 15 public MyTableModel mtm; 16 17 //1_4.发现消除的是一个,点一个就消掉一个 18 //所以需要做下关联, 控制第一次还是第二次点击的操作 19 public boolean flag = true; 20 public int row1, column1, row2, column2; 21 //3.鼠标监控 22 public LLKMouseListener(MyTableModel mtm) { 23 this.mtm = mtm; 24 } 25 26 public void mousePressed(MouseEvent e) { 27 //1.相同图片能够消除 28 // 1_1.需要知道自己点击的是表格哪个位置 29 // 1_2.得到被选中行被选中列 30 JTable table = (JTable) e.getSource(); 31 32 // 1_3.把指定位置的图片消除:去除路径 33 String[][] saveDB = mtm.getSaveDB(); 34 35 if(flag){ 36 row1 = table.getSelectedRow(); 37 column1 = table.getSelectedColumn(); 38 flag = false; 39 }else{ 40 row2 = table.getSelectedRow(); 41 column2 = table.getSelectedColumn(); 42 saveDB[row1][column1] = ""; 43 saveDB[row2][column2] = ""; 44 flag = true; 45 } 46 } 47 }
到这一步已经实现任意两个图形相消除,接下来是——两个相同图形的消除。
- LLKMouseListener.java
1 package com.edp.impl; 2 3 import java.awt.event.MouseAdapter; 4 import java.awt.event.MouseEvent; 5 6 import javax.swing.JTable; 7 8 public class LLKMouseListener extends MouseAdapter{ 9 /** 10 1.相同图片能够消除 11 2.在同一行或者同一列无障碍物可消除 12 3.一个拐点可消除 13 4.两个拐点可消除 14 */ 15 public MyTableModel mtm; 16 17 //1_4.发现消除的是一个,点一个就消掉一个 18 //所以需要做下关联, 控制第一次还是第二次点击的操作 19 public boolean flag = true; 20 public int row1, column1, row2, column2; 21 //3.鼠标监控 22 public LLKMouseListener(MyTableModel mtm) { 23 this.mtm = mtm; 24 } 25 26 public void mousePressed(MouseEvent e) { 27 //1.相同图片能够消除 28 // 1_1.需要知道自己点击的是表格哪个位置 29 // 1_2.得到被选中行被选中列 30 JTable table = (JTable) e.getSource(); 31 32 // 1_3.把指定位置的图片消除:去除路径 33 String[][] saveDB = mtm.getSaveDB(); 34 35 if(flag){ 36 row1 = table.getSelectedRow(); 37 column1 = table.getSelectedColumn(); 38 flag = false; 39 }else{ 40 row2 = table.getSelectedRow(); 41 column2 = table.getSelectedColumn(); 42 if((row1 != row2 || column1 != column2)){ 43 if(saveDB[row1][column1].equals(saveDB[row2][column2])){ 44 if(checkRow(row1,column1,row2,column2)|| 45 checkColumn(row1,column1,row2,column2)){ 46 saveDB[row1][column1] = ""; 47 saveDB[row2][column2] = ""; 48 } 49 } 50 } 51 flag = true; 52 } 53 } 54 55 //同行算法 56 public boolean checkRow(int row1, int column1, int row2, int column2) { 57 // 1.保证两个位置是同一行 58 if (row1 == row2) { 59 int minColumn = Math.min(column1, column2); 60 int maxColumn = Math.max(column1, column2); 61 // 寻找两个位置之间的所有位置是否为空 62 for (int i = minColumn + 1; i < maxColumn; i++) { 63 if (!"".equals(mtm.getSaveDB()[row1][i])) { 64 return false; 65 } 66 } 67 return true; 68 } 69 return false; 70 } 71 72 //同列算法 73 public boolean checkColumn(int row1, int column1, int row2, int column2) { 74 // 1.保证两个位置是同一列 75 if (column1 == column2) { 76 int minRow = Math.min(row1, row2); 77 int maxRow = Math.max(row1, row2); 78 // 寻找两个位置之间的所有位置是否为空 79 for (int i = minRow + 1; i < maxRow; i++) { 80 if (!"".equals(mtm.getSaveDB()[column1][i])) { 81 return false; 82 } 83 } 84 return true; 85 } 86 return false; 87 88 } 89 public boolean checkOnePoint(int row1, int column1, int row2, int column2) { 90 return false; 91 92 } 93 public boolean checkTwoPoint(int row1, int column1, int row2, int column2) { 94 return false; 95 } 96 97 }
- 继续增加代码,也就是限制消除的条件(对消除提条件),因为只有鼠标监听类有做修改,所以就只放这个类的代码了。
- 这里实现的行和列相同图片可以消除。还剩一个拐点和两个拐点。
- 在写出上述代码的时候一直用 "System.out.println();"语句进行反复测试才实现代码,而且在不断增加代码中,这种测试方法会一直用。
- 一个拐点的实现需要利用到同行消除判断算法和同列消除判断算法。
- 这里主调函数没变就不放上来了。
- MyTableModel.java
package com.edp.impl; import java.util.Random; import javax.swing.ImageIcon; import javax.swing.event.TableModelListener; import javax.swing.table.TableModel; public class MyTableModel implements TableModel { //1.创建数组,一个持久化存储的容器:存储连连看的图片 迷宫寻路 private String[][] saveDB = new String[13][13]; //2.有图像在数组看得到 //2_2在存的时候想到图片最好随机 private Random ran = new Random();//创建随机对象 //2_1 把图片存到数组 //3.消除肯定要用鼠标点呀点的。而实现鼠标操作,肯定是要监控。 public MyTableModel() { int value; for(int i = 0;i<saveDB.length;i++){ for (int j = 0; j < saveDB[i].length; j++) { value = ran.nextInt(13)+1; saveDB[i][j] = "image/"+value+".jpg"; } } } //获取列类型 public Class<?> getColumnClass(int columnIndex) { return javax.swing.ImageIcon.class; } //获取总行数 public int getRowCount() { return saveDB.length; } //获取总列数 public int getColumnCount() { //这里考虑一个bug:如果连列数都没有,这行代码就会报出异常 if(saveDB.length>0){ return saveDB[0].length; } return 0; } //获取表格列名 public String getColumnName(int columnIndex) { //连连看游戏没必要出现表格列名呀,反正不需要 //实现列名可以通过switch语句,最适合实现。然后在TableFrame类里面实现 //不过想要实现得这样(用到JScrollPane): // JTable table = new JTable(mtm); // //把JTable对象加载到JScrollPane // JScrollPane jsp = new JScrollPane(table); // this.add(jsp); //JScrollPane到底是个什么玩意,请自己去查java API说明书。 return null; } //设置单元格数据 public void setValueAt(Object aValue, int rowIndex, int columnIndex) { saveDB[rowIndex][columnIndex] = (String)aValue; } //获得单元格数据 public Object getValueAt(int rowIndex, int columnIndex) { //返回图片 ImageIcon icon = new ImageIcon(saveDB[rowIndex][columnIndex]); return icon; } //单元格是否编辑 public boolean isCellEditable(int rowIndex, int columnIndex) { //连连看游戏肯定不需要对单元格进行修改或删除,游戏逻辑自会处理相关格子内的东西。 return false; } public void removeTableModelListener(TableModelListener e) {} public void addTableModelListener(TableModelListener e) {} public String[][] getSaveDB() { return saveDB; } }
- LLKMouseListener.java ,该有的说明都在代码里面,思路按标的序号自己看。
package com.edp.impl; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JTable; public class LLKMouseListener extends MouseAdapter{ /** * 鼠标键控 * 1.相同图片能够消除 * 2.在同一行或者同一列无障碍物可消除 * 3.一个拐点可消除 * 4.两个拐点可消除 * */ public MyTableModel mtm; //1_4.发现消除的是一个,点一个就消掉一个 //所以需要做下关联, 控制第一次还是第二次点击的操作 public boolean flag = true; public int row1, column1, row2, column2; public LLKMouseListener(MyTableModel mtm) { this.mtm = mtm; } public void mousePressed(MouseEvent e) { //1.相同图片能够消除 // 1_1.需要知道自己点击的是表格哪个位置 // 1_2.得到被选中行被选中列 JTable table = (JTable) e.getSource(); // 1_3.把指定位置的图片消除:去除路径 String[][] saveDB = mtm.getSaveDB(); if(flag){ row1 = table.getSelectedRow(); column1 = table.getSelectedColumn(); flag = false; }else{ row2 = table.getSelectedRow(); column2 = table.getSelectedColumn(); if((row1 != row2 || column1 != column2)){ if(saveDB[row1][column1].equals(saveDB[row2][column2])){ if(checkRow(row1,column1,row2,column2) || checkColumn(row1,column1,row2,column2) || checkOnePoint(row1,column1,row2,column2) || checkTwoPoint(row1,column1,row2,column2)){ saveDB[row1][column1] = ""; saveDB[row2][column2] = ""; } } } flag = true; } } //2_1.同行算法,保证两个位置是同一行 public boolean checkRow(int row1, int column1, int row2, int column2) { if (row1 == row2) { int minColumn = Math.min(column1, column2); int maxColumn = Math.max(column1, column2); // 寻找两个位置之间的所有位置是否为空 for (int i = minColumn + 1; i < maxColumn; i++) { if (!"".equals(mtm.getSaveDB()[row1][i])) { return false; } } return true; } return false; } //2_2.同列算法,保证两个位置是同一列 public boolean checkColumn(int row1, int column1, int row2, int column2) { if (column1 == column2) { int minRow = Math.min(row1, row2); int maxRow = Math.max(row1, row2); // 寻找两个位置之间的所有位置是否为空 for (int i = minRow + 1; i < maxRow; i++) { if (!"".equals(mtm.getSaveDB()[i][column1])) { return false; } } return true; } return false; } //2_3.一个拐点算法 public boolean checkOnePoint(int row1, int column1, int row2, int column2) { //先寻找拐点坐标(row1,column2),(row2 column1) if("".equals(mtm.getSaveDB()[row1][column2])&& checkRow(row1, column2, row1, column1)&& checkColumn(row1, column2, row2, column2)){ return true; } if("".equals(mtm.getSaveDB()[row2][column1])&& checkRow(row2, column1, row2, column2)&& checkColumn(row2, column1, row1, column1)){ return true; } return false; } //2_4.两个拐点算法 public boolean checkTwoPoint(int row1, int column1, int row2, int column2) { //2_4_1.向左判断,各方向判断都是无数个“一个拐点”算法集合在一起。 for(int rowLeft = row1 - 1 ; mtm.getSaveDB()[rowLeft][column1] == "" && rowLeft >= 0 ; rowLeft --){ if(checkOnePoint(rowLeft,column1,row2,column2)){ return true; } } //2_4_1.向右判断 for(int rowRight = row1 + 1; rowRight <= mtm.getSaveDB()[0].length && mtm.getSaveDB()[rowRight][column1] == "" ; rowRight ++){ if(checkOnePoint(rowRight,column1,row2,column2)){ return true; } } //2_4_1.向上判断 for(int columnUp = column1 - 1 ; columnUp >= 0 && mtm.getSaveDB()[row1][columnUp] == ""; columnUp --){ if(checkOnePoint(row1,columnUp,row2,column2)){ return true; } } //2_4_1.向下判断 for(int columnDown = column1 + 1 ; columnDown <= mtm.getSaveDB().length && mtm.getSaveDB()[row1][columnDown] == "" ; columnDown ++){ if(checkOnePoint(row1,columnDown,row2,column2)){ return true; } } return false; } }
- 到这一步基本实现可玩性,但还有两个bug没有解决。
- 第一个bug:边缘消除无法实现
- 第二个bug:消除图片不是成双出现,而是单个随机出现的。