package main
import (
"bufio" // 用到了带缓冲地读取文件数据
"fmt" // 格式化输出等
"io" // 判断是否到文件末尾等
"os" // 只用到了文件打开
"strconv" // 只用于将string转换为int
"strings" // 只用到了字符串分割,删除无用字符
)
// 定义一个结构体用于存储稀松矩阵的行列元素值
type ValNode struct {
row int
col int
val int
}
// valNode结构体的构造函数
func newValNode(row, col, val int) ValNode {
return ValNode{
row: row,
col: col,
val: val,
}
}
// 存盘
func SaveCheesMap() {
// 创建原始的二维数组
// 1代表黑子,2代表白子,0代表没放棋子
var cheesMap [11][11]int // 初始化一个二维数组代表空棋盘(此处零值=0)
cheesMap[0][1] = 1
cheesMap[1][2] = 2
cheesMap[2][3] = 3
fmt.Println("输出原始的二维数组")
for _, v1 := range cheesMap {
for _, v2 := range v1 {
fmt.Printf("%d\t", v2)
}
fmt.Println() // 遍历完一行换行
}
// 转换成稀疏矩阵存盘
var sparseArr []ValNode // 用来存储稀疏矩阵的所有信息(第一个为稀松矩阵规模:行列数,无效值=0,其他为有效值)
// 稀松矩阵规模,无效值=0
valnode0 := newValNode(11, 11, 0)
sparseArr = append(sparseArr, valnode0)
// 转换成稀疏矩阵
for r, v1 := range cheesMap {
for c, v2 := range v1 {
if v2 != 0 {
// 如果不是0,实例化对象 r:行 c:列
valnode := newValNode(r, c, v2)
// 添加到sparseArr切片
sparseArr = append(sparseArr, valnode)
}
}
}
// 遍历sparseArr存盘
fileObj, err := os.OpenFile("sparseArr.data", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) // 不存在则创建
defer fileObj.Close() // 即将退出函数是关闭文件
if err != nil {
fmt.Println("open file failed,error:", err)
return
}
for _, v := range sparseArr {
// fmt.Printf("%d %d %d\n", v.row, v.col, v.val)
fileObj.WriteString(fmt.Sprintf("%d %d %d\n", v.row, v.col, v.val))
}
}
func ReadFromSparseArr() {
// 读取之前的存盘并恢复成原始数组(此处使用切片)
// 1.读盘
fileObj, err := os.Open("sparseArr.data")
defer fileObj.Close()
if err != nil {
fmt.Println("open file failed,error:", err)
return
}
// 2.按行读取数据并恢复成数组
var cheesMapNew [][]int
reader := bufio.NewReader(fileObj)
times := 0
for {
times++
content, err := reader.ReadString('\n')
if err == io.EOF {
// fmt.Println("文件读取完成")
break
}
if err != nil {
fmt.Println("read file failed,error:", err)
return
}
contentNew := strings.Trim(content, "\n") // 去掉\n换行符 返回字符串
contentSlice := strings.Split(contentNew, " ") // 根据空格拆分字符串 返回string的切片
// 将字符串转换为int
row, _ := strconv.Atoi(contentSlice[0])
col, _ := strconv.Atoi(contentSlice[1])
val, _ := strconv.Atoi(contentSlice[2])
// 对二维切片进行初始化
if times == 1 {
// 遍历到第一个数据(规模,默认值)时对二维切片进行初始化
// 因为无效数据(没有放棋子)为0,正好等于int切片的零值,因此初始化后不必特殊处理
cheesMapNew = make([][]int, row) // 共有几行?
for i, _ := range cheesMapNew {
cheesMapNew[i] = make([]int, col) // 一行具体有几列:切片初始化
}
// 第一个数据:11 11 0只是原来数据的规模,默认值,跳过即可
continue // 也可以在if语句中else分支写有效数据赋值代码
}
// 对初始化好的二维切片赋值(将稀疏矩阵中的有效数据进行还原) 1代表黑子,2代表白子
cheesMapNew[row][col] = val
}
// 验证:输出恢复后的二维序列(切片类型)
fmt.Println("验证:输出恢复后的二维切片")
for _, v1 := range cheesMapNew {
for _, v2 := range v1 {
fmt.Printf("%d\t", v2)
}
fmt.Println()
}
}
// 程序入口
func main() {
fmt.Println("苦しんでる人がいるかぎり、頑張ります。Let's Go!")
// 存盘
SaveCheesMap()
// 读取存盘文件并恢复
ReadFromSparseArr()
}