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

使用Perl的Term::Animation编写的程序提前退出问题排查

问题分析与修复

核心问题

  1. 未处理getch()的超时返回值:halfdelay(1)设置1秒超时,超时后getch()返回ERR(数值-1),原代码未处理该情况,可能触发意外逻辑。
  2. 按键类型不匹配:KEY_LEFT/KEY_RIGHT是数值常量,原代码用lc(getch())将输入转为字符串后用eq比较,导致方向键逻辑失效,还可能引发隐性错误。
  3. 未限制对象移动边界:x值无限制增减,当超出终端可视范围时,Term::Animation的渲染逻辑可能抛出异常导致程序崩溃。
  4. 未正确终止Curses会话:原代码中quit()函数未定义,且未在所有退出路径调用endwin()恢复终端状态。

修复后的代码

use strict;
use warnings;
use Curses;
use Term::Animation;

my $anim = Term::Animation->new();
# 获取终端宽度,限制x的移动范围
my ($cols) = getmaxyx(stdscr);
my $x = 0;

$anim->new_entity(
    shape           => ['@'],
    position        => [$x, 0, 0],
    auto_trans      => 1,
);

halfdelay(1);

while (1) {
    my $in = getch();
    # 跳过超时返回的无效值
    next if $in == ERR;

    # 区分字符按键和特殊按键的比较方式
    if ($in eq 'q') {
        endwin();
        exit;
    }
    elsif ($in eq 'r') {
        last;
    }
    elsif ($in eq 'p') {
        $anim->pause(!$anim->paused());
    }
    elsif ($in eq 'd' || $in == KEY_RIGHT) {
        # 限制x不超过终端宽度-1
        $x++ if $x < $cols - 1;
        $anim->set_entity_position(0, $x, 0, 0);
    }
    elsif ($in eq 'a' || $in == KEY_LEFT) {
        # 限制x不小于0
        $x-- if $x > 0;
        $anim->set_entity_position(0, $x, 0, 0);
    }

    $anim->animate();
}

# 退出循环后恢复终端状态
endwin();
$anim->update_term_size();
$anim->remove_all_entities();

修改说明

  • 处理超时返回值:增加next if $in == ERR;跳过无效的超时返回,避免后续逻辑出错。
  • 修正按键比较逻辑:字符按键用eq字符串比较,特殊按键(方向键)用==数值比较,确保移动逻辑正确触发。
  • 限制移动边界:通过getmaxyx获取终端宽度,限制x在0到cols-1区间内,防止对象超出可视范围导致崩溃。
  • 规范终端退出流程:在q按键分支调用endwin()后直接exit,循环结束后也调用endwin(),确保终端状态正常恢复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 02:12:13