Java实现的linux终端扫雷

帮忙做了一个在linux终端上运行的扫雷(不知道为啥要做这东西...
用了两个二维数组,一个表示雷图,一个表示遮盖
由于命令行无法使用方向键,所以先将命令行设置为了raw模式,并用u001b转义字符控制光标移动

2019-12-07.png

一共三个java文件
MapManage.java

import java.util.Random;

/*
 * MapManage 管理扫雷地图
 * 
 */

public class MapManage {
    private final int wi;
    private final int he;
    private int[][] newMap;
    
    /*
     * MapManage 初始化地图
     * @param wi,he 地图宽和高
     */
    
    public MapManage(int wi,int he) {
        this.wi=wi;
        this.he=he;
        newMap=new int[wi][he];
    } 
    
    /*
     * create 创建地图
     * @param num 地雷数量
     */
    
    public void create(int num) {
        Random random =new Random();
        Random random2 = new Random();
        for(int i=0;i<num;i++) {
            newMap[random.nextInt(wi)][random2.nextInt(he)]=9;
        }
        for(int i=0;i<wi;i++)
            for(int j=0;j<he;j++)
                if(newMap[i][j]!=9)
                    newMap[i][j]=mineNum(i, j);
    }
    
    /*
     * getMap 获取地图
     * @return 地图数组
     */
    
    public int[][] getMap(){
        return newMap;
    }
    
    /*
     * getNum 获取指定坐标的地图数字
     * @param x,y 指定的坐标
     * @return 返回数字
     */
    
    public  int getNum(int x,int y) {
        return newMap[x][y];
    }
    
    /*
     * mineNum 获取指定坐标周围的地雷数量
     * @param x,y 指定的坐标
     */
    
    private int mineNum(int x,int y) {
        int num=0;
        for(int i=-1;i<2;i++) 
            for(int j=-1;j<2;j++)
                num+=isMine(x+i, y+j)?1:0;
        return num;
    }
    
    /*
     * getWidth 返回宽度
     */
    
    public int getWidth() {
        return wi;
    }
    
    /*
     * getHeight 返回高度
     */
    public int getHeight() {
        return he;
    }
    
    /*
     * haveNull 返回指定坐标周围是否有空块
     */
    
    public boolean haveNull(int x,int y) {
        if(newMap[x][y]==9) return false;
        for(int i=-1;i<2;i++) 
            for(int j=-1;j<2;j++)
                if(isNull(x+i, y+j)) return true;
        return false;
    }
    
    /*
     * isMine 指定坐标是否是雷
     */
    
    public boolean isMine(int x,int y) {
        if(x>=0&&y>=0&&x<wi&&y<he&&newMap[x][y]==9) return true;
        else return false;
    }
    
    /*
     * isNull 指定坐标是否是空块
     */
    
    public boolean isNull(int x,int y) {
        if(x>=0&&y>=0&&x<wi&&y<he&&newMap[x][y]==0) return true;
        else return false;
    }

}

Calculate.java

/*
 * Calculate : 用于管理遮盖层
 * 
 */

public class Calculate {
    private int[][] newCover;
    private final int wi,he;
    MapManage manage;
    
    /*
     * Calculate : 使用MapManage初始化
     */
    
    public Calculate(MapManage manage) {
        this.manage=manage;
        this.wi=manage.getWidth();
        this.he=manage.getHeight();
        newCover=new int[wi][he];
    }
    
    /*
     * OpenOne : 打开一个坐标的方块可能发生的事件
     * @param x,y 要打开的坐标
     */
    
    public boolean OpenOne(int x,int y) {
        if(!manage.haveNull(x, y)) {
            if(manage.isMine(x, y)) {
                return false;
            }
            else {
                setOpen(x, y);
                return true;
            }
        }else {clear(x, y);
            return true;
        }
        
    }
    
    /*
     * clear : 递归打开周围的空方块
     * @param x,y 要打开的坐标
     */
    
    public void clear(int x,int y) {
        if(x>=0&&x<he&&y>=0&&y<wi&&manage.haveNull(x, y)&&newCover[x][y]!=1) {
            setOpen(x, y);
            clear(x, y+1);
            clear(x+1, y);
            clear(x, y-1);
            clear(x-1, y);
        }
    }
    
    /*
     * getCover : 获取遮盖层数组
     * @return int[][] 遮盖层数组
     */
    
    public int[][] getCover(){
        return newCover;
    }
    
    /*
     * setFlag : 在指定坐标上插旗
     * @param x,y 要插旗的坐标
     * @return true为该局游戏已经胜利,false为还未胜利
     */
    
    public boolean setFlag(int x,int y) {
        newCover[x][y]=2;
        return isSuc();
    }
    
    /*
     * setOpen : 打开指定坐标的方块
     * @param x,y 要打开的坐标
     */
    
    public void setOpen(int x,int y) {
        newCover[x][y]=1;    
        Display.open(x,y,manage.getNum(x, y));
    }
    
    /*
     * getNum : 获取给定坐标的遮盖状态
     * @return 0为被遮盖状态,1为打开状态,2为插旗状态
     */
    
    public int getNum(int x,int y) {
        return newCover[x][y];
    }
    
    /*
     * isSuc : 检验该局是否胜利
     * @return true为该局游戏已经胜利,false为还未胜利
     */
    
    private boolean isSuc() {
        for(int i=0;i<wi;i++) 
            for(int j=0;j<he;j++) 
                if(manage.isMine(i, j))
                    if(newCover[i][j]!=2)
                        return false;
        return true;
    }
}

Display.java

/*
 * Display : 用于输出游戏画面
 * 
 */

public class Display {
    private MapManage mm;
    private Calculate ca;
    private int X=0,Y=0;
    
    public Display(MapManage mm,Calculate ca) {
        this.mm=mm;
        this.ca=ca;
    }
    
    /*
     * printMap:输出完整的游戏界面
     * @param wiSize 扫雷地图宽度
     *           heSize 扫雷地图高度
     */
    public static void printMap(int wiSize,int heSize) {
        System.out.print("\u001b[0m");
        printHead(wiSize);
        System.out.print("╔");
        for(int i=0;i<wiSize*2;i++) {
            System.out.print("═");
        }
        System.out.print("╗");
        System.out.print("\u001b[1000D");
        System.out.println();
        for(int i=0;i<wiSize;i++) {
            System.out.print("║");
            System.out.print("\u001b[47;1m");
            for(int j=0;j<heSize;j++) {
                System.out.print("▀");
                System.out.print(" ");
                
            }
            System.out.print("\u001b[0m");
            System.out.print("║");
            System.out.println();
            System.out.print("\u001b[1000D");
        }
        System.out.print("╚");
        for(int i=0;i<wiSize*2;i++) {
            System.out.print("═");
        }
        System.out.print("╝");
        printFoot(wiSize, heSize);
    }
    
    /*
     * printHead : 输出扫雷头部提醒栏
     * @param  wiSize 扫雷地图宽度
     */
    
    private static void printHead(int wiSize) {
        for(int i=0;i<wiSize-3;i++) System.out.print(" ");
        System.out.println("♪(*^∇^)");
        System.out.print("\u001b[1000D");
    }
    
    /*
     * printFoot : 输出扫雷尾部提醒栏
     * @param  wiSize 扫雷地图宽度
     *            heSize 扫雷地图高度
     */
    
    private static void printFoot(int wiSize,int heSize) { 
        System.out.println();
        System.out.print("\u001b[1000D");
        System.out.println("难度:"+wiSize+"*"+heSize);
        System.out.print("\u001b[1000D");
        System.out.println("说明:  方向键移动,回车键插旗,空格键开块");
        System.out.print("\u001b[1000D");
        
    }
    
    /*
     * resetPos : 用于第一次输出后,设置X,Y初始坐标,并将光标移至左上角
     * @param x 初始坐标水平位置
     *           y 初始坐标垂直位置
     */
    
    public void resetPos(int x,int y) {
        X=x;Y=y;
        ToZero();
        //ToPos(1, 1);
    }
     
    /*
     * ToZero : 用于第一次输出后,将光标移动到左上角
     */
    
    private void ToZero() {
        System.out.print("\u001b[1000D");
        System.out.print("\u001b["+(3+mm.getHeight())+"A");
        System.out.print("\u001b[1C");
        
        System.out.print("\u001b[44;1m");
        System.out.print("▀ ");
        System.out.print("\u001b[0m");
        System.out.print("\u001b[2A");
        System.out.print("\u001b[3D");
        System.out.print("\u001b[s");
    }
    
    /*
     * ToPos : 用于将光标用左上角移动到X,Y坐标处
     */
    
    private void ToPos() {
        System.out.print("\u001b[1000D");
        System.out.print("\u001b["+(Y+2)+"B");
        System.out.print("\u001b["+(X*2+1)+"C");
    }
    
    /*
     * ToPos : 用于将光标移动到给定的x,y坐标处
     * @param x 给定要移动到的x坐标
     *           y 给定要移动到的y坐标
     */
    
    private static void ToPos(int x,int y) {
        System.out.print("\u001b[1000D");
        System.out.print("\u001b["+(y+2)+"B");
        System.out.print("\u001b["+(x*2+1)+"C");
    }
    
    /*
     * back : 坐标回到左上角
     */
    
    private static void back() {
        System.out.print("\u001b[u");
    }
    
    /*
     * MoveR : 坐标向左或者右移动
     * @param : r true为向右,false为向左
     */
    
    public void MoveR(boolean r) {
        ToPos();
        ClearPos();
        if(r) {
            X++;
            PrintPos();
        }else {
            X--;
            System.out.print("\u001b[4D");
            PrintPos();
        }
        back();
    }
    
    /*
     * MoveT : 坐标向上或者下移动
     * @param : t true为向下,false为向上
     */
    
    public void MoveT(boolean t) {
        ToPos();
        ClearPos();
        if(t) {
            Y++;
            System.out.print("\u001b[2D");
            System.out.print("\u001b[1B");
            PrintPos();
        }else {
            Y--;
            System.out.print("\u001b[2D");
            System.out.print("\u001b[1A");
            PrintPos();
        }
        back();
    }
    
    /*
     * ClearPos : 清除坐标的选中状态
     */
    
    private void ClearPos() {
        switch (ca.getNum(X, Y)) {
        case 2:
            System.out.print("\u001b[2C");
            break;
        case 1:
            System.out.print(mm.getNum(X, Y)+" ");
            break;

        default:
            System.out.print("\u001b[47;1m");
            System.out.print("▀ ");
            System.out.print("\u001b[0m");
        }
    }
    
    /*
     * PrintPos : 将坐标设为选中状态
     */
    
    private void PrintPos() {
        switch (ca.getNum(X, Y)) {
        case 2:
            System.out.print("\u001b[2C");
            break;
        case 1:
            System.out.print("\u001b[44;1m");
            System.out.print(mm.getNum(X, Y)+" ");
            System.out.print("\u001b[0m");
            break;
        default:
            System.out.print("\u001b[44;1m");
            System.out.print("▀ ");
            System.out.print("\u001b[0m");
        }
    }
    
    /*
     * RefreshPos : 刷新坐标的选中状态
     */
    
    public void RefreshPos() {
        ToPos();
        PrintPos();
        back();
    }
    
    /*
     * open : 将一个坐标设为打开的状态
     * @param x 要打开的坐标x
     *           y 要打开的坐标y
     *           num 打开后显示的数字
     */
    
    public static void open(int x,int y,int num) {
        ToPos(x, y);
        System.out.print(num+" ");
        back();
        
    }
    
    /*
     * AddFlag : 在现在的光标位置插旗
     */
    
    public void AddFlag() {
        ToPos();
        System.out.print("\u001b[42m");
        System.out.print("▼ ");
        System.out.print("\u001b[0m");
        back();
    }
    
    /*
     * Failed : 显示失败提示
     */
    
    public void Failed() {
        System.out.print("\u001b[41m");
        System.out.print(" o(TヘTo) 炸了唉~ ");
        System.out.print("\u001b[0m");
    }
    
    /*
     * Succeed : 显示成功提示
     */
    
    public void Succeed() {
        System.out.print("\u001b[42m");
        System.out.print(" ヽ(✿゚▽゚)ノ     我好了! ");
        System.out.print("\u001b[0m");
    }
    
    /*
     * End : 将光标移动到最底部
     */
    
    public void End() {
        back();
        System.out.print("\u001b["+(5+mm.getHeight())+"B");
    }
}
Muyoo

Muyoo

留下你的评论