黑马程序员技术交流社区

标题: JavaEE第7天自虐综合练习之简化版扫雷 [打印本页]

作者: esaygoing    时间: 2018-3-24 10:40
标题: JavaEE第7天自虐综合练习之简化版扫雷
经过一周的学习终于把前面的JavaEE语法基础学完了,刚好碰上自习,自己琢磨着综合一下学过的知识,自己给自己出了个综合练习。运用之前一周学过的知识写一个简化版的扫雷出来,终于可以自己写点能玩的了,想想就激动啊有木有……此处省略1000字。

好吧,学着老师之前教的,首先进行需求分析。刚刚学了数组和面向对象,刚好可以拿来做个简单的游戏。
首先扫雷的地图好像是随机生成的,那么好像可以用到刚学的Random类,然后用二维数组生成随机的地图,地图的数字就可以用来判定哪个是雷区,选1-5吧,然后把5当雷了。而且扫雷的地图有明暗之分,为了方便存储多个数据,创建一个雷的对象吧。嗯,还有,控制台打印的稍微好看点,打印的时候顺便画个框框边界出来。判断雷 用数字的话好像很麻烦,用boolean比较简单,为了降低难度,还是不设定自己输入扫雷游戏的数组大小了。

主要流程大概就是:
1. 生成游戏的地图
2.循环输入坐标
3.几个辅助方法的编写
        检测函数,打印函数,等等
4.游戏胜负的判定

最难的大概就是地图的生成了.



[attach]218844[/attach] 想了一天,直接上代码吧
//雷区类
/*主要用Boom的二维数组来进行同一个坐标点的多个属性的实现
* 例如 是否是雷的判断,修改是否显示当前位置的内容,存储当前内容属性
*/
public class Boom {
        private int Id;                                        //标记属性,-1为周边无雷,-4为雷,正数1-8代表
                                                                //以该点为中心一周范围内的雷的数目
       
        private String ico;                               //根据标记数字转化相应的字符串存入此处,用于图标显示
       
        private boolean bang = false;            //是否是雷的标记,true 为雷,默认为false,地图生成时根据随机数修改
       
        private boolean flag = false;              //在扫雷地图上是否显示的标记 true显示,false不显示,默认不显示,选择点的时候修改
       
        public Boom() {                                      //不需要有参构造,写个空参就好.
        }
        public String getIco() {
                return ico;
        }
        public void setIco(String ico) {
                this.ico = ico;
        }
        public int getId() {
                return Id;
        }
        public void setId(int id) {
                Id = id;
        }
        public boolean isBang() {
                return bang;
        }
        public void setBang(boolean bang) {
                this.bang = bang;
        }
        public boolean isFlag() {
                return flag;
        }
        public void setFlag(boolean flag) {
                this.flag = flag;
        }       
}
以下是测试类的代码再也不自己乱玩了
package com.itheima_02;
import java.util.Random;
import java.util.Scanner;

public class RunBoom {

        public static void main(String[] args) {
                Random r = new Random();

                int[][] map = new int[12][18];     //二维随机数数组,提供随机的数字分布
                int[][] gameMap = new int[10][16]; //根据map生成扫雷的主要游戏数组

                Boom[][] show = new Boom[12][18];//真正的用于修改的游戏地图
               
               
                //初始化随机地图,二维数组边界为全部是系统初始化的0 ,便于判断扫雷地图的边界雷区
                //主要是为了防止检测的时候数组越界
                //从[1][1]到[max-1][max-1]
                for (int i = 1; i < map.length-1; i++) {
                        for (int j = 1; j < map.length-1; j++) {
                                map[j] = r.nextInt(5) + 1;        //随机范围 1-5
                        }
                }
                //printSoSo(map);这个是测试用的,打印查看随机数数组的生成情况
               
                //获取gameMap 去掉map的边框并且检测每个位置的周边含有数字5的情况(就是含有雷的数目)
                for (int i = 1; i < map.length-1; i++) {
                        for (int j = 1; j < map.length-1; j++) {
                                Boom b = new Boom();//每次都需要一个新的对象,用于存入Boom[][]中

                                //计数器,存储每个坐标周围的的雷的个数
                                int count = 0;
                                //已map[j]为中心进行边缘一圈检测
                                if (map[i - 1][j - 1] == 5) {
                                        count++;
                                }
                                if (map[i - 1][j] == 5) {
                                        count++;
                                }
                                if (map[i - 1][j + 1] == 5) {
                                        count++;
                                }
                                if (map[j - 1] == 5) {
                                        count++;
                                }
                                if (map[j + 1] == 5) {
                                        count++;
                                }
                                if (map[i + 1][j - 1] == 5) {
                                        count++;
                                }
                                if (map[i + 1][j + 1] == 5) {
                                        count++;
                                }
                                if (map[i + 1][j] == 5) {
                                        count++;
                                }
                                //这里gameMap是比map 两边都少1
                                gameMap[i-1][j-1] = count;

                                //此处设置 地图随机点 为5 的 时候    为雷
                                if (map[j]==5) {
                                        b.setBang(true);//改变Boom对象的bang属性
                                }

                                /*其实gameMap应该是不必要的,可以直接存入Boom的对象中,主要是一开始自己写的
                                  Boom类没那么多属性,后来写的过程中,慢慢调试加入的.后来写完了,感觉太痛苦,就不改了……
                                */
                                b.setId(gameMap[i-1][j-1]);
                               
                                show[j]=b;
                                //将Boom对象放入Boom的二维数组,注意,此处的数组中有一圈是null的,
                                //后面会进行数组修复,为了使检测到这些位置的时候自动停止,防止数组越界
                        }
                }
                //printSoSo(show); 这是测试用,看看地图生成的情况,下一行一样。
                //printSoSo(gameMap);

                //根据Id属性,对Boom的二维数组进行对应的ico的修改
                //"#"代表雷," "代表周围一圈无雷,数字代表周围雷的数目,都以字符串的形式存入ico属性
                change(show);

                //对Boom数组的边界进行修复
                repair(show);
                //printIco(show);


                while (true) {
                        Scanner sc = new Scanner(System.in);
                        //print(show);
                        int wide;//横坐标
                        int deep;//纵坐标
                        System.out.println("欢迎来到渣渣的扫雷,请输入横纵坐标(1-10)(1-16)");
                        while (true) {
                                System.out.println("请输入横坐标");
                                wide = sc.nextInt();
                                if (wide <= 10 && wide >= 1) {
                                        //wide -= 1;
                                        break;
                                } else {
                                        System.out.println("请输入正确的横坐标");
                                }
                        }
                        while (true) {
                                System.out.println("请输入纵坐标");
                                deep = sc.nextInt();
                                if (deep <= 16 && deep >= 1) {
                                        //deep -= 1;
                                        break;
                                } else {
                                        System.out.println("请输入正确的纵坐标");
                                }
                        }
                        //改变地图,判断结果
                        changeMap(show, wide, deep);
                       
                       
                       
                }
        }



        //游戏开始时函数.功能:改变显示,判断 gameover 与 win
        public static void changeMap(Boom[][] show, int wide, int deep) {
                if (show[wide][deep].isBang() == true) {
                        System.out.println("你摸到雷了哦,gameover");

                        //判断是雷,游戏结束,修改所有对象的显示属性, war 3   "i see dead people".
                        for (int i = 1; i < show.length-1; i++) {
                                for (int j = 1; j < show.length-1; j++) {
                                        show[j].setFlag(true);
                                }
                        }
                        printIco(show);//打印全图
                        System.exit(0);//关机
                } else {
                        //判断不为雷,则修改显示标记
                        show[wide][deep].setFlag(true);

                        //检测该坐标周围是否无雷,无雷显示
                        check(show,wide,deep);


                        //改变地图后,统计当前Boom[][]中是否还存在非雷的未显示的对象
                        int count = 0;
                        for (int i = 1; i < show.length-1; i++) {
                                for (int j = 1; j < show.length-1; j++) {
                                        if (show[j].isFlag()==false&&show[j].isBang()==false) {
                                                count++;
                                        }
                                }
                        }
                        //如果所有的非雷对象都被显示,则游戏结束
                        if (count==0) {
                                System.out.println("you win");

                                System.exit(0);//关闭虚拟机
                        }
                        printIco(show);//打印刷新后的  扫雷地图
                }
        }

        //修复函数,把周围边界的值设定好
        public static void repair(Boom[][] show){
                for (int i = 0; i < show.length; i++) {
                        for (int j = 0; j < show.length; j++) {

                                //二维数组中无对象,则写入
                                if (show[j]==null) {
                                        Boom empty = new Boom();
                                        empty.setId(9);                              //原本想留着有用,终究没用上
                                        empty.setIco(" ");
                                        empty.setBang(false);
                                        empty.setFlag(true);
                                        show[j] = empty;
                                }
                        }
                }
        }

        //刚开始想递归检测,栈内存溢出,后来放弃了,...技术太差,装不来
        /*
        检测函数,功能是检测输入点的一周是否无雷,无雷则全部显示;
        写完后就没修改了,比较复杂,后来写注释的时候,感觉不用这么麻烦;
        点周围一圈无雷的话直接判断输入点坐标对象的Id是否为-4或者其ico是否equals(" ")就可以了;
        */
        public static void check(Boom[][] show,int wide,int deep) {
                //if(show[wide][deep].getId()!=9){
                //判断条件很恶心......
                        if (show[wide-1][deep].isBang()==false&&show[wide-1][deep-1].isBang()==false&&show[wide-1][deep+1].isBang()==false&&show[wide][deep-1].isBang()==false&&show[wide][deep+1].isBang()==false&&show[wide+1][deep-1].isBang()==false&&show[wide+1][deep].isBang()==false&&show[wide+1][deep+1].isBang()==false) {
                               
                                show[wide-1][deep].setFlag(true);
                               
                                show[wide-1][deep-1].setFlag(true);
                               
                                show[wide-1][deep+1].setFlag(true);
               
                               
                                show[wide][deep+1].setFlag(true);
                               
                                show[wide][deep-1].setFlag(true);
                               
                               
                                show[wide+1][deep].setFlag(true);
                               
                                show[wide+1][deep-1].setFlag(true);
                               
                                show[wide+1][deep+1].setFlag(true);
                               
               
                }       
               
                       
        }       
                       

                               
                       
        //测试用的数组内容显示函数
        public static void testPrintIco(Boom[][] show){
                for (int i = 1; i < show.length-1; i++) {
                        for (int j = 1; j < show.length-1; j++) {
                                System.out.print(show[j].getIco()+"|");
                        }
                        System.out.println();
                        System.out.println("————————————————————————————————");
                }
               
        }

        //游戏中打印函数,根据flag 决定是否显示当前位置,顺便画了个简易的框图.
        public static void printIco(Boom[][] show){
                for (int i = 1; i < show.length-1; i++) {
                        System.out.println(" ————————————————————————————————");
                        System.out.print("|");
                        for (int j = 1; j < show.length-1; j++) {
                               
                                if (show[j].isFlag()) {
                                        System.out.print(show[j].getIco()+"|");
                                }else{
                                        System.out.print("*|");
                                }
                               
                        }
                        System.out.println();
                       
                }
                System.out.println(" ————————————————————————————————");
        }


        public static void change(Boom[][] show){
                //遍历检测 雷和无雷的位置,并且修改相应对象的Id
                for (int i = 1; i < show.length-1; i++) {
                        for (int j = 1; j < show.length-1; j++) {
                                if (show[j].isBang()==true) {
                                        show[j].setId(-1);
                                }else{
                                        if (show[j].getId()==0) {
                                                show[j].setId(-4);
                                        }
                                }
                        }
                }
                //再次遍历,根据相应对象的Id值,对其ico进行不同的修改
                for (int i = 1; i < show.length-1; i++) {
                        for (int j = 1; j < show.length-1; j++) {
                                if (show[j].getId()==-4) {
                                        show[j].setIco(" ");
                                }else if (show[j].getId()==-1) {
                                        show[j].setIco("#");
                       
                                }else {
                                        show[j].setIco(""+show[j].getId());
                                }
                        }
                }
        }



        public static void printSoSo(int[][] a){        //打印int 数组
                for (int i = 0; i < a.length; i++) {
                        for (int j = 0; j < a.length; j++) {
                                System.out.print(a[j]+"   ");
                        }
                        System.out.println();
                }
                System.out.println("------------------------------------------------");
               
        }


        public static void printSoSo(Boom[][] a){       //打印 boom数组
                for (int i = 1; i < a.length-1; i++) {
                        for (int j = 1; j < a.length-1; j++) {
                                System.out.print(a[j].getId()+"   ");
                        }
                        System.out.println();
                }
                System.out.println("------------------------------------------------");
        }
       
}
......真的被自己恶心到了...写的格式有点乱....以后要注意...不过能成功运行,还是挺开心的
扫雷.zip (9.45 KB, 下载次数: 18)






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2