由于某些特殊原因近期无法完成安卓软件开发的学习,今天借鉴网络完成了一个连连看的游戏
package LianLianKan; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; public class GameClient extends JFrame { GamePanel panel2=new GamePanel(10); JButton button1=new JButton("重来一局"); JButton button2=new JButton("退出"); static JTextField textField=new JTextField(10); public GameClient(){ JLabel label1=new JLabel("已消去方块数量"); JPanel panel=new JPanel(new BorderLayout()); JPanel panel3=new JPanel (new BorderLayout()); textField.setEditable(false); panel2.setLayout(new BorderLayout()); panel.setLayout(new FlowLayout()); panel.add(label1); panel.add(textField); panel.add(button1); panel.add(button2); this.getContentPane().setLayout(new BorderLayout()); this.getContentPane().add(panel,BorderLayout.SOUTH); this.getContentPane().add(panel2,BorderLayout.CENTER); this.getContentPane().add(panel3,BorderLayout.SOUTH); this.setSize(800,700); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setTitle("连连看"); this.setVisible(true); button1.setEnabled(true); button2.setEnabled(true); button1.addMouseListener(new MouseAdapter(){ public void mouseClicked(MouseEvent e){ textField.setText("0"); panel2.startNewGame(); } }); button2.addMouseListener(new MouseAdapter(){ public void mouseClicked(MouseEvent e){ System.exit(0); } }); } public static void main(String[] args) { new GameClient(); } }
package LianLianKan; public class MapFactory { static int[][] map; public MapFactory(){} public static int[][] getMap(int n){ map=new int [n][n];//生成地图 for(int i=0;i<n;i++){//初始地图 for(int j=0;j<n;j++){ map[i][j]=-1; } } return map; } }
package LianLianKan; import java.util.ArrayList; public class Map { private int[][]map; private int count; private int n; public Map(int count, int n){//生成图案 map=MapFactory.getMap(n);//获取数组 this.count=count; this.n=n; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public int getN() { return n; } public void setN(int n) { this.n = n; } public int[][] getMap(){ ArrayList<Integer>list=new ArrayList<Integer>();//添加图片 for(int i=0;i<n*n/10;i++){ for(int j=0;j<count;j++){ list.add(j); } } for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ int index=(int)(Math.random()*list.size());//图片转化为数组 map[i][j]=list.get(index); list.remove(index); } } return map;//返回随机生成的地图数组 } public int[][]getResetMap(){//打乱地图 ArrayList<Integer>list=new ArrayList<Integer>(); for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(map[i][j]!=-1); list.add(map[i][j]); map[i][j]=-1; } } while(!list.isEmpty()){ int index=(int)(Math.random()*list.size()); boolean flag=false; while(!flag){ int i=(int)(Math.random()*n);//获取地图 int j=(int)(Math.random()*n); if(map[i][j]==-1){//无地图 map[i][j]=list.get(index); list.remove(index); flag=true; } } } return map; } }
package LianLianKan; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Point; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.JOptionPane; import javax.swing.JPanel; public class GamePanel extends JPanel implements ActionListener ,MouseListener,KeyListener { private Image[] pics;//图片数组 private int n;//行列数 private int[][] map;//存储地图信息 private int leftX = 140, leftY = 80;//row,column表示人物坐标;leftX,leftY记载左上角图片位置 private boolean isClick = false;//标记是否第一次选中图片 private int clickId, clickX, clickY;//记录首次选中图片的id,以及数组下标 private int linkMethod;//连接方式 private Node z1, z2;//存储拐角点的信息 private Map mapUtil;//地图工具类 public static int count = 0;//存储消去图案的个数 public static final int LINKBYHORIZONTAL = 1, LINKBYVERTICAL = 2, LINKBYONECORNER = 3, LINKBYTWOCORNER = 4; public static final int BLANK_STATE = -1; public GamePanel(int count) { setSize(600, 600); n = 10; mapUtil = new Map(count, n); map = mapUtil.getMap();//获取初始时,图片种类为count,行列数为n的地图信息 this.setVisible(true); this.addKeyListener(this); this.addMouseListener(this); this.setFocusable(true); getPics(); repaint(); } //初始化图片数组 private void getPics() { pics = new Image[10]; for (int i = 0; i <= 9; i++) { pics[i] = Toolkit.getDefaultToolkit().getImage("D:/IDEA/LinkGameSuCai/pic" + (i + 1) + ".png"); } } public void paint(Graphics g) { g.clearRect(0, 0, 800, 30); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (map[i][j] != BLANK_STATE) { g.drawImage(pics[map[i][j]], leftX + j * 50, leftY + i * 50, 50, 50, this); } else { g.clearRect(leftX + j * 50, leftY + i * 50, 50, 50); } } } } //判断是否可以水平相连 private boolean horizontalLink(int clickX1, int clickY1, int clickX2, int clickY2) { if (clickY1 > clickY2) {//保证y1<y2 int temp1 = clickX1; int temp2 = clickY1; clickX1 = clickX2; clickY1 = clickY2; clickX2 = temp1; clickY2 = temp2; } if (clickX1 == clickX2) { for (int i = clickY1 + 1; i < clickY2; i++) { if (map[clickX1][i] != BLANK_STATE) {//判断不能相连 return false; } } linkMethod = LINKBYHORIZONTAL; return true; } return false; } //判断是否可以垂直连接 private boolean verticalLink(int clickX1, int clickY1, int clickX2, int clickY2) { if (clickX1 > clickX2) {//保证x1<x2 int temp1 = clickX1; int temp2 = clickY1; clickX1 = clickX2; clickY1 = clickY2; clickX2 = temp1; clickY2 = temp2; } if (clickY1 == clickY2) {//可以相连 for (int i = clickX1 + 1; i < clickX2; i++) { if (map[i][clickY1] != BLANK_STATE) {//判断不可以相连 return false; } } linkMethod = LINKBYVERTICAL; return true; } return false; } //判断是否可以通过一个拐点相连 private boolean oneCornerLink(int clickX1, int clickY1, int clickX2, int clickY2) { if (clickY1 > clickY2) {//保证(x1,y1)是矩形的左上角或者左下角 int temp1 = clickX1; int temp2 = clickY1; clickX1 = clickX2; clickY1 = clickY2; clickX2 = temp1; clickY2 = temp2; } if (clickX1 < clickX2) {//如果(x1,y1)位于矩形左上角 //判断右上角是否为空并且可以直接与(x1,y1)和(x2,y2)相连接,(clickX1, clickY2)是右上角拐点下标 if (map[clickX1][clickY2] == BLANK_STATE && horizontalLink(clickX1, clickY1, clickX1, clickY2) && verticalLink(clickX2, clickY2, clickX1, clickY2)) { linkMethod = LINKBYONECORNER; z1 = new Node(clickX1, clickY2); return true; } //判断左下角是否为空并且可以直接与(x1,y1)和(x2,y2)相连接,(clickX2, clickY1)是左下角拐点下标 if (map[clickX2][clickY1] == BLANK_STATE && horizontalLink(clickX2, clickY2, clickX2, clickY1) && verticalLink(clickX1, clickY1, clickX2, clickY1)) { linkMethod = LINKBYONECORNER; z1 = new Node(clickX2, clickY1); return true; } } else {//如果(x1,y1)位于矩形左下角 //判断左上角是否为空并且可以直接与(x1,y1)和(x2,y2)相连接,(clickX2, clickY1)是左上角拐点下标 if (map[clickX2][clickY1] == BLANK_STATE && horizontalLink(clickX2, clickY2, clickX2, clickY1) && verticalLink(clickX1, clickY1, clickX2, clickY1)) { linkMethod = LINKBYONECORNER; z1 = new Node(clickX2, clickY1); return true; } //判断右下角是否为空并且可以直接与(x1,y1)和(x2,y2)相连接,(clickX1, clickY2)是右下角拐点下标 if (map[clickX1][clickY2] == BLANK_STATE && horizontalLink(clickX1, clickY1, clickX1, clickY2) && verticalLink(clickX2, clickY2, clickX1, clickY2)) { linkMethod = LINKBYONECORNER; z1 = new Node(clickX1, clickY2); return true; } } return false; } //判断是否可以相连 private boolean twoCornerLink(int clickX1, int clickY1, int clickX2, int clickY2) { //向上查找 for (int i = clickX1 - 1; i >= -1; i--) { //两个拐点在选中图案的上侧,并且两个拐点在地图区域之外 if (i == -1 && throughVerticalLink(clickX2, clickY2, true)) { z1 = new Node(-1, clickY1); z2 = new Node(-1, clickY2); linkMethod = LINKBYTWOCORNER; return true; } if (i >= 0 && map[i][clickY1] == BLANK_STATE) { if (oneCornerLink(i, clickY1, clickX2, clickY2)) { linkMethod = LINKBYTWOCORNER; z1 = new Node(i, clickY1); z2 = new Node(i, clickY2); return true; } } else { break; } } //向下查找 for (int i = clickX1 + 1; i <= n; i++) { //两个拐点在选中图案的下侧,并且两个拐点在地图区域之外 if (i == n && throughVerticalLink(clickX2, clickY2, false)) { z1 = new Node(n, clickY1); z2 = new Node(n, clickY2); linkMethod = LINKBYTWOCORNER; return true; } if (i != n && map[i][clickY1] == BLANK_STATE) { if (oneCornerLink(i, clickY1, clickX2, clickY2)) { linkMethod = LINKBYTWOCORNER; z1 = new Node(i, clickY1); z2 = new Node(i, clickY2); return true; } } else { break; } } //向左查找 for (int i = clickY1 - 1; i >= -1; i--) { //两个拐点在选中图案的左侧,并且两个拐点在地图区域之外 if (i == -1 && throughHorizontalLink(clickX2, clickY2, true)) { linkMethod = LINKBYTWOCORNER; z1 = new Node(clickX1, -1); z2 = new Node(clickX2, -1); return true; } if (i != -1 && map[clickX1][i] == BLANK_STATE) { if (oneCornerLink(clickX1, i, clickX2, clickY2)) { linkMethod = LINKBYTWOCORNER; z1 = new Node(clickX1, i); z2 = new Node(clickX2, i); return true; } } else { break; } } //向右查找 for (int i = clickY1 + 1; i <= n; i++) { //两个拐点在选中图案的右侧,并且两个拐点在地图区域之外 if (i == n && throughHorizontalLink(clickX2, clickY2, false)) { z1 = new Node(clickX1, n); z2 = new Node(clickX2, n); linkMethod = LINKBYTWOCORNER; return true; } if (i != n && map[clickX1][i] == BLANK_STATE) { if (oneCornerLink(clickX1, i, clickX2, clickY2)) { linkMethod = LINKBYTWOCORNER; z1 = new Node(clickX1, i); z2 = new Node(clickX2, i); return true; } } else { break; } } return false; } //根据flag,判断(x1,y1)左右两侧中的一侧是否还有其他图片,如果没有,可以相连 private boolean throughHorizontalLink(int clickX, int clickY, boolean flag) { if (flag) {//向左查找 for (int i = clickY - 1; i >= 0; i--) { if (map[clickX][i] != BLANK_STATE) { return false; } } } else {//向右查找 for (int i = clickY + 1; i < n; i++) { if (map[clickX][i] != BLANK_STATE) { return false; } } } return true; } //根据flag,判断(x1,y1)上下两侧中的一侧是否还有其他图片,如果没有,可以相连 private boolean throughVerticalLink(int clickX, int clickY, boolean flag) { if (flag) {//向上查找 for (int i = clickX - 1; i >= 0; i--) { if (map[i][clickY] != BLANK_STATE) { return false; } } } else {//向下查找 for (int i = clickX + 1; i < n; i++) { if (map[i][clickY] != BLANK_STATE) { return false; } } } return true; } //画选中框 private void drawSelectedBlock(int x, int y, Graphics g) { Graphics2D g2 = (Graphics2D) g;//生成Graphics对象 BasicStroke s = new BasicStroke(1);//宽度为1的画笔 g2.setStroke(s); g2.setColor(Color.RED); g.drawRect(x + 1, y + 1, 48, 48); } //画线,此处的x1,y1,x2,y2二维数组下标 @SuppressWarnings("static-access") private void drawLink(int x1, int y1, int x2, int y2) { Graphics g = this.getGraphics(); Point p1 = new Point(y1 * 50 + leftX + 25, x1 * 50 + leftY + 25); Point p2 = new Point(y2 * 50 + leftX + 25, x2 * 50 + leftY + 25); if (linkMethod == LINKBYHORIZONTAL || linkMethod == LINKBYVERTICAL) { g.drawLine(p1.x, p1.y, p2.x, p2.y); System.out.println("无拐点画线"); } else if (linkMethod == LINKBYONECORNER) { Point point_z1 = new Point(z1.y * 50 + leftX + 25, z1.x * 50 + leftY + 25);//将拐点转换成像素坐标 g.drawLine(p1.x, p1.y, point_z1.x, point_z1.y); g.drawLine(p2.x, p2.y, point_z1.x, point_z1.y); System.out.println("单拐点画线"); } else { Point point_z1 = new Point(z1.y * 50 + leftX + 25, z1.x * 50 + leftY + 25); Point point_z2 = new Point(z2.y * 50 + leftX + 25, z2.x * 50 + leftY + 25); if (p1.x != point_z1.x && p1.y != point_z1.y) {//保证(x1,y1)与拐点z1在同一列或者同一行 Point temp; temp = point_z1; point_z1 = point_z2; point_z2 = temp; } g.drawLine(p1.x, p1.y, point_z1.x, point_z1.y); g.drawLine(p2.x, p2.y, point_z2.x, point_z2.y); g.drawLine(point_z1.x, point_z1.y, point_z2.x, point_z2.y); System.out.println("双拐点画线"); } count += 2;//消去的方块数目+2 GameClient.textField.setText(count + ""); try { Thread.currentThread().sleep(500);//延时500ms } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } repaint(); map[x1][y1] = BLANK_STATE; map[x2][y2] = BLANK_STATE; isWin();//判断游戏是否结束 } public void clearSelectBlock(int i, int j, Graphics g) { g.clearRect(j * 50 + leftX, i * 50 + leftY, 50, 50); g.drawImage(pics[map[i][j]], leftX + j * 50, leftY + i * 50, 50, 50, this); // System.out.println("清空选定"+i+","+j); } private boolean find2Block() { // boolean isFound = false; if (isClick) {//如果之前玩家选中了一个方块,清空该选中框 clearSelectBlock(clickX, clickY, this.getGraphics()); isClick = false; } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (map[i][j] == BLANK_STATE) { continue; } for (int p = i; p < n; p++) { for (int q = 0; q < n; q++) { if (map[p][q] != map[i][j] || (p == i && q == j)) {//如果图案不相等 continue; } if (verticalLink(p, q, i, j) || horizontalLink(p, q, i, j) || oneCornerLink(p, q, i, j) || twoCornerLink(p, q, i, j)) { drawSelectedBlock(j * 50 + leftX, i * 50 + leftY, this.getGraphics()); drawSelectedBlock(q * 50 + leftX, p * 50 + leftY, this.getGraphics()); drawLink(p, q, i, j); repaint(); return true; } } } } } isWin(); return false; } private void isWin() { if (count == n * n) { String msg = "恭喜您通关成功,是否开始新局?"; int type = JOptionPane.YES_NO_OPTION; String title = "过关"; int choice = 0; choice = JOptionPane.showConfirmDialog(null, msg, title, type); if (choice == 1) { System.exit(0); } else if (choice == 0) { startNewGame(); } } } public void startNewGame() { // TODO Auto-generated method stub count = 0; mapUtil = new Map(10, n); map = mapUtil.getMap(); isClick = false; clickId = -1; clickX = -1; clickY = -1; linkMethod = -1; GameClient.textField.setText(count + ""); repaint(); } public class Node { int x; int y; public Node(int x, int y) { this.x = x; this.y = y; } } @Override public void keyPressed(KeyEvent e) { // TODO Auto-generated method stub if (e.getKeyCode() == KeyEvent.VK_A) {//打乱地图 map = mapUtil.getResetMap(); repaint(); } if (e.getKeyCode() == KeyEvent.VK_D) {//智能提示 if (!find2Block()) { JOptionPane.showMessageDialog(this, "没有可以连通的方块了"); } isWin();//判断是否游戏结束 } } @Override public void mousePressed(MouseEvent e) { // TODO Auto-generated method stub Graphics g = this.getGraphics(); int x = e.getX() - leftX;//点击位置x-偏移量x int y = e.getY() - leftY;//点击位置y-偏移量y int i = y / 50;//对应数组行数,根据像素坐标转换成数组下标坐标 int j = x / 50;//对应数组列数 if (x < 0 || y < 0)//超出地图范围 return; if (isClick) {//第二次点击 if (map[i][j] != BLANK_STATE) { if (map[i][j] == clickId) {//点击的是相同图片Id,但不是重复点击同一图片 if (i == clickX && j == clickY) return; if (verticalLink(clickX, clickY, i, j) || horizontalLink(clickX, clickY, i, j) || oneCornerLink(clickX, clickY, i, j) || twoCornerLink(clickX, clickY, i, j)) {//如果可以连通,画线连接,然后消去选中图片并重置第一次选中标识 drawSelectedBlock(j * 50 + leftX, i * 50 + leftY, g); drawLink(clickX, clickY, i, j);//画线连接 isClick = false; } else { clickId = map[i][j];//重新选中图片并画框 clearSelectBlock(clickX, clickY, g); clickX = i; clickY = j; drawSelectedBlock(j * 50 + leftX, i * 50 + leftY, g); } } else { clickId = map[i][j];//重新选中图片并画框 clearSelectBlock(clickX, clickY, g); clickX = i; clickY = j; drawSelectedBlock(j * 50 + leftX, i * 50 + leftY, g); } } } else {//第一次点击 if (map[i][j] != BLANK_STATE) { //选中图片并画框 clickId = map[i][j]; isClick = true; clickX = i; clickY = j; drawSelectedBlock(j * 50 + leftX, i * 50 + leftY, g); } } } @Override public void mouseClicked(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseReleased(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub } @Override public void keyTyped(KeyEvent e) { // TODO Auto-generated method stub } @Override public void keyReleased(KeyEvent e) { // TODO Auto-generated method stub } }