在五子棋遊戲或類似的遊戲中,我們可以把整個棋盤想象成是一個有規律的二維陣列,其值由0、1、2三個數位組成,0代表空白區域,1代表白子,2代表黑子。這種情況:即當一個陣列中大部分元素為0或者為同一值時,儲存該陣列資料可以使用稀疏陣列來對原始陣列進行精簡,以減少原始陣列中無用資料所佔的空間。
下圖表示的是一個12×12大小的二維陣列與之對應的稀疏陣列表示,其中普通二維陣列中有11個有效值,其餘的全為無用資料0填充。稀疏陣列的第一行表示有一個12行12列且11個有效數值的二維陣列。第二行表示,二維陣列中的第2行(從0開始)、第4列的數值為1。從第二行開始,每一行表示的都是二維陣列中數值的行列位置和真實值。
private int[][] generatorArray() {
// 初始化二維陣列
int[][] arr = new int[12][12];
// 二維陣列賦值
arr[2][4] = 1;
arr[2][5] = 1;
arr[3][4] = 1;
arr[3][5] = 1;
arr[3][6] = 2;
arr[3][7] = 2;
arr[4][5] = 2;
arr[4][6] = 1;
arr[5][5] = 1;
arr[5][6] = 2;
arr[5][7] = 2;
System.out.println("原始二維陣列為:");
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + "\t");
}
System.out.println();
}
System.out.println();
return arr;
}
執行結果:
原始二維陣列為:
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0 0 0
0 0 0 0 1 1 2 2 0 0 0 0
0 0 0 0 0 2 1 0 0 0 0 0
0 0 0 0 0 1 2 2 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
private int[][] toSparseArray(int[][] originalArray) {
// 獲得原始陣列行列、有效值初始化稀疏陣列
int sum = 0;
for (int i = 0; i < originalArray.length; i++) {
for (int j = 0; j < originalArray[i].length; j++) {
if (originalArray[i][j] != 0) {
sum += 1;
}
}
}
// 稀疏陣列length為有效值個數+1
int[][] sparseArray = new int[sum+1][3];
// 行
sparseArray[0][0] = originalArray.length;
// 列
sparseArray[0][1] = originalArray[0].length;
// 有效值個數
sparseArray[0][2] = sum;
// 賦值
int count = 0;
for (int i = 0; i < originalArray.length; i++) {
for (int j = 0; j < originalArray[i].length; j++) {
if (originalArray[i][j] != 0) {
count++;
sparseArray[count][0] = i;
sparseArray[count][1] = j;
sparseArray[count][2] = originalArray[i][j];
}
}
}
// 輸出稀疏陣列
System.out.println("轉換後的稀疏陣列為:");
for (int i = 0; i < sparseArray.length; i++) {
for (int j = 0; j < sparseArray[i].length; j++) {
System.out.print(sparseArray[i][j] + "\t");
}
System.out.println();
}
System.out.println();
return sparseArray;
}
執行結果:
轉換後的稀疏陣列為:
12 12 11
2 4 1
2 5 1
3 4 1
3 5 1
3 6 2
3 7 2
4 5 2
4 6 1
5 5 1
5 6 2
5 7 2
private int[][] toOriginalArray(int[][] sparseArray) {
// 初始化原始陣列
int[][] originalArray = new int[sparseArray[0][0]][sparseArray[0][1]];
// 從第二個值開始,因為第一個值存的是原始陣列的行列、有效值個數等資訊
for (int i = 1; i < sparseArray.length; i++) {
// 由稀疏陣列給原始陣列賦值
originalArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
}
System.out.println("轉換後的二維陣列為:");
for (int i = 0; i < originalArray.length; i++) {
for (int j = 0; j < originalArray[i].length; j++) {
System.out.print(originalArray[i][j] + "\t");
}
System.out.println();
}
return originalArray;
}
在真實開發中,一般是將稀疏陣列資料在資料庫或者檔案中進行儲存,這裡我使用 fastjson2 將稀疏陣列轉換成 JSON 字串之後儲存到電腦本地(二維陣列轉稀疏陣列),再從本地讀取檔案內容進行解析(稀疏陣列轉二維陣列)。儲存到資料庫也是同理的操作。
/**
* 將JSON字串儲存為檔案
* @param jsonString 轉換後的稀疏陣列JSON字串
* @param fileName 電腦本地檔案
*/
private void toFile(String jsonString, String fileName) {
File file = new File(fileName);
FileWriter fileWriter = null;
if (!file.exists()) {
try {
file.createNewFile();
fileWriter = new FileWriter(file);
char[] chars = jsonString.toCharArray();
fileWriter.write(chars);
fileWriter.flush();
} catch (IOException ioException) {
ioException.printStackTrace();
} finally {
try {
fileWriter.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
/**
* 從檔案讀取內容
* @param fileName
* @return
* @throws IOException
*/
private String readFile(String fileName) throws IOException {
File file = new File(fileName);
FileReader reader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(reader);
String line = null;
System.out.println("檔案讀取內容為:");
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
System.out.println();
return line;
}
reader.close();
bufferedReader.close();
return line;
}
/**
* 由JSON字串轉換成原始二維陣列
* @param jsonString
* @return
*/
private int[][] stringToOriginArray(String jsonString) {
JSONArray objects = JSON.parseArray(jsonString);
JSONArray s = (JSONArray) objects.get(0);
// 初始化原始陣列
int[][] originalArray = new int[(int)s.get(0)][(int)s.get(1)];
// 從第二個值開始,因為第一個值存的是原始陣列的行列、有效值個數等資訊
for (int i = 1; i < objects.size(); i++) {
JSONArray se = (JSONArray) objects.get(i);
originalArray[(int)se.get(0)][(int)se.get(1)] = (int)se.get(2);
}
System.out.println("JSON字串轉換為二維陣列:");
for (int i = 0; i < originalArray.length; i++) {
for (int j = 0; j < originalArray[i].length; j++) {
System.out.print(originalArray[i][j] + "\t");
}
System.out.println();
}
return originalArray;
}