在json中优化布尔数组大小

时间:2017-09-15 07:21:47

标签: javascript arrays json typescript binary

我为一个类似塞尔达的游戏写了一个小水平设计师(RPG) 是否某个地方(当从水平设计师保存地图时,可以预先计算16x16平方可以预先计算) 然后将此地图加载到游戏中。

可行走方格(瓦片)存储在大量数组(x,y)

让我们说它是一张小巧的3x3地图,json看起来像这样:

walls = [[true,true, true],
         [true,false,true],
         [true,true, true]]

意味着只有中心区块可以步行(1x1 墙壁== false)

现在我确实使用了布尔值,所以我可以优化空间,技术上可以在1个字节中存储8个块信息。

但现在存储它的方式感觉ULTRA未优化,因为每个块都存储为json文件中布尔值的字符串表示。

有没有办法存储数组的原始二进制数据,或创建自己的协议并将这些不规则的二进制数据存储在json中?

这个数组显然从未被人类解释过,所以我不介意它是不可读的。

1 个答案:

答案 0 :(得分:1)

首先,让我们改用整数:

walls = [[1,1,1],
         [1,0,1],
         [1,1,1]]

1甚至看起来像墙; - )

对此进行字符串化会给你一些比布尔短的东西:

JSON.stringify(walls) // "[[1,1,1],[1,0,1],[1,1,1]]"

您也可以自己将地图字符串化为更紧凑的格式:

const walls = [[1,1,1],
             [1,0,1],
             [1,1,1]];

// Stringified
const map = walls.map(r => r.join('')).join('|');
console.log(map); // "111|101|111"

// Unstringified
const wallsAgain = map.split('|').map(r => r.split('').map(Number))
console.log(wallsAgain);

// Or back to your boolean format.
const wallsToBooleans = map.split('|').map(r => r.split('').map(c => c === '1'))
console.log(wallsToBooleans)

现在事情变得有趣......

如果我们真的疯了,我们可以通过将1/0的“二进制”表示转换为不同的基数来使字符串化地图更短:

const walls = [[1,1,1,1,1],
               [1,0,1,0,1],
               [1,1,1,1,1],
               [1,0,1,0,1],
               [1,1,1,1,1]];

const mapBase = 36;

const map = stringifyMap(walls);

console.log(map);                           // Stringified ("1f|15|1f|15|1f")
console.log(parseMap(map));                 // Unstringified
console.log(parseMap(map, c => c === '1')); // Or back to your boolean format.

// Walls to string
function stringifyMap(walls) {
  return walls.map(r => rowToStr(r)).join('|');
}

// String to walls
function parseMap(map, cellParser) {
  return map.split('|')
    .map(r => strToRow(r)
      .map(cellParser || Number))

}

function rowToStr(row){
  const num = parseInt(row.join(''), 2); // Parse the `'10101'` to int,
  return num.toString(mapBase);          // Then convert it to a higher base;
}

function strToRow(str){
  const num = parseInt(str, mapBase); // Parse the higher base to int,
  return num.toString(2).split('');   // Then convert it to binary.
}