You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

计算机专业学生数独项目redo功能故障修复求助

修复数独项目Redo功能的常见思路与方案

Hey there! 作为开发过数独类项目的过来人,我太懂这种undo正常但redo卡壳的憋屈感了😉 结合你描述的Bug场景——修改Case时存旧值到历史支持undo,但首次redo出问题——大概率是你对undo/redo的双栈逻辑处理有漏洞,下面给你拆解问题、落地修复方案:

先分析你可能踩的坑

你提到修改Case时会把旧Case存入历史记录,这说明undo的基础逻辑是对的,但redo失效通常逃不开这两个核心问题:

  • 没有分离Undo和Redo的存储栈:如果只用一个栈同时存undo和redo记录,undo后没有把当前状态单独存入redo栈,导致redo时无有效记录可取;
  • 状态存储用了浅拷贝:如果存到历史栈里的Case只是当前对象的引用(浅拷贝),后续修改当前Case会同时篡改栈里的历史记录,redo时拿到的是已经被修改过的无效状态;
  • 首次Undo后未正确维护Redo栈:第一次执行undo时,忘记把当前的Case状态推入redo栈,导致redo栈为空,自然无法执行首次redo。

落地修复的具体步骤

1. 改用双栈结构(核心!)

必须分开维护undoStack和redoStack,明确两个栈的职责:

  • undoStack:存储所有可以被撤销的历史Case状态;
  • redoStack:存储所有可以被重做的历史Case状态。

对应的操作逻辑应该是这样:

  • 修改Case时:
    • 先把当前完整的Case状态深拷贝后推入undoStack;
    • 执行修改操作;
    • 清空redoStack(因为新操作会让之前的redo记录全部失效,这一点很容易忘!)
  • 执行Undo时:
    • 先判断undoStack是否为空,不为空则把当前Case状态深拷贝后推入redoStack;
    • 从undoStack弹出最后一个状态,恢复为当前Case;
  • 执行Redo时:
    • 先判断redoStack是否为空,不为空则把当前Case状态深拷贝后推入undoStack;
    • 从redoStack弹出最后一个状态,恢复为当前Case。

2. 确保状态是深拷贝

这是很多人忽略的细节:如果你的Case是一个对象或复杂数据结构(比如数组、字典),直接存引用会导致历史记录被后续修改污染。举个例子:

  • 错误做法:undoStack.append(current_case)(存引用,修改current_case会同步改栈里的内容)
  • 正确做法:用深拷贝工具,比如Python的copy.deepcopy(),Java的clone()(要实现深克隆),C++的拷贝构造函数等。

3. 给首次Redo加日志排查

如果只有首次redo失效,建议在undo和redo操作前后打印两个栈的长度,比如:

// 执行undo前打印
System.out.println("Undo前: undo栈长度=" + undoStack.size() + ", redo栈长度=" + redoStack.size());
// 执行undo后打印
System.out.println("Undo后: undo栈长度=" + undoStack.size() + ", redo栈长度=" + redoStack.size());

看看首次undo后redo栈有没有新增元素——如果没有,说明你在undo时漏了把当前状态推入redo栈,补上这个步骤就能解决问题。

伪代码示例(Python版)

import copy

# 初始化双栈和初始数独状态
undo_stack = []
redo_stack = []
current_case = [[0 for _ in range(9)] for _ in range(9)]  # 9x9空数独

def update_case(row, col, value):
    global current_case
    # 深拷贝当前状态到undo栈
    undo_stack.append(copy.deepcopy(current_case))
    # 执行修改
    current_case[row][col] = value
    # 新操作后清空redo栈
    redo_stack.clear()

def undo():
    global current_case
    if undo_stack:
        # 把当前状态存到redo栈
        redo_stack.append(copy.deepcopy(current_case))
        # 恢复undo栈的最后状态
        current_case = undo_stack.pop()

def redo():
    global current_case
    if redo_stack:
        # 把当前状态存到undo栈
        undo_stack.append(copy.deepcopy(current_case))
        # 恢复redo栈的最后状态
        current_case = redo_stack.pop()

按照这个逻辑调整后,你的redo功能应该就能正常工作了,尤其是首次redo的问题会得到解决。

内容的提问来源于stack exchange,提问作者Nemtecl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:01:51