文 | Java聖鬥士
文 | Java聖鬥士
Hello 各位熱愛學習的小夥伴們大家好,今天來給大家聊聊五子棋遊戲的後臺實現。
相信大家都玩過五子棋遊戲,規則就是率先連成 5 顆棋子的一方獲勝。小編小的時候也非常喜歡玩五子棋,覺得自己天下無敵了,對手再怎麼努力都不會逃脫自己的圍追堵截,堵著堵著就贏了,哈哈。
文 | Java聖鬥士
Hello 各位熱愛學習的小夥伴們大家好,今天來給大家聊聊五子棋遊戲的後臺實現。
相信大家都玩過五子棋遊戲,規則就是率先連成 5 顆棋子的一方獲勝。小編小的時候也非常喜歡玩五子棋,覺得自己天下無敵了,對手再怎麼努力都不會逃脫自己的圍追堵截,堵著堵著就贏了,哈哈。
可是你有想過五子棋的“保存棋局”和“續上局”是如何實現的嗎?
五子棋的數據結構描述
我們知道,五子棋有一個正方形棋盤,分別設有白子和黑子:
文 | Java聖鬥士
Hello 各位熱愛學習的小夥伴們大家好,今天來給大家聊聊五子棋遊戲的後臺實現。
相信大家都玩過五子棋遊戲,規則就是率先連成 5 顆棋子的一方獲勝。小編小的時候也非常喜歡玩五子棋,覺得自己天下無敵了,對手再怎麼努力都不會逃脫自己的圍追堵截,堵著堵著就贏了,哈哈。
可是你有想過五子棋的“保存棋局”和“續上局”是如何實現的嗎?
五子棋的數據結構描述
我們知道,五子棋有一個正方形棋盤,分別設有白子和黑子:
那麼這個五子棋盤就可以使用二維數組來描述,假設是一個 11 × 11 的二維數組:
int[][] chessArr = new int[11][11];
然後我們輸出一下:
for (int[] row : chessArr) {
\tfor (int data : row) {
\t\tSystem.out.printf("%d ", data);
\t}
\tSystem.out.println();
}
文 | Java聖鬥士
Hello 各位熱愛學習的小夥伴們大家好,今天來給大家聊聊五子棋遊戲的後臺實現。
相信大家都玩過五子棋遊戲,規則就是率先連成 5 顆棋子的一方獲勝。小編小的時候也非常喜歡玩五子棋,覺得自己天下無敵了,對手再怎麼努力都不會逃脫自己的圍追堵截,堵著堵著就贏了,哈哈。
可是你有想過五子棋的“保存棋局”和“續上局”是如何實現的嗎?
五子棋的數據結構描述
我們知道,五子棋有一個正方形棋盤,分別設有白子和黑子:
那麼這個五子棋盤就可以使用二維數組來描述,假設是一個 11 × 11 的二維數組:
int[][] chessArr = new int[11][11];
然後我們輸出一下:
for (int[] row : chessArr) {
\tfor (int data : row) {
\t\tSystem.out.printf("%d ", data);
\t}
\tSystem.out.println();
}
然後我們先來填幾顆棋子,模擬一個五子棋局,在代碼中,由於初始的二維數組中默認都是 0 ,那我們就可以考慮用 1 代表 黑子,用 2 代表白子:
chessArr[1][2] = 1; // 黑子先行
chessArr[2][3] = 2; // 白子緊隨其後
chessArr[1][4] = 1; // 黑子欲形成橫向三連之勢
chessArr[1][3] = 2; // 白子“挺進大別山”斷了黑子的陰謀
再輸出,就可以看到黑子白子形成的“圍追堵截”之勢了,有沒有點懷念小時候的感覺?
文 | Java聖鬥士
Hello 各位熱愛學習的小夥伴們大家好,今天來給大家聊聊五子棋遊戲的後臺實現。
相信大家都玩過五子棋遊戲,規則就是率先連成 5 顆棋子的一方獲勝。小編小的時候也非常喜歡玩五子棋,覺得自己天下無敵了,對手再怎麼努力都不會逃脫自己的圍追堵截,堵著堵著就贏了,哈哈。
可是你有想過五子棋的“保存棋局”和“續上局”是如何實現的嗎?
五子棋的數據結構描述
我們知道,五子棋有一個正方形棋盤,分別設有白子和黑子:
那麼這個五子棋盤就可以使用二維數組來描述,假設是一個 11 × 11 的二維數組:
int[][] chessArr = new int[11][11];
然後我們輸出一下:
for (int[] row : chessArr) {
\tfor (int data : row) {
\t\tSystem.out.printf("%d ", data);
\t}
\tSystem.out.println();
}
然後我們先來填幾顆棋子,模擬一個五子棋局,在代碼中,由於初始的二維數組中默認都是 0 ,那我們就可以考慮用 1 代表 黑子,用 2 代表白子:
chessArr[1][2] = 1; // 黑子先行
chessArr[2][3] = 2; // 白子緊隨其後
chessArr[1][4] = 1; // 黑子欲形成橫向三連之勢
chessArr[1][3] = 2; // 白子“挺進大別山”斷了黑子的陰謀
再輸出,就可以看到黑子白子形成的“圍追堵截”之勢了,有沒有點懷念小時候的感覺?
棋盤的壓縮保存
接下來就是今天的正題!如果你已經看到這裡,一定要堅持!
五子棋的保存實際上並不是保存整個棋盤,而是通過一個叫做“稀疏數組”的結構來完成的。
稀疏數組,顧名思義是一個很稀疏的數組......
文 | Java聖鬥士
Hello 各位熱愛學習的小夥伴們大家好,今天來給大家聊聊五子棋遊戲的後臺實現。
相信大家都玩過五子棋遊戲,規則就是率先連成 5 顆棋子的一方獲勝。小編小的時候也非常喜歡玩五子棋,覺得自己天下無敵了,對手再怎麼努力都不會逃脫自己的圍追堵截,堵著堵著就贏了,哈哈。
可是你有想過五子棋的“保存棋局”和“續上局”是如何實現的嗎?
五子棋的數據結構描述
我們知道,五子棋有一個正方形棋盤,分別設有白子和黑子:
那麼這個五子棋盤就可以使用二維數組來描述,假設是一個 11 × 11 的二維數組:
int[][] chessArr = new int[11][11];
然後我們輸出一下:
for (int[] row : chessArr) {
\tfor (int data : row) {
\t\tSystem.out.printf("%d ", data);
\t}
\tSystem.out.println();
}
然後我們先來填幾顆棋子,模擬一個五子棋局,在代碼中,由於初始的二維數組中默認都是 0 ,那我們就可以考慮用 1 代表 黑子,用 2 代表白子:
chessArr[1][2] = 1; // 黑子先行
chessArr[2][3] = 2; // 白子緊隨其後
chessArr[1][4] = 1; // 黑子欲形成橫向三連之勢
chessArr[1][3] = 2; // 白子“挺進大別山”斷了黑子的陰謀
再輸出,就可以看到黑子白子形成的“圍追堵截”之勢了,有沒有點懷念小時候的感覺?
棋盤的壓縮保存
接下來就是今天的正題!如果你已經看到這裡,一定要堅持!
五子棋的保存實際上並不是保存整個棋盤,而是通過一個叫做“稀疏數組”的結構來完成的。
稀疏數組,顧名思義是一個很稀疏的數組......
咳咳,稀疏數組實際上是一個只保存原始二維數組有效數據,去掉無效數據的一個二維數組。
當一個數組中大部分元素是0,或為同一個值的時候,可以使用稀疏數組來保存數組。它是一個十分有效的壓縮存儲結構,而且還不涉及任何複雜的算法,簡單又實用!!
文 | Java聖鬥士
Hello 各位熱愛學習的小夥伴們大家好,今天來給大家聊聊五子棋遊戲的後臺實現。
相信大家都玩過五子棋遊戲,規則就是率先連成 5 顆棋子的一方獲勝。小編小的時候也非常喜歡玩五子棋,覺得自己天下無敵了,對手再怎麼努力都不會逃脫自己的圍追堵截,堵著堵著就贏了,哈哈。
可是你有想過五子棋的“保存棋局”和“續上局”是如何實現的嗎?
五子棋的數據結構描述
我們知道,五子棋有一個正方形棋盤,分別設有白子和黑子:
那麼這個五子棋盤就可以使用二維數組來描述,假設是一個 11 × 11 的二維數組:
int[][] chessArr = new int[11][11];
然後我們輸出一下:
for (int[] row : chessArr) {
\tfor (int data : row) {
\t\tSystem.out.printf("%d ", data);
\t}
\tSystem.out.println();
}
然後我們先來填幾顆棋子,模擬一個五子棋局,在代碼中,由於初始的二維數組中默認都是 0 ,那我們就可以考慮用 1 代表 黑子,用 2 代表白子:
chessArr[1][2] = 1; // 黑子先行
chessArr[2][3] = 2; // 白子緊隨其後
chessArr[1][4] = 1; // 黑子欲形成橫向三連之勢
chessArr[1][3] = 2; // 白子“挺進大別山”斷了黑子的陰謀
再輸出,就可以看到黑子白子形成的“圍追堵截”之勢了,有沒有點懷念小時候的感覺?
棋盤的壓縮保存
接下來就是今天的正題!如果你已經看到這裡,一定要堅持!
五子棋的保存實際上並不是保存整個棋盤,而是通過一個叫做“稀疏數組”的結構來完成的。
稀疏數組,顧名思義是一個很稀疏的數組......
咳咳,稀疏數組實際上是一個只保存原始二維數組有效數據,去掉無效數據的一個二維數組。
當一個數組中大部分元素是0,或為同一個值的時候,可以使用稀疏數組來保存數組。它是一個十分有效的壓縮存儲結構,而且還不涉及任何複雜的算法,簡單又實用!!
它的處理方式是:
1、記錄數組一共有幾行幾列,有多少有效值;
2、把具有有效值的元素的行、列及值記錄在一個小規模二維數組中(稀疏數組),從而降低存儲數據的規模。
如果一個二維數組長這樣:
文 | Java聖鬥士
Hello 各位熱愛學習的小夥伴們大家好,今天來給大家聊聊五子棋遊戲的後臺實現。
相信大家都玩過五子棋遊戲,規則就是率先連成 5 顆棋子的一方獲勝。小編小的時候也非常喜歡玩五子棋,覺得自己天下無敵了,對手再怎麼努力都不會逃脫自己的圍追堵截,堵著堵著就贏了,哈哈。
可是你有想過五子棋的“保存棋局”和“續上局”是如何實現的嗎?
五子棋的數據結構描述
我們知道,五子棋有一個正方形棋盤,分別設有白子和黑子:
那麼這個五子棋盤就可以使用二維數組來描述,假設是一個 11 × 11 的二維數組:
int[][] chessArr = new int[11][11];
然後我們輸出一下:
for (int[] row : chessArr) {
\tfor (int data : row) {
\t\tSystem.out.printf("%d ", data);
\t}
\tSystem.out.println();
}
然後我們先來填幾顆棋子,模擬一個五子棋局,在代碼中,由於初始的二維數組中默認都是 0 ,那我們就可以考慮用 1 代表 黑子,用 2 代表白子:
chessArr[1][2] = 1; // 黑子先行
chessArr[2][3] = 2; // 白子緊隨其後
chessArr[1][4] = 1; // 黑子欲形成橫向三連之勢
chessArr[1][3] = 2; // 白子“挺進大別山”斷了黑子的陰謀
再輸出,就可以看到黑子白子形成的“圍追堵截”之勢了,有沒有點懷念小時候的感覺?
棋盤的壓縮保存
接下來就是今天的正題!如果你已經看到這裡,一定要堅持!
五子棋的保存實際上並不是保存整個棋盤,而是通過一個叫做“稀疏數組”的結構來完成的。
稀疏數組,顧名思義是一個很稀疏的數組......
咳咳,稀疏數組實際上是一個只保存原始二維數組有效數據,去掉無效數據的一個二維數組。
當一個數組中大部分元素是0,或為同一個值的時候,可以使用稀疏數組來保存數組。它是一個十分有效的壓縮存儲結構,而且還不涉及任何複雜的算法,簡單又實用!!
它的處理方式是:
1、記錄數組一共有幾行幾列,有多少有效值;
2、把具有有效值的元素的行、列及值記錄在一個小規模二維數組中(稀疏數組),從而降低存儲數據的規模。
如果一個二維數組長這樣:
那麼用於保存它的稀疏數組就可以是這樣:
文 | Java聖鬥士
Hello 各位熱愛學習的小夥伴們大家好,今天來給大家聊聊五子棋遊戲的後臺實現。
相信大家都玩過五子棋遊戲,規則就是率先連成 5 顆棋子的一方獲勝。小編小的時候也非常喜歡玩五子棋,覺得自己天下無敵了,對手再怎麼努力都不會逃脫自己的圍追堵截,堵著堵著就贏了,哈哈。
可是你有想過五子棋的“保存棋局”和“續上局”是如何實現的嗎?
五子棋的數據結構描述
我們知道,五子棋有一個正方形棋盤,分別設有白子和黑子:
那麼這個五子棋盤就可以使用二維數組來描述,假設是一個 11 × 11 的二維數組:
int[][] chessArr = new int[11][11];
然後我們輸出一下:
for (int[] row : chessArr) {
\tfor (int data : row) {
\t\tSystem.out.printf("%d ", data);
\t}
\tSystem.out.println();
}
然後我們先來填幾顆棋子,模擬一個五子棋局,在代碼中,由於初始的二維數組中默認都是 0 ,那我們就可以考慮用 1 代表 黑子,用 2 代表白子:
chessArr[1][2] = 1; // 黑子先行
chessArr[2][3] = 2; // 白子緊隨其後
chessArr[1][4] = 1; // 黑子欲形成橫向三連之勢
chessArr[1][3] = 2; // 白子“挺進大別山”斷了黑子的陰謀
再輸出,就可以看到黑子白子形成的“圍追堵截”之勢了,有沒有點懷念小時候的感覺?
棋盤的壓縮保存
接下來就是今天的正題!如果你已經看到這裡,一定要堅持!
五子棋的保存實際上並不是保存整個棋盤,而是通過一個叫做“稀疏數組”的結構來完成的。
稀疏數組,顧名思義是一個很稀疏的數組......
咳咳,稀疏數組實際上是一個只保存原始二維數組有效數據,去掉無效數據的一個二維數組。
當一個數組中大部分元素是0,或為同一個值的時候,可以使用稀疏數組來保存數組。它是一個十分有效的壓縮存儲結構,而且還不涉及任何複雜的算法,簡單又實用!!
它的處理方式是:
1、記錄數組一共有幾行幾列,有多少有效值;
2、把具有有效值的元素的行、列及值記錄在一個小規模二維數組中(稀疏數組),從而降低存儲數據的規模。
如果一個二維數組長這樣:
那麼用於保存它的稀疏數組就可以是這樣:
如上圖所示:稀疏數組有固定的三列,分別代表原始二維數組的行、列和值,但是第一行具有特殊的含義:稀疏數組的第一行存儲原始數組的行數、列數和有效數據個數,這三個信息。而從第二行(也就是[1]行)開始,才是真正的原始二維數組的有效數據。
是不是非常簡單?
稀疏數組保存五子棋的代碼實現
分析完了稀疏數組的數據結構,那麼我們就來通過代碼實現上面五子棋局的保存。
剛才的五子棋局是這樣的:
文 | Java聖鬥士
Hello 各位熱愛學習的小夥伴們大家好,今天來給大家聊聊五子棋遊戲的後臺實現。
相信大家都玩過五子棋遊戲,規則就是率先連成 5 顆棋子的一方獲勝。小編小的時候也非常喜歡玩五子棋,覺得自己天下無敵了,對手再怎麼努力都不會逃脫自己的圍追堵截,堵著堵著就贏了,哈哈。
可是你有想過五子棋的“保存棋局”和“續上局”是如何實現的嗎?
五子棋的數據結構描述
我們知道,五子棋有一個正方形棋盤,分別設有白子和黑子:
那麼這個五子棋盤就可以使用二維數組來描述,假設是一個 11 × 11 的二維數組:
int[][] chessArr = new int[11][11];
然後我們輸出一下:
for (int[] row : chessArr) {
\tfor (int data : row) {
\t\tSystem.out.printf("%d ", data);
\t}
\tSystem.out.println();
}
然後我們先來填幾顆棋子,模擬一個五子棋局,在代碼中,由於初始的二維數組中默認都是 0 ,那我們就可以考慮用 1 代表 黑子,用 2 代表白子:
chessArr[1][2] = 1; // 黑子先行
chessArr[2][3] = 2; // 白子緊隨其後
chessArr[1][4] = 1; // 黑子欲形成橫向三連之勢
chessArr[1][3] = 2; // 白子“挺進大別山”斷了黑子的陰謀
再輸出,就可以看到黑子白子形成的“圍追堵截”之勢了,有沒有點懷念小時候的感覺?
棋盤的壓縮保存
接下來就是今天的正題!如果你已經看到這裡,一定要堅持!
五子棋的保存實際上並不是保存整個棋盤,而是通過一個叫做“稀疏數組”的結構來完成的。
稀疏數組,顧名思義是一個很稀疏的數組......
咳咳,稀疏數組實際上是一個只保存原始二維數組有效數據,去掉無效數據的一個二維數組。
當一個數組中大部分元素是0,或為同一個值的時候,可以使用稀疏數組來保存數組。它是一個十分有效的壓縮存儲結構,而且還不涉及任何複雜的算法,簡單又實用!!
它的處理方式是:
1、記錄數組一共有幾行幾列,有多少有效值;
2、把具有有效值的元素的行、列及值記錄在一個小規模二維數組中(稀疏數組),從而降低存儲數據的規模。
如果一個二維數組長這樣:
那麼用於保存它的稀疏數組就可以是這樣:
如上圖所示:稀疏數組有固定的三列,分別代表原始二維數組的行、列和值,但是第一行具有特殊的含義:稀疏數組的第一行存儲原始數組的行數、列數和有效數據個數,這三個信息。而從第二行(也就是[1]行)開始,才是真正的原始二維數組的有效數據。
是不是非常簡單?
稀疏數組保存五子棋的代碼實現
分析完了稀疏數組的數據結構,那麼我們就來通過代碼實現上面五子棋局的保存。
剛才的五子棋局是這樣的:
那麼如何生成對應的稀疏數組呢?當然是先循環了......
首先要確定有多少個有效數據,這個是非常關鍵的:
int sum = 0;
for (int i = 0; i < chessArr.length; i++) {
\tfor (int j = 0; j < chessArr[0].length; j++) {
\t\tif (chessArr[i][j] != 0) {
\t\t\tsum++;
\t\t}
\t}
}
得到 sum 的原始二維數組有效數據有,我們就可以聲明這個稀疏數組了:
int[][] sparseArr = new int[sum + 1][3];
然後是將原始數組的 行數、列數 和 有效數據個數 放入稀疏數組的第一行:
sparseArr[0][0] = chessArr.length;
sparseArr[0][1] = chessArr[0].length;
sparseArr[0][2] = sum;
最後就是將原始數組中的非 0 數據存放到稀疏數組中
int sparseArrRow = 1;
for (int i = 0; i < chessArr.length; i++) {
\tfor (int j = 0; j < chessArr[0].length; j++) {
\t\tif (chessArr[i][j] != 0) {
\t\t\tsparseArr[sparseArrRow][0] = i;
\t\t\tsparseArr[sparseArrRow][1] = j;
\t\t\tsparseArr[sparseArrRow][2] = chessArr[i][j];
\t\t\tsparseArrRow++;
\t\t}
\t}
}
到這裡為止,就完成了對稀疏數組的創建和賦值,我們的二維數組也已經放入到了這個 “壓縮”了的二維數組——稀疏數組之中。那我們來輸出一下這個稀疏數組,看看是不是我們想要的內容:
文 | Java聖鬥士
Hello 各位熱愛學習的小夥伴們大家好,今天來給大家聊聊五子棋遊戲的後臺實現。
相信大家都玩過五子棋遊戲,規則就是率先連成 5 顆棋子的一方獲勝。小編小的時候也非常喜歡玩五子棋,覺得自己天下無敵了,對手再怎麼努力都不會逃脫自己的圍追堵截,堵著堵著就贏了,哈哈。
可是你有想過五子棋的“保存棋局”和“續上局”是如何實現的嗎?
五子棋的數據結構描述
我們知道,五子棋有一個正方形棋盤,分別設有白子和黑子:
那麼這個五子棋盤就可以使用二維數組來描述,假設是一個 11 × 11 的二維數組:
int[][] chessArr = new int[11][11];
然後我們輸出一下:
for (int[] row : chessArr) {
\tfor (int data : row) {
\t\tSystem.out.printf("%d ", data);
\t}
\tSystem.out.println();
}
然後我們先來填幾顆棋子,模擬一個五子棋局,在代碼中,由於初始的二維數組中默認都是 0 ,那我們就可以考慮用 1 代表 黑子,用 2 代表白子:
chessArr[1][2] = 1; // 黑子先行
chessArr[2][3] = 2; // 白子緊隨其後
chessArr[1][4] = 1; // 黑子欲形成橫向三連之勢
chessArr[1][3] = 2; // 白子“挺進大別山”斷了黑子的陰謀
再輸出,就可以看到黑子白子形成的“圍追堵截”之勢了,有沒有點懷念小時候的感覺?
棋盤的壓縮保存
接下來就是今天的正題!如果你已經看到這裡,一定要堅持!
五子棋的保存實際上並不是保存整個棋盤,而是通過一個叫做“稀疏數組”的結構來完成的。
稀疏數組,顧名思義是一個很稀疏的數組......
咳咳,稀疏數組實際上是一個只保存原始二維數組有效數據,去掉無效數據的一個二維數組。
當一個數組中大部分元素是0,或為同一個值的時候,可以使用稀疏數組來保存數組。它是一個十分有效的壓縮存儲結構,而且還不涉及任何複雜的算法,簡單又實用!!
它的處理方式是:
1、記錄數組一共有幾行幾列,有多少有效值;
2、把具有有效值的元素的行、列及值記錄在一個小規模二維數組中(稀疏數組),從而降低存儲數據的規模。
如果一個二維數組長這樣:
那麼用於保存它的稀疏數組就可以是這樣:
如上圖所示:稀疏數組有固定的三列,分別代表原始二維數組的行、列和值,但是第一行具有特殊的含義:稀疏數組的第一行存儲原始數組的行數、列數和有效數據個數,這三個信息。而從第二行(也就是[1]行)開始,才是真正的原始二維數組的有效數據。
是不是非常簡單?
稀疏數組保存五子棋的代碼實現
分析完了稀疏數組的數據結構,那麼我們就來通過代碼實現上面五子棋局的保存。
剛才的五子棋局是這樣的:
那麼如何生成對應的稀疏數組呢?當然是先循環了......
首先要確定有多少個有效數據,這個是非常關鍵的:
int sum = 0;
for (int i = 0; i < chessArr.length; i++) {
\tfor (int j = 0; j < chessArr[0].length; j++) {
\t\tif (chessArr[i][j] != 0) {
\t\t\tsum++;
\t\t}
\t}
}
得到 sum 的原始二維數組有效數據有,我們就可以聲明這個稀疏數組了:
int[][] sparseArr = new int[sum + 1][3];
然後是將原始數組的 行數、列數 和 有效數據個數 放入稀疏數組的第一行:
sparseArr[0][0] = chessArr.length;
sparseArr[0][1] = chessArr[0].length;
sparseArr[0][2] = sum;
最後就是將原始數組中的非 0 數據存放到稀疏數組中
int sparseArrRow = 1;
for (int i = 0; i < chessArr.length; i++) {
\tfor (int j = 0; j < chessArr[0].length; j++) {
\t\tif (chessArr[i][j] != 0) {
\t\t\tsparseArr[sparseArrRow][0] = i;
\t\t\tsparseArr[sparseArrRow][1] = j;
\t\t\tsparseArr[sparseArrRow][2] = chessArr[i][j];
\t\t\tsparseArrRow++;
\t\t}
\t}
}
到這裡為止,就完成了對稀疏數組的創建和賦值,我們的二維數組也已經放入到了這個 “壓縮”了的二維數組——稀疏數組之中。那我們來輸出一下這個稀疏數組,看看是不是我們想要的內容:
完美!
五子棋的覆盤——稀疏數組還原原始二維數組
有了上面的經驗,下面的“小怪獸”就基本上不需要怎麼打了。
文 | Java聖鬥士
Hello 各位熱愛學習的小夥伴們大家好,今天來給大家聊聊五子棋遊戲的後臺實現。
相信大家都玩過五子棋遊戲,規則就是率先連成 5 顆棋子的一方獲勝。小編小的時候也非常喜歡玩五子棋,覺得自己天下無敵了,對手再怎麼努力都不會逃脫自己的圍追堵截,堵著堵著就贏了,哈哈。
可是你有想過五子棋的“保存棋局”和“續上局”是如何實現的嗎?
五子棋的數據結構描述
我們知道,五子棋有一個正方形棋盤,分別設有白子和黑子:
那麼這個五子棋盤就可以使用二維數組來描述,假設是一個 11 × 11 的二維數組:
int[][] chessArr = new int[11][11];
然後我們輸出一下:
for (int[] row : chessArr) {
\tfor (int data : row) {
\t\tSystem.out.printf("%d ", data);
\t}
\tSystem.out.println();
}
然後我們先來填幾顆棋子,模擬一個五子棋局,在代碼中,由於初始的二維數組中默認都是 0 ,那我們就可以考慮用 1 代表 黑子,用 2 代表白子:
chessArr[1][2] = 1; // 黑子先行
chessArr[2][3] = 2; // 白子緊隨其後
chessArr[1][4] = 1; // 黑子欲形成橫向三連之勢
chessArr[1][3] = 2; // 白子“挺進大別山”斷了黑子的陰謀
再輸出,就可以看到黑子白子形成的“圍追堵截”之勢了,有沒有點懷念小時候的感覺?
棋盤的壓縮保存
接下來就是今天的正題!如果你已經看到這裡,一定要堅持!
五子棋的保存實際上並不是保存整個棋盤,而是通過一個叫做“稀疏數組”的結構來完成的。
稀疏數組,顧名思義是一個很稀疏的數組......
咳咳,稀疏數組實際上是一個只保存原始二維數組有效數據,去掉無效數據的一個二維數組。
當一個數組中大部分元素是0,或為同一個值的時候,可以使用稀疏數組來保存數組。它是一個十分有效的壓縮存儲結構,而且還不涉及任何複雜的算法,簡單又實用!!
它的處理方式是:
1、記錄數組一共有幾行幾列,有多少有效值;
2、把具有有效值的元素的行、列及值記錄在一個小規模二維數組中(稀疏數組),從而降低存儲數據的規模。
如果一個二維數組長這樣:
那麼用於保存它的稀疏數組就可以是這樣:
如上圖所示:稀疏數組有固定的三列,分別代表原始二維數組的行、列和值,但是第一行具有特殊的含義:稀疏數組的第一行存儲原始數組的行數、列數和有效數據個數,這三個信息。而從第二行(也就是[1]行)開始,才是真正的原始二維數組的有效數據。
是不是非常簡單?
稀疏數組保存五子棋的代碼實現
分析完了稀疏數組的數據結構,那麼我們就來通過代碼實現上面五子棋局的保存。
剛才的五子棋局是這樣的:
那麼如何生成對應的稀疏數組呢?當然是先循環了......
首先要確定有多少個有效數據,這個是非常關鍵的:
int sum = 0;
for (int i = 0; i < chessArr.length; i++) {
\tfor (int j = 0; j < chessArr[0].length; j++) {
\t\tif (chessArr[i][j] != 0) {
\t\t\tsum++;
\t\t}
\t}
}
得到 sum 的原始二維數組有效數據有,我們就可以聲明這個稀疏數組了:
int[][] sparseArr = new int[sum + 1][3];
然後是將原始數組的 行數、列數 和 有效數據個數 放入稀疏數組的第一行:
sparseArr[0][0] = chessArr.length;
sparseArr[0][1] = chessArr[0].length;
sparseArr[0][2] = sum;
最後就是將原始數組中的非 0 數據存放到稀疏數組中
int sparseArrRow = 1;
for (int i = 0; i < chessArr.length; i++) {
\tfor (int j = 0; j < chessArr[0].length; j++) {
\t\tif (chessArr[i][j] != 0) {
\t\t\tsparseArr[sparseArrRow][0] = i;
\t\t\tsparseArr[sparseArrRow][1] = j;
\t\t\tsparseArr[sparseArrRow][2] = chessArr[i][j];
\t\t\tsparseArrRow++;
\t\t}
\t}
}
到這裡為止,就完成了對稀疏數組的創建和賦值,我們的二維數組也已經放入到了這個 “壓縮”了的二維數組——稀疏數組之中。那我們來輸出一下這個稀疏數組,看看是不是我們想要的內容:
完美!
五子棋的覆盤——稀疏數組還原原始二維數組
有了上面的經驗,下面的“小怪獸”就基本上不需要怎麼打了。
廢話不多說,直接上代碼:
int[][] chessArr1 = new int[sparseArr[0][0]][sparseArr[0][1]];
for (int i = 1; i < sparseArr.length; i++) {
\tchessArr1[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
}
然後輸出:
文 | Java聖鬥士
Hello 各位熱愛學習的小夥伴們大家好,今天來給大家聊聊五子棋遊戲的後臺實現。
相信大家都玩過五子棋遊戲,規則就是率先連成 5 顆棋子的一方獲勝。小編小的時候也非常喜歡玩五子棋,覺得自己天下無敵了,對手再怎麼努力都不會逃脫自己的圍追堵截,堵著堵著就贏了,哈哈。
可是你有想過五子棋的“保存棋局”和“續上局”是如何實現的嗎?
五子棋的數據結構描述
我們知道,五子棋有一個正方形棋盤,分別設有白子和黑子:
那麼這個五子棋盤就可以使用二維數組來描述,假設是一個 11 × 11 的二維數組:
int[][] chessArr = new int[11][11];
然後我們輸出一下:
for (int[] row : chessArr) {
\tfor (int data : row) {
\t\tSystem.out.printf("%d ", data);
\t}
\tSystem.out.println();
}
然後我們先來填幾顆棋子,模擬一個五子棋局,在代碼中,由於初始的二維數組中默認都是 0 ,那我們就可以考慮用 1 代表 黑子,用 2 代表白子:
chessArr[1][2] = 1; // 黑子先行
chessArr[2][3] = 2; // 白子緊隨其後
chessArr[1][4] = 1; // 黑子欲形成橫向三連之勢
chessArr[1][3] = 2; // 白子“挺進大別山”斷了黑子的陰謀
再輸出,就可以看到黑子白子形成的“圍追堵截”之勢了,有沒有點懷念小時候的感覺?
棋盤的壓縮保存
接下來就是今天的正題!如果你已經看到這裡,一定要堅持!
五子棋的保存實際上並不是保存整個棋盤,而是通過一個叫做“稀疏數組”的結構來完成的。
稀疏數組,顧名思義是一個很稀疏的數組......
咳咳,稀疏數組實際上是一個只保存原始二維數組有效數據,去掉無效數據的一個二維數組。
當一個數組中大部分元素是0,或為同一個值的時候,可以使用稀疏數組來保存數組。它是一個十分有效的壓縮存儲結構,而且還不涉及任何複雜的算法,簡單又實用!!
它的處理方式是:
1、記錄數組一共有幾行幾列,有多少有效值;
2、把具有有效值的元素的行、列及值記錄在一個小規模二維數組中(稀疏數組),從而降低存儲數據的規模。
如果一個二維數組長這樣:
那麼用於保存它的稀疏數組就可以是這樣:
如上圖所示:稀疏數組有固定的三列,分別代表原始二維數組的行、列和值,但是第一行具有特殊的含義:稀疏數組的第一行存儲原始數組的行數、列數和有效數據個數,這三個信息。而從第二行(也就是[1]行)開始,才是真正的原始二維數組的有效數據。
是不是非常簡單?
稀疏數組保存五子棋的代碼實現
分析完了稀疏數組的數據結構,那麼我們就來通過代碼實現上面五子棋局的保存。
剛才的五子棋局是這樣的:
那麼如何生成對應的稀疏數組呢?當然是先循環了......
首先要確定有多少個有效數據,這個是非常關鍵的:
int sum = 0;
for (int i = 0; i < chessArr.length; i++) {
\tfor (int j = 0; j < chessArr[0].length; j++) {
\t\tif (chessArr[i][j] != 0) {
\t\t\tsum++;
\t\t}
\t}
}
得到 sum 的原始二維數組有效數據有,我們就可以聲明這個稀疏數組了:
int[][] sparseArr = new int[sum + 1][3];
然後是將原始數組的 行數、列數 和 有效數據個數 放入稀疏數組的第一行:
sparseArr[0][0] = chessArr.length;
sparseArr[0][1] = chessArr[0].length;
sparseArr[0][2] = sum;
最後就是將原始數組中的非 0 數據存放到稀疏數組中
int sparseArrRow = 1;
for (int i = 0; i < chessArr.length; i++) {
\tfor (int j = 0; j < chessArr[0].length; j++) {
\t\tif (chessArr[i][j] != 0) {
\t\t\tsparseArr[sparseArrRow][0] = i;
\t\t\tsparseArr[sparseArrRow][1] = j;
\t\t\tsparseArr[sparseArrRow][2] = chessArr[i][j];
\t\t\tsparseArrRow++;
\t\t}
\t}
}
到這裡為止,就完成了對稀疏數組的創建和賦值,我們的二維數組也已經放入到了這個 “壓縮”了的二維數組——稀疏數組之中。那我們來輸出一下這個稀疏數組,看看是不是我們想要的內容:
完美!
五子棋的覆盤——稀疏數組還原原始二維數組
有了上面的經驗,下面的“小怪獸”就基本上不需要怎麼打了。
廢話不多說,直接上代碼:
int[][] chessArr1 = new int[sparseArr[0][0]][sparseArr[0][1]];
for (int i = 1; i < sparseArr.length; i++) {
\tchessArr1[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
}
然後輸出:
完美!
稀疏數組總結
其實呢,稀疏數組主要就是用於壓縮存儲,將原來的二維數組中大量的無效數據捨棄掉,通過記錄行數、列數、有效值個數,以及有效值的 “座標”和值,來實現一個節省空間的存儲結構。
稀疏數組主要的特點就是體現在其獨特的數據結構上,其中不涉及任何算法,完全就是憑著結構完成了數據壓縮的功能。有點像憑顏值搞定一切的趕腳......
甚至我們也可以將稀疏數組進行改裝,在不是五子棋這種應用場景下,依然可以利用“結構化有效數據”的思路來實現數據壓縮,節省更多的存儲空間。
數據結構和算法都是需要平時慢慢積累的知識,所以,如果大家在地鐵或者公交上看了這篇文章,因為沒有靜心,讀不懂,可以收藏後,通過代碼一步一步代入式學習,相信你一定會有所收穫的。
怎麼樣?聰明的你學會了嗎?!
往期精彩:
對話式情景剖析,String被final修飾的真正原因!一篇足矣
Java如何處理JSON數據?一篇Jackson教你快速入門
關注Java聖鬥士,帶你輕鬆暢談程序內外的人與事,做一個快樂的 IT 技術精英,升職加薪、迎娶白富美、走上人生巔峰!你還在等啥呢?快上車!