编写的五子棋程序中,有存盘退出和续上盘的功能
因为该二维数组的很多值是默认值 0, 因此记录了很多没有意义的数据
当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方法是:
记录数组一共有几行几列,有多少个不同的值
思想:把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模
使用稀疏数组,来保留类似前面的二维数组(棋盘、地图等等)
把稀疏数组存盘,并且可以从新恢复原来的二维数组数
思路分析:
代码实现:
package main
import (
"bufio"
"fmt"
"os"
)
type ValNode struct {
row int
col int
val int
}
func main() {
filePath := "E:/golang开发学习/sparsearray.data"
file, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
fmt.Printf("open file err=%v\n", err)
return
}
//及时关闭file句柄
defer file.Close()
// 1. 创建一个原始数组
var chessMap [11][11]int
chessMap[1][2] = 1
chessMap[2][3] = 2
// 2. 输出查看原始数组
fmt.Println("原始数组为:")
for _, v := range chessMap {
for _, v2 := range v {
fmt.Printf("%d\t", v2)
}
fmt.Println()
}
// 3. 转成稀疏数组
// 思路
// 1.遍历chessMap,如果我们发现有一个元素的值不为0,创建一个node结构体
// 2.将其放入到对应的切片即可
var sparseArr []ValNode
// 添加初始节点 保存二维数组规模(行和列, 默认值)
ValNode := ValNode{
row: 11,
col: 11,
val: 0,
}
sparseArr = append(sparseArr, ValNode)
for i, v := range chessMap {
for j, v1 := range v {
if v1 != 0 {
// 创建一个ValNode 值节点
ValNode.row = i
ValNode.col = j
ValNode.val = v1
sparseArr = append(sparseArr, ValNode)
}
}
}
// 4. 输出稀疏数组
fmt.Println("当前的稀疏数组是:")
writer := bufio.NewWriter(file)
for _, ValNode := range sparseArr {
var s1 = fmt.Sprintf("%d %d %d\n", ValNode.row, ValNode.col, ValNode.val)
writer.WriteString(s1)
fmt.Printf("%s", s1)
}
writer.Flush()
}
运行结果
[Running] go run "e:\golang开发学习\go_pro\test.go"
原始数组为:
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 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 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
当前的稀疏数组是:
11 11 0
1 2 1
2 3 2
坑点一:读取后是字符串需要,分割成字符串数组,这里通过Split但是数组最后一个多一个换行符号需要去掉。
坑点二:golang是无法直接在二维数组创建时传变量的。这个时候先声明一个二维切片。初始化二维切片后。填入初始值。
代码实现:
package main
import (
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
)
func main() {
file, err := os.Open("E:/golang开发学习/sparsearray.data")
if err != nil {
fmt.Printf("打开文件出错:%v", err)
}
defer file.Close()
reader := bufio.NewReader(file)
str, err := reader.ReadString('\n')
if err == io.EOF { //io.EOF 文件末尾
fmt.Println("第一行 读取完毕")
}
// 分割字符串 通过空格
arr := strings.Split(str, " ")
m, _ := strconv.Atoi(arr[0])
n, _ := strconv.Atoi(arr[1])
v, err := strconv.Atoi(strings.Replace(arr[2], "\n", "", -1))
if err != nil {
// handle error
fmt.Println(err)
os.Exit(2)
}
// golang是无法直接在二维数组创建时传变量的 var chessMap [m][n]int 不能成功
var chessMap [][]int
for i := 0; i < m; i++ {
arr1 := make([]int, n) //创建一个一维切片
chessMap = append(chessMap, arr1) //把一维切片,当作一个整体传入二维切片中
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
chessMap[i][j] = v
}
}
for {
str, err := reader.ReadString('\n') // 一次读到换行结束
if err == io.EOF { //io.EOF 文件末尾
break
}
//输出内容
arr := strings.Split(str, " ")
m, _ := strconv.Atoi(arr[0])
n, _ := strconv.Atoi(arr[1])
v, _ := strconv.Atoi(strings.Replace(arr[2], "\n", "", -1))
chessMap[m][n] = v
}
fmt.Println("稀疏数组还原成原数组:")
for _, v := range chessMap {
for _, v2 := range v {
fmt.Printf("%d\t", v2)
}
fmt.Println()
}
}