- package tetris;
- import java.io.DataInputStream;
- import java.io.DataOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- public class ShapesUtil
- {
-
- public static void main(String[] args) throws IOException
- {
- //先看代码最后的那个三位数组,俄罗斯方块对于我们来说
- //没一个单元格cell,只有2个状态吧?一个就是有,一个
- //就是没有,或者理解成可通行的和障碍物
-
- /*
- * 0 0 0 0
- * 1 0 0 0
- * 1 0 0 0
- * 1 1 0 0
- */
-
- //上方这个图形,咱们就可以用一个short表示了吧,16位
- //这也是为什么会有第六题的原因,循序渐进。
-
- //其实很多人做这个东西,并不是按位存储的,而就是一个
- //3维int数组,每次3层循环迭代,效率是问题不说,内存
- //和硬盘占用也大,早先的手机ROM很小,流量也贵,下载
- //东西节约流量是很重要的,现在的3G流量虽然便宜,但
- //也需要重视,另外一个就是RAM也就是我们说的内存,
- //在我最早做手机游戏的时候,200K的内存,去掉其他占用
- //留给你的内存使用是很少的,所以节约内存也是一个好习惯
-
- //当然说那么多都是废话,咱们这里只是练习一下位运算符和
- //一些存储方面的常见用法。
-
- //运行一次之后刷新下你的eclipse项目,就可以看见这个cfg
- //文件,至于这个后缀你随便起什么,因为除了咱们的程序能
- //正常解析之外,你拿记事本是看不出来什么东西的。
-
- //而后缀名只是一种便捷的标识,他并不能证明这个后缀名是靠
- //什么程序解析,就像咱们这个不能被记事本解析一样,你会看
- //到乱码
- //如果咱们取个Tetris.txt 你还真的去拿记事本看?那样的话
- //你就会看见下边这个天书,或许你苦思冥想数十载也可能看懂
- //? ."€ ?& ?? Nb@ ? ? ? ? l? l? ?? ?菵D UU
-
- writeShapes();
- readShapes();
- }
-
- /**
- * 保存俄罗斯方块图形数据的文件路径
- */
- public static final String FILE_NAME = "Tetris.cfg";
-
- public static void readShapes() throws IOException
- {
- FileInputStream fis = new FileInputStream(new File(FILE_NAME));
- DataInputStream dis = new DataInputStream(fis);
- long shape = 0;
- //这里的这个dis.available() > 0算是一种便捷用法
- //也是避免一些IO异常的方式。
-
- //为什么我不需要知道文件内有多少个图形?
- //实际上如果你的写入和读取是对等,用dis.available() > 0
- //这种方式并不会导致EOF异常
- //EOF的一种情况是你的读取字节大于写入字节。
- while(dis.available() > 0)
- {
- shape = dis.readLong();
- System.out.println(getLongToBinary(shape));
- }
- }
-
- /**
- * 将图形数据写入文件,根据图形的实际数据进行位合并
- * 并每个short表示一帧,每个long表示一个图形
- * @throws IOException
- */
- public static void writeShapes() throws IOException
- {
- FileOutputStream fos = new FileOutputStream(new File(FILE_NAME));
- DataOutputStream dos = new DataOutputStream(fos);
-
- //这个shape就是换算过的图形,用来写入文件
- long shape = 0;
- //将图形循环写入文件
- //shape_index 在这里表示图形索引
- //frame_index 表示这个图形的帧索引
- //bit 表示当前帧数据上的2进制位
- for (int shape_index = 0; shape_index < shapes.length; shape_index++)
- {
- //清0,将缓冲的上一个图形删除
- shape &= 0;
- //计算当前图形的每一2进制位数据,最后保存为一个long
- //并将该数据写入文件
- for (int frame_index = 0; frame_index < shapes[shape_index].length; frame_index++)
- {
- for (int bit = 0; bit < shapes[shape_index][frame_index].length; bit++)
- {
- /*
- * 0 0 0 0
- * 1 0 0 0
- * 1 0 0 0
- * 1 1 0 0
- */
-
- //从数据源中,可以看出来这就是一个short,也就是16位的2进制数据
- //由于我们规定每个图形都是4帧,所以没一个图形的完整数据就是64位
- //也就是一个long
-
- //(long)shapes[shape_index][frame_index][bit] 表示的当前位
- //但是咱们的循环是0开始,所以读入的顺序不会错,但是写进去的话就是
- //倒叙了,因为我们是从最低位为起始位的。
-
- //(((frame_index) << 4) 表示的是我们当前帧需要前进多少位
- //我们划分数据区是16位一帧,最多是左移48位表示高16位
- //而由于前边说的我们读入和写入的顺序是相反的,所以这里的这个
- //(((frame_index) << 4),我们还得做下处理,在倒叙一下就变
- //正序了吧?所以这里需要一个((3 - frame_index) << 4)
-
- //15-bit 的原理跟上边的帧序列一样
- //而这里的 shape |= 就跟我们前边讲的往上添数据一样的用法
- shape |= (long)shapes[shape_index][frame_index][bit] << (((3 - frame_index) << 4) + (15-bit));
- }
- }
- dos.writeLong(shape);
- }
- dos.close();
- }
-
- public static final String DEFAULT_LONG_ZERO = "0000000000000000000000000000000000000000000000000000000000000000";
- public static final String getLongToBinary(long value)
- {
- String binary = Long.toBinaryString(value);
- int length = Long.SIZE - binary.length();
- return DEFAULT_LONG_ZERO.substring(0, length) + binary;
- }
-
- /**
- * 俄罗斯方块中的图形,第一维表示的是图形的索引
- * 第二维表示的是这个图形的帧索引
- * 第三维表示这个图形当前帧的数据,每4位为一行
- */
- public static final int[][][] shapes =
- {
- /*
- * 0 0 0 0
- * 1 0 0 0
- * 1 0 0 0
- * 1 1 0 0
- */
- {
- {
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 1, 0, 0, 0,
- 1, 1, 0, 0,
- },
-
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 1, 0,
- 1, 1, 1, 0,
- },
-
- {
- 0, 0, 0, 0,
- 0, 1, 1, 0,
- 0, 0, 1, 0,
- 0, 0, 1, 0,
- },
-
- {
- 0, 0, 0, 0,
- 1, 1, 1, 0,
- 1, 0, 0, 0,
- 0, 0, 0, 0,
- }
- },
-
- /*
- * 0 0 0 0
- * 0 0 0 0
- * 1 0 0 0
- * 1 1 1 0
- */
- {
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 1, 1, 1, 0,
- },
-
- {
- 0, 0, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 1, 0,
- 0, 1, 1, 0,
- },
-
- {
- 0, 0, 0, 0,
- 1, 1, 1, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 0,
- },
-
- {
- 0, 0, 0, 0,
- 1, 1, 0, 0,
- 1, 0, 0, 0,
- 1, 0, 0, 0,
- }
- },
-
- /*
- * 0 0 0 0
- * 1 0 0 0
- * 1 1 0 0
- * 1 0 0 0
- */
- {
- {
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 1, 1, 0, 0,
- 1, 0, 0, 0,
- },
-
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 1, 0, 0,
- 1, 1, 1, 0,
- },
-
- {
- 0, 0, 0, 0,
- 0, 0, 1, 0,
- 0, 1, 1, 0,
- 0, 0, 1, 0,
- },
-
- {
- 0, 0, 0, 0,
- 1, 1, 1, 0,
- 0, 1, 0, 0,
- 0, 0, 0, 0,
- }
- },
-
- /*
- * 0 0 0 0
- * 0 0 0 0
- * 1 1 0 0
- * 1 1 0 0
- */
- {
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 1, 0, 0,
- 1, 1, 0, 0,
- },
-
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 1, 0, 0,
- 1, 1, 0, 0,
- },
-
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 1, 0, 0,
- 1, 1, 0, 0,
- },
-
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 1, 0, 0,
- 1, 1, 0, 0,
- }
- },
-
- /*
- * 0 0 0 0
- * 0 0 0 0
- * 0 1 1 0
- * 1 1 0 0
- */
- {
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 1, 1, 0,
- 1, 1, 0, 0,
- },
-
- {
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 1, 1, 0, 0,
- 0, 1, 0, 0,
- },
-
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 1, 1, 0,
- 1, 1, 0, 0,
- },
-
- {
- 0, 0, 0, 0,
- 1, 0, 0, 0,
- 1, 1, 0, 0,
- 0, 1, 0, 0,
- }
- },
-
- /*
- * 0 0 0 0
- * 0 0 0 0
- * 1 1 0 0
- * 0 1 1 0
- */
- {
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 1, 0, 0,
- 0, 1, 1, 0,
- },
-
- {
- 0, 0, 0, 0,
- 0, 1, 0, 0,
- 1, 1, 0, 0,
- 1, 0, 0, 0,
- },
-
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 1, 0, 0,
- 0, 1, 1, 0,
- },
-
- {
- 0, 0, 0, 0,
- 0, 1, 0, 0,
- 1, 1, 0, 0,
- 1, 0, 0, 0,
- }
- },
-
-
- /*
- * 1 0 0 0
- * 1 0 0 0
- * 1 0 0 0
- * 1 0 0 0
- */
- {
- {
- 0, 1, 0, 0,
- 0, 1, 0, 0,
- 0, 1, 0, 0,
- 0, 1, 0, 0,
- },
-
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 1, 1, 1,
- },
-
- {
- 0, 1, 0, 1,
- 0, 1, 0, 1,
- 0, 1, 0, 1,
- 0, 1, 0, 1,
- },
-
- {
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 1, 1, 1,
- }
- },
- };
- }
复制代码 |