zoukankan      html  css  js  c++  java
  • 小游戏五子连珠消除解决方案

    序言

    五子连珠,顾名思义就是当有五个相同的球在一条直线上,横,竖,斜,总共四个方向呈《米》型的消除规则,达到5个或者5个以上

    但是我们的五子连珠不是达到五个就结束,只是连续相同的5个或者5个以上的棋子会被消除同时增加对应的积分;

    我们的设计是棋盘上 是 8 * 8 坐标格子,

    总共有6总颜色的球,五个独立颜色(色号1-5),一个是彩色叫万能替代球(色号6);

    还有一个附加状态是球有爆炸效果

    棋子在棋盘上可以沿着四个方向移动,然后移动到需要移动的地方,所以这里采用A*算法来做格子移动;

    如果移动棋子没有可以消除的棋子,棋盘上会随机刷出三个新的球;

    设计

     先设计基本棋盘代码,完成基础存储功能 

     1 import java.io.Serializable;
     2 
     3 /**
     4  * @author: Troy.Chen(失足程序员 , 15388152619)
     5  * @create: 2020-11-23 22:37
     6  **/
     7 public class Wzlz implements Serializable {
     8 
     9     private static final long serialVersionUID = 1L;
    10 
    11     /*用于A* 算法的移动寻路导航,*/
    12     protected int[][] blockCells;
    13     /*棋盘上每个格子状态*/
    14     protected Qiu[][] qiuCells;
    15 
    16     public Wzlz() {
    17         blockCells = new int[8][8];
    18         qiuCells = new Qiu[8][8];
    19         for (int z = 0; z < blockCells.length; z++) {
    20             for (int x = 0; x < blockCells[z].length; x++) {
    21                 blockCells[z][x] = 0;
    22                 qiuCells[z][x] = new Qiu(0, x, z);
    23             }
    24         }
    25     }
    26 
    27     public class Qiu {
    28         /*1-5是五个颜色的球,6是彩色万能球*/
    29         private int qiuId;
    30         private int x;
    31         private int z;
    32         private int zhadan;
    33 
    34         public Qiu() {
    35         }
    36 
    37         public Qiu(int qiuId, int x, int z) {
    38             this.qiuId = qiuId;
    39             this.x = x;
    40             this.z = z;
    41         }
    42 
    43         public int getQiuId() {
    44             return qiuId;
    45         }
    46 
    47         public void setQiuId(int qiuId) {
    48             this.qiuId = qiuId;
    49         }
    50 
    51         public int getX() {
    52             return x;
    53         }
    54 
    55         public void setX(int x) {
    56             this.x = x;
    57         }
    58 
    59         public int getZ() {
    60             return z;
    61         }
    62 
    63         public void setZ(int z) {
    64             this.z = z;
    65         }
    66 
    67         public int getZhadan() {
    68             return zhadan;
    69         }
    70 
    71         public void setZhadan(int zhadan) {
    72             this.zhadan = zhadan;
    73         }
    74     }
    75 
    76     public void print() {
    77         StringBuilder stringBuilder = new StringBuilder();
    78         stringBuilder.append("==============================================================");
    79         stringBuilder.append("
    ");
    80         for (int z = 0; z < qiuCells.length; z++) {
    81             for (int x = 0; x < qiuCells[z].length; x++) {
    82                 stringBuilder.append(qiuCells[z][x].getQiuId() + "(" + qiuCells[z][x].getZhadan() + ")" + ", ");
    83             }
    84             stringBuilder.append("
    ");
    85         }
    86         stringBuilder.append("==============================================================");
    87         System.out.println(stringBuilder.toString());
    88     }
    89 }

    初始化一下类,然后看一下棋盘打印

     1 import java.io.Serializable;
     2 
     3 /**
     4  * @author: Troy.Chen(失足程序员 , 15388152619)
     5  * @create: 2020-11-23 22:59
     6  **/
     7 public class WzlzMain implements Serializable {
     8 
     9     private static final long serialVersionUID = 1L;
    10 
    11     public static void main(String[] args) {
    12         Wzlz wzlzTest = new Wzlz();
    13         wzlzTest.print();
    14     }
    15 
    16 
    17     public static void test(int[][] cells, Wzlz.Qiu[][] qius, int x, int z, int qiu) {
    18         /*设置格子阻挡信息*/
    19         cells[z][x] = 1;
    20         /*设置球的id*/
    21         qius[z][x].setQiuId(qiu);
    22     }
    23 }
    View Code

    棋盘初始化完成;

    如何消除棋子;

    如何只是横向或者纵向,我们想很多人都知道。

    我先看一段简单代码

     1     public static void xiaochu(int[][] cells, Wzlz.Qiu[][] qius) {
     2         Set<Wzlz.Qiu> qiuSet = new HashSet<>();
     3         /*消除横线算法*/
     4         for (int z = 0; z < qius.length; z++) {
     5             int qiuid = 0;
     6             List<Wzlz.Qiu> qiuList = new ArrayList<>();
     7             for (int x = 0; x < qius[z].length; x++) {
     8                 final Wzlz.Qiu qiu = qius[z][x];
     9                 if (qiu.getQiuId() == 0 || (qiuid != 0 && qiu.getQiuId() != 6/*不是万能球*/ && qiu.getQiuId() != qiuid)) {
    10                     if (qiuList.size() >= 5) {
    11                         qiuSet.addAll(qiuList);
    12                     }
    13                     qiuid = 0;
    14                     qiuList.clear();
    15                 }
    16 
    17                 if (qiu.getQiuId() != 0) {
    18                     if (qiu.getQiuId() != 6) {
    19                         /*记录除万能球在内的;连续球的数量*/
    20                         qiuid = qiu.getQiuId();
    21                     }
    22                     qiuList.add(qiu);
    23                 }
    24             }
    25             if (qiuList.size() >= 5) {
    26                 qiuSet.addAll(qiuList);
    27             }
    28         }
    29         for (Wzlz.Qiu qiu : qiuSet) {
    30             qiu.setQiuId(0);
    31             /*清理阻挡状态*/
    32             cells[qiu.getZ()][qiu.getX()] = 0;
    33         }
    34     }

    我们先来看一段消除横线连珠的代码

    编写一下测试代码,这段代码折叠一下

     1     public static void main(String[] args) {
     2         Wzlz wzlzTest = new Wzlz();
     3         test(wzlzTest.blockCells, wzlzTest.qiuCells, 0, 0, 3);
     4         test(wzlzTest.blockCells, wzlzTest.qiuCells, 1, 0, 6);
     5         test(wzlzTest.blockCells, wzlzTest.qiuCells, 2, 0, 6);
     6         test(wzlzTest.blockCells, wzlzTest.qiuCells, 3, 0, 3);
     7         test(wzlzTest.blockCells, wzlzTest.qiuCells, 4, 0, 3);
     8         test(wzlzTest.blockCells, wzlzTest.qiuCells, 5, 0, 4);
     9         test(wzlzTest.blockCells, wzlzTest.qiuCells, 6, 0, 4);
    10         wzlzTest.print();
    11         xiaochu(wzlzTest.blockCells, wzlzTest.qiuCells);
    12         wzlzTest.print();
    13     }
    View Code

    查看一下结果

    消除成功;

    看到这里,可能还没有发现一个问题

    我们修改一下测试代码,我刚才测试代码的第一个球的颜色改为1,把第6个球的颜色改3,也就是2-6是相同的5个颜色

    再来看执行效果

    可以看出来,棋子并没有被消除;

    原因是这段代码是单链循环,

    单身我们理想的效果是不是应该是这样?第一个,开始往后找,如果不对,从第二个开始往后找;

    所以我们修改递归循环代码

     1 public static void xiaochu(int[][] cells, Wzlz.Qiu[][] qius) {
     2         Set<Wzlz.Qiu> qiuSet = new HashSet<>();
     3         /*消除横线算法*/
     4         for (int z = 0; z < qius.length; z++) {
     5             for (int x = 0; x < qius[z].length; x++) {
     6                 int qiuid = 0;
     7                 List<Wzlz.Qiu> qiuList = new ArrayList<>();
     8                 for (int x1 = x; x1 < qius[z].length; x1++) {
     9                     final Wzlz.Qiu qiu = qius[z][x1];
    10                     if (qiu.getQiuId() == 0 || (qiuid != 0 && qiu.getQiuId() != 6/*不是万能球*/ && qiu.getQiuId() != qiuid)) {
    11                         if (qiuList.size() >= 5) {
    12                             qiuSet.addAll(qiuList);
    13                         }
    14                         qiuid = 0;
    15                         qiuList.clear();
    16                     }
    17 
    18                     if (qiu.getQiuId() != 0) {
    19                         if (qiu.getQiuId() != 6) {
    20                             /*记录除万能球在内的;连续球的数量*/
    21                             qiuid = qiu.getQiuId();
    22                         }
    23                         qiuList.add(qiu);
    24                     }
    25                 }
    26 
    27                 if (qiuList.size() >= 5) {
    28                     qiuSet.addAll(qiuList);
    29                 }
    30             }
    31         }
    32         for (Wzlz.Qiu qiu : qiuSet) {
    33             qiu.setQiuId(0);
    34             /*清理阻挡状态*/
    35             cells[qiu.getZ()][qiu.getX()] = 0;
    36         }
    37     }

    注意for里面的x和for里面的x1;这两个循环

    来看看效果

    第2-6个球成功消除;

    横线消除,竖线消除其实就是一个道理,只是换一下循环方向就能实现;

    暂时就不再赘述;

    那么问题和难点在哪里?

    其实因为消除规则是《米》字型的,也就是斜线消除;

    其实根据刚才写法,找到消除规则和算法并不难;

    只需要把x和z坐标都加一取下一个格子就能判断,就不在赘述;

     1 import com.ty.tools.dlog.DLogger;
     2 
     3 import java.io.Serializable;
     4 
     5 /**
     6  * @author: Troy.Chen(失足程序员 , 15388152619)
     7  * @create: 2020-11-18 10:37
     8  **/
     9 public class WzlzTest implements Serializable {
    10 
    11     private static final long serialVersionUID = 1L;
    12     private static final DLogger log = DLogger.getLogger();
    13 
    14     public static void main(String[] args) {
    15         int mx = 7;
    16         int x = 0;
    17         int z = 0;
    18         /* todo         正方形的左上方的三角形 ↙↙↙↙            */
    19         while (true) {
    20             int z1 = z;
    21             int x1 = x;
    22             while (true) {
    23                 System.out.print("[" + x1 + "," + z1 + "]");
    24                 x1--;
    25                 z1++;
    26                 if (x1 < 0 || z1 > mx) {
    27                     break;
    28                 }
    29             }
    30             System.out.println();
    31             if (x < 7) {
    32                 x++;
    33             } else if (z <= mx) {
    34                 z++;
    35             }
    36 
    37             if (x >= mx && z > mx) {
    38                 break;
    39             }
    40         }
    41         System.out.println("=================================================================");
    42         x = 7;
    43         z = 0;
    44         /*    todo        从左边一直往右边斜 ↘↘↘↘            */
    45         while (true) {
    46             int z1 = z;
    47             int x1 = x;
    48             while (true) {
    49                 System.out.print("[" + x1 + "," + z1 + "]");
    50                 x1++;
    51                 z1++;
    52                 if (x1 > mx || z1 > mx) {
    53                     break;
    54                 }
    55             }
    56             System.out.println();
    57             if (x > 0) {
    58                 x--;
    59             } else if (z <= mx) {
    60                 z++;
    61             }
    62             if (z > mx && x <= 0) {
    63                 break;
    64             }
    65         }
    66         System.exit(0);
    67     }
    68 
    69 }
    View Code

    这是寻找格子的基本算法,愿意的可以打开看看;

    如果说这不是重点那么什么才是重点?

    其实上面的代码不知道你们发现了没有;其实是再一次移动棋子后去调用执行查找的,每一次都要重新组装棋子。

    其实我们是不是可以一次性把棋子组装完成?

      1 import java.io.Serializable;
      2 import java.util.ArrayList;
      3 import java.util.Iterator;
      4 import java.util.LinkedList;
      5 import java.util.List;
      6 
      7 /**
      8  * @author: Troy.Chen(失足程序员 , 15388152619)
      9  * @create: 2020-11-23 22:37
     10  **/
     11 public class Wzlz implements Serializable {
     12 
     13     private static final long serialVersionUID = 1L;
     14 
     15     /*用于A* 算法的移动寻路导航,*/
     16     protected int[][] blockCells;
     17     /*棋盘上每个格子状态*/
     18     protected Qiu[][] qiuCells;
     19     /*纵横交错的排列*/
     20     protected List<List<Wzlz.Qiu>> qiuLines = new LinkedList<>();
     21 
     22 
     23     public Wzlz() {
     24         blockCells = new int[8][8];
     25         qiuCells = new Qiu[8][8];
     26         for (int z = 0; z < blockCells.length; z++) {
     27             for (int x = 0; x < blockCells[z].length; x++) {
     28                 blockCells[z][x] = 0;
     29                 qiuCells[z][x] = new Qiu(0, x, z);
     30             }
     31         }
     32         resetHangline();
     33     }
     34 
     35     /**
     36      * 四个方向的组装
     37      */
     38     public void resetHangline() {
     39         if (qiuCells == null || qiuCells.length < 1) {
     40             return;
     41         }
     42         qiuLines = new ArrayList<>();
     43         /* todo    组装 横着的行数据 → */
     44         for (int z = 0; z < qiuCells.length; z++) {
     45             List<Wzlz.Qiu> line = new LinkedList<>();
     46             for (int x = 0; x < qiuCells[z].length; x++) {
     47                 line.add(qiuCells[z][x]);
     48             }
     49             qiuLines.add(line);
     50         }
     51 
     52         /* todo    组装 竖着的行数据 → */
     53         for (int x = 0; x < qiuCells[0].length; x++) {
     54             List<Wzlz.Qiu> line = new LinkedList<>();
     55             for (int z = 0; z < qiuCells.length; z++) {
     56                 line.add(qiuCells[z][x]);
     57             }
     58             qiuLines.add(line);
     59         }
     60 
     61         int mx = qiuCells.length - 1;
     62         int x = 0;
     63         int z = 0;
     64         /* todo    组装  正方形的左上方的三角形 ↙↙↙↙            */
     65         while (true) {
     66             int z1 = z;
     67             int x1 = x;
     68             List<Wzlz.Qiu> line = new LinkedList<>();
     69             while (true) {
     70                 line.add(qiuCells[z1][x1]);
     71 //                System.out.print("[" + x1 + "," + z1 + "]");
     72                 x1--;
     73                 z1++;
     74                 if (x1 < 0 || z1 > mx) {
     75                     break;
     76                 }
     77             }
     78             qiuLines.add(line);
     79 //            System.out.println();
     80             if (x < 7) {
     81                 x++;
     82             } else if (z <= mx) {
     83                 z++;
     84             }
     85             if (x >= mx && z > mx) {
     86                 break;
     87             }
     88         }
     89 
     90         x = qiuCells.length - 1;
     91         z = 0;
     92         /*    todo        从左边一直往右边斜 ↘↘↘↘            */
     93         while (true) {
     94             int z1 = z;
     95             int x1 = x;
     96             List<Wzlz.Qiu> line = new LinkedList<>();
     97             while (true) {
     98 //                System.out.print("[" + x1 + "," + z1 + "]");
     99                 line.add(qiuCells[z1][x1]);
    100                 x1++;
    101                 z1++;
    102                 if (x1 > mx || z1 > mx) {
    103                     break;
    104                 }
    105             }
    106             qiuLines.add(line);
    107 //            System.out.println();
    108             if (x > 0) {
    109                 x--;
    110             } else if (z <= mx) {
    111                 z++;
    112             }
    113             if (z > mx && x <= 0) {
    114                 break;
    115             }
    116         }
    117         for (Iterator<List<Wzlz.Qiu>> integerIterator = qiuLines.iterator(); integerIterator.hasNext(); ) {
    118             List<Wzlz.Qiu> next = integerIterator.next();
    119             if (next.size() < 5) {
    120                 integerIterator.remove();
    121             }
    122         }
    123     }
    124 
    125     public class Qiu {
    126         /*1-5是五个颜色的球,6是彩色万能球*/
    127         private int qiuId;
    128         private int x;
    129         private int z;
    130         private int zhadan;
    131 
    132         public Qiu() {
    133         }
    134 
    135         public Qiu(int qiuId, int x, int z) {
    136             this.qiuId = qiuId;
    137             this.x = x;
    138             this.z = z;
    139         }
    140 
    141         public int getQiuId() {
    142             return qiuId;
    143         }
    144 
    145         public void setQiuId(int qiuId) {
    146             this.qiuId = qiuId;
    147         }
    148 
    149         public int getX() {
    150             return x;
    151         }
    152 
    153         public void setX(int x) {
    154             this.x = x;
    155         }
    156 
    157         public int getZ() {
    158             return z;
    159         }
    160 
    161         public void setZ(int z) {
    162             this.z = z;
    163         }
    164 
    165         public int getZhadan() {
    166             return zhadan;
    167         }
    168 
    169         public void setZhadan(int zhadan) {
    170             this.zhadan = zhadan;
    171         }
    172     }
    173 
    174     public void print() {
    175         StringBuilder stringBuilder = new StringBuilder();
    176         stringBuilder.append("==============================================================");
    177         stringBuilder.append("
    ");
    178         for (int z = 0; z < qiuCells.length; z++) {
    179             for (int x = 0; x < qiuCells[z].length; x++) {
    180                 stringBuilder.append(qiuCells[z][x].getQiuId() + "(" + qiuCells[z][x].getZhadan() + ")" + ", ");
    181             }
    182             stringBuilder.append("
    ");
    183         }
    184         stringBuilder.append("==============================================================");
    185         System.out.println(stringBuilder.toString());
    186     }
    187 }

    于是有了以上代码,第一次初始化就把横线,纵向,斜线的连线全部组装完成

     1 import java.io.Serializable;
     2 import java.util.ArrayList;
     3 import java.util.HashSet;
     4 import java.util.List;
     5 import java.util.Set;
     6 
     7 /**
     8  * @author: Troy.Chen(失足程序员 , 15388152619)
     9  * @create: 2020-11-23 22:59
    10  **/
    11 public class WzlzMain implements Serializable {
    12 
    13     private static final long serialVersionUID = 1L;
    14 
    15     public static void main(String[] args) {
    16         Wzlz wzlzTest = new Wzlz();
    17         test(wzlzTest.blockCells, wzlzTest.qiuCells, 0, 0, 1);
    18         test(wzlzTest.blockCells, wzlzTest.qiuCells, 1, 1, 6);
    19         test(wzlzTest.blockCells, wzlzTest.qiuCells, 2, 2, 6);
    20         test(wzlzTest.blockCells, wzlzTest.qiuCells, 3, 3, 3);
    21         test(wzlzTest.blockCells, wzlzTest.qiuCells, 4, 4, 3);
    22         test(wzlzTest.blockCells, wzlzTest.qiuCells, 5, 5, 3);
    23         test(wzlzTest.blockCells, wzlzTest.qiuCells, 6, 6, 4);
    24         wzlzTest.print();
    25         xiaochu(wzlzTest.blockCells, wzlzTest.qiuLines);
    26         wzlzTest.print();
    27     }
    28 
    29 
    30     public static void test(int[][] cells, Wzlz.Qiu[][] qius, int x, int z, int qiu) {
    31         /*设置格子阻挡信息*/
    32         cells[z][x] = 1;
    33         /*设置球的id*/
    34         qius[z][x].setQiuId(qiu);
    35     }
    36 
    37     public static void xiaochu(int[][] cells, List<List<Wzlz.Qiu>> qiuLines) {
    38         Set<Wzlz.Qiu> xiaochu = new HashSet<>();
    39         for (List<Wzlz.Qiu> line : qiuLines) {
    40             for (int i = 0; i < line.size(); i++) {
    41                 int qid = 0;
    42                 List<Wzlz.Qiu> list = new ArrayList<>();
    43                 for (int k = i; k < line.size(); k++) {
    44                     Wzlz.Qiu qiu = line.get(k);
    45                     if (qiu.getQiuId() == 0 || (qid != 0 && qid != qiu.getQiuId() && qiu.getQiuId() != 6)) {
    46                         if (list.size() >= 5) {
    47                             /*todo 前面都是连续相同的*/
    48                             xiaochu.addAll(list);
    49                         }
    50                         /*到这里就表示没有相同的棋子需要清理*/
    51                         qid = 0;
    52                         list.clear();
    53                     }
    54                     if (qiu.getQiuId() > 0) {
    55                         if (qiu.getQiuId() != 6) {
    56                             qid = qiu.getQiuId();
    57                         }
    58                         list.add(qiu);
    59                     }
    60                 }
    61                 if (list.size() >= 5) {
    62                     /*先查找最后消除*/
    63                     xiaochu.addAll(list);
    64                 }
    65             }
    66         }
    67         for (Wzlz.Qiu qiu : xiaochu) {
    68             qiu.setQiuId(0);
    69             /*球阻挡清空*/
    70             cells[qiu.getZ()][qiu.getX()] = 0;
    71         }
    72     }
    73 
    74 }

    调整消除代码,这样每次获取连线代码都变得简单清晰

    总结:

    其实网上算法很多;但是基本都是一次性的,也就是说他们是正中的五子棋,因为只要有五个连珠的棋子就结束了需要重新来;

    但是我们这个变种的。有5个相同的只会消除,然后继续玩;

    所以算法稍稍不同,但是基本也是大同小异;

  • 相关阅读:
    Java 抽象类和抽象方法
    java中的不为空判断
    表单form action的url写法
    对称加密和非对称加密
    spring全注解项目
    java自定义异常
    Spring data jpa学习
    SpringMVC实现简单应用
    MySql与Java的时间类型
    java反射
  • 原文地址:https://www.cnblogs.com/shizuchengxuyuan/p/14027912.html
Copyright © 2011-2022 走看看