五子棋与稀疏数组

简介: 五子棋与稀疏数组

前言

稀疏数组是我们一开始学数据结构的时候第一次有点味道的小算法了,大部分的人第一次是交代在这里。这是因为,这个需求来自于我们比较喜欢的五子棋小游戏。这个游戏主要是当年有个东西叫做电子词典,也不知道是啥规则,清一色都有这个游戏。

稀疏数组在应用在五子棋上面的一个原因是,落子不多的话格子是很少,但是我们定义全局的时候其实是一个二维数组

说正事

棋盘中的代码其实是一个数组,但是里面会附带很多0元素,这样子保存起来其实是很划不来的,我们要实现的就是按照压缩策略去进行存储。

首先我们的数组长这个样子:

  |0| |1| |2| |3| |4| |5| |6| |7| |8| 
|0|  0   0   0   0   0   1   1   0   0  
|1|  0   0   0   0   0   0   0   0   0  
|2|  0   0   0   0   0   0   0   0   0  
|3|  0   0   0   0   0   0   0   0   0  
|4|  0   0   0   0   0   0   0   0   0  
|5|  0   0   0   0   0   0   0   0   0  
|6|  0   0   0   0   0   0   0   2   2  
|7|  0   0   0   0   0   0   0   0   0  
|8|  0   0   0   0   0   0   0   0   0  

我们的有效数据其实只有4个,我们定义稀疏数组的规则如下:

1.首行保存数组多少行多少列

2.剩下的行按照行号+列号+原数值来保存

具体的保存效果如下:

  [9][9][4] 首行表示原数组有多少行多少列
  [0][5][1] 剩下的行数存储信息为行号|列号|原数值
  [6][7][2]
  [6][8][1]

一旦这样子去做,我们的数组一下子就减少很多,至少肉眼看过去盘面也小很多。

稀疏数组生成

稀疏数组的转换,核心部分我加了详细注释

 public void sparseArr(){
        int count=0; 
        //因为需要知道稀疏数组的大小,除了首行之外我们需要有多少个有效的元素
        for(int i = 0; i< chessArry.length; i++){
            for (int j = 0; j < chessArry[i].length; j++) {
                if(chessArry[i][j]!=0){
                    count++;
                }
            }
        }
        //0行用来保存原数组的大小信息
        sparseArray=new int[count+1][3];
        //首行赋值
        sparseArray[0][0]=chessArrySize;
        sparseArray[0][1]=chessArrySize;
        sparseArray[0][2]=count;
        //保存有效元素按照 行号|列号|值的格式去存储
        int offset=1;
        for (int i = 0; i < chessArry.length; i++) {
            for (int  j = 0; j < chessArry[i].length; j++) {
                if(chessArry[i][j]!=0){
                   sparseArray[offset][0]=i;
                   sparseArray[offset][1]=j;
                   sparseArray[offset][2]=chessArry[i][j];
                    offset++;
                }
            }
        }
    }

稀疏数组存盘与恢复

存盘操作就是一个写文件操作,但是文件需要我们约定一下格式,以便读取的时候按照格式恢复,我这边直接用竖线分割就好了。

  public void storeChess(){
        if(sparseArray==null){
            sparseArr();
        }
        //把稀疏数组保存到磁盘
        File file=new File(storePath);
        PrintWriter printWriter=null;
        try {
             printWriter=new PrintWriter(new FileOutputStream(file));
            for (int i = 0; i < sparseArray.length; i++) {
                for (int j = 0; j < sparseArray[i].length; j++) {
                    printWriter.print(sparseArray[i][j]+"|");
                }
                printWriter.println();
            }
            System.out.printf("sparse data save to %s successful!\n",storePath);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally {
            if(printWriter!=null){
                printWriter.close();
            }
        }
    }

数据恢复

数据恢复包含两个方面,一个是从磁盘读取,另外是我们需要恢复成正常的数组,这个是数据解压的操作。

  public void restoreChess(){
        if(chessArry!=null){
            clearChess();
        }
        System.out.println("准备恢复棋盘...");
        //从文件中恢复数据
        File file=new File(storePath);
        try {
            BufferedReader br=new BufferedReader(new FileReader(file));
            String firstLine= br.readLine();//首行记录了棋盘的信息
            String[] headSplits= firstLine.split("\\|");
            int lineSize=Integer.valueOf(headSplits[0]);
            int cloumnSize=Integer.valueOf(headSplits[1]);
            int elCount=Integer.valueOf(headSplits[2]);
            System.out.printf("棋盘行数:%d,棋盘列数%d,有效元素个数%d\n",lineSize,cloumnSize,elCount);
            chessArry=new int[lineSize][cloumnSize];
            for(int i=1;i<elCount+1;i++){ //第一行开始才有元素
                String line= br.readLine();//数组信息
                String[] lineSplit= line.split("\\|");
                int xIndex=Integer.valueOf(lineSplit[0]);
                int yIndex=Integer.valueOf(lineSplit[1]);
                int value=Integer.valueOf(lineSplit[2]);
                chessArry[xIndex][yIndex]=value;
            }
            System.out.println("恢复棋盘完成...");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

整个连起来跑一通

略去原数组

压缩后的数组
9 9 4 
0 5 1 
0 6 1 
6 7 2 
6 8 2 
准备恢复棋盘...
棋盘行数:9,棋盘列数9,有效元素个数4
恢复棋盘完成...
  |0| |1| |2| |3| |4| |5| |6| |7| |8| 
|0|  0   0   0   0   0   1   1   0   0  
|1|  0   0   0   0   0   0   0   0   0  
|2|  0   0   0   0   0   0   0   0   0  
|3|  0   0   0   0   0   0   0   0   0  
|4|  0   0   0   0   0   0   0   0   0  
|5|  0   0   0   0   0   0   0   0   0  
|6|  0   0   0   0   0   0   0   2   2  
|7|  0   0   0   0   0   0   0   0   0  
|8|  0   0   0   0   0   0   0   0   0  

后记

博客上面展示代码其实比较长,但是还没想到好点的办法,最后附上源码:

稀疏数组源码

目录
相关文章
|
7月前
【每日一题Day146】给定行和列的和求可行矩阵 | 贪心
【每日一题Day146】给定行和列的和求可行矩阵 | 贪心
52 0
|
7月前
|
存储 机器学习/深度学习 算法
【算法训练-数组 三】【数组矩阵】螺旋矩阵、旋转图像、搜索二维矩阵
【算法训练-数组 三】【数组矩阵】螺旋矩阵、旋转图像、搜索二维矩阵
94 0
|
7月前
|
算法 Java Go
Rust每日一练(Leetday0025) 矩阵置零、搜索二维矩阵、颜色分类
Rust每日一练(Leetday0025) 矩阵置零、搜索二维矩阵、颜色分类
72 0
Rust每日一练(Leetday0025) 矩阵置零、搜索二维矩阵、颜色分类
|
算法
精选算法题(2)——矩阵螺旋输出
精选算法题(2)——矩阵螺旋输出
|
存储 算法 Java
Java数据结构与算法分析(二)稀疏数组
在介绍稀疏数组前我们先来引入一个需求,下面是一个五子棋的棋盘(15 * 15),玩到中途时想要保存离开,希望下次打开还可以继续玩。我们怎么实现呢?
81 0
|
算法 大数据 Python
Leedcode 每日一练 搜索二维矩阵Ⅰ Python实现
Leedcode 每日一练 搜索二维矩阵Ⅰ Python实现
158 2
Leedcode 每日一练 搜索二维矩阵Ⅰ Python实现
|
Java
通过五子棋案例,实现稀疏数组与二维数组直接互相转换。
通过五子棋案例,实现稀疏数组与二维数组直接互相转换。
105 0
通过五子棋案例,实现稀疏数组与二维数组直接互相转换。
|
算法 前端开发
日拱算法:搜索二维矩阵 II
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性: 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。
|
存储 算法 Java
【算法】1470. 重新排列数组,细节满满一道题
【算法】1470. 重新排列数组,细节满满一道题
95 0
【算法】1470. 重新排列数组,细节满满一道题
|
算法 C++
【基础算法训练】—— 一维前缀和
【基础算法训练】—— 一维前缀和
151 0
【基础算法训练】—— 一维前缀和