对一小排地图格子进行编辑后,可以撤销一步,也可以重做刚撤销的步骤。但撤销之后做了新的有效修改,原来的未来分支通常不能再直接沿用。
下面把一个游戏界面或模拟规则拆成可复查的记录。每组输入独立给出,先确认单位、先后次序和边界,再核对结果。它不依赖具体游戏的隐藏参数,读者可以直接挑选几步手工复算。
六格初始为零,操作为设置某格、撤销或重做。只记录确实改变内容的设置;有效设置清空重做记录,撤销保存反向恢复机会,重做重新应用原结果。历史最多保留给定次数,改成相同值不算新编辑,也不清空重做。
最多保留3步撤销,初始六格全零 操作[['set', 0, 2], ['set', 1, 5], ['undo'], ['redo'], ['undo'], ['set', 4, 5], ['redo'], ['set', 5, 2], ['set', 2, 3], ['set', 2, 1], ['set', 0, 0], ['redo'], ['set', 3, 5], ['set', 4, 5], ['redo'], ['set', 1, 4], ['redo'], ['redo'], ['redo'], ['set', 3, 4]]
第1步['set', 0, 2],画面六格[2, 0, 0, 0, 0, 0],可撤销1步、可重做0步,本次状态有变。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第2步['set', 1, 5],画面六格[2, 5, 0, 0, 0, 0],可撤销2步、可重做0步,本次状态有变。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第3步['undo'],画面六格[2, 0, 0, 0, 0, 0],可撤销1步、可重做1步,本次状态有变。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第4步['redo'],画面六格[2, 5, 0, 0, 0, 0],可撤销2步、可重做0步,本次状态有变。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第5步['undo'],画面六格[2, 0, 0, 0, 0, 0],可撤销1步、可重做1步,本次状态有变。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第6步['set', 4, 5],画面六格[2, 0, 0, 0, 5, 0],可撤销2步、可重做0步,本次状态有变。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第7步['redo'],画面六格[2, 0, 0, 0, 5, 0],可撤销2步、可重做0步,本次无有效变化。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第8步['set', 5, 2],画面六格[2, 0, 0, 0, 5, 2],可撤销3步、可重做0步,本次状态有变。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第9步['set', 2, 3],画面六格[2, 0, 3, 0, 5, 2],可撤销3步、可重做0步,本次状态有变。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第10步['set', 2, 1],画面六格[2, 0, 1, 0, 5, 2],可撤销3步、可重做0步,本次状态有变。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第11步['set', 0, 0],画面六格[0, 0, 1, 0, 5, 2],可撤销3步、可重做0步,本次状态有变。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第12步['redo'],画面六格[0, 0, 1, 0, 5, 2],可撤销3步、可重做0步,本次无有效变化。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第13步['set', 3, 5],画面六格[0, 0, 1, 5, 5, 2],可撤销3步、可重做0步,本次状态有变。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第14步['set', 4, 5],画面六格[0, 0, 1, 5, 5, 2],可撤销3步、可重做0步,本次无有效变化。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第15步['redo'],画面六格[0, 0, 1, 5, 5, 2],可撤销3步、可重做0步,本次无有效变化。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第16步['set', 1, 4],画面六格[0, 4, 1, 5, 5, 2],可撤销3步、可重做0步,本次状态有变。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第17步['redo'],画面六格[0, 4, 1, 5, 5, 2],可撤销3步、可重做0步,本次无有效变化。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第18步['redo'],画面六格[0, 4, 1, 5, 5, 2],可撤销3步、可重做0步,本次无有效变化。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第19步['redo'],画面六格[0, 4, 1, 5, 5, 2],可撤销3步、可重做0步,本次无有效变化。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
第20步['set', 3, 4],画面六格[0, 4, 1, 4, 5, 2],可撤销3步、可重做0步,本次状态有变。有效的新编辑才截断原重做分支,相同值设置不算新编辑。
最终六格[0, 4, 1, 4, 5, 2],撤销可用3步,重做可用0步;更早超容量的操作不能继续恢复。
另一种实现可以保存一列完整状态和当前游标:撤销移到前一状态,重做移到后一状态,新编辑先切掉游标之后的状态再追加。核对两种模型每步画面和可撤销、可重做次数。
容量限制会让更早编辑失去撤销机会,但不能改掉当前地图。连续多次撤销到头后应保持不动;空重做也一样。本例只处理单人本地编辑,不处理多人同时修改、保存到磁盘或跨会话历史。
练习时可以只改动一项输入,预测从哪一步开始出现变化,再逐步比较。空状态、数值零和无法判断要分别记录;不要为了让最后结果一致而忽略中途的偏差。边界与同分约定同样属于规则,复核时应一并保留。