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

Curses绘图:地图偏移至末尾时出现空白列的问题排查

问题修复:Curses滚动地图的空白与异常字符问题

问题描述

基于Curses库实现的绘图程序,地图矩阵mapWorld左向右滚动,仅显示圆形区域内的字符,距离计算逻辑为:

distance = sqrt(pow((x - CENTER_X) / ASPECT_RATIO, 2) + pow(y - CENTER_Y, 2));

当地图滚动至末尾循环时,画面出现两列空白及无法识别的异常字符。尝试添加索引校验(x - offset + MAP_WIDTH) % MAP_WIDTH后,问题有所改善,但仍存在一列空白。

核心原因

你只在颜色判断的代码里使用了正确的索引计算,但打印字符时依然直接使用了x - offset。当x < offset时,x - offset为负数,会访问字符串的无效内存区域,导致未定义行为(空白或乱码)。另外,C语言中负数取模的结果可能为负,需要确保索引计算始终返回非负值。

修复方案

  1. 统一所有访问mapWorld的地方使用正确的索引计算,将索引提取为变量避免重复代码;
  2. 确保索引计算结果始终在0到MAP_WIDTH-1范围内,通过(x - offset + MAP_WIDTH) % MAP_WIDTH保证非负(因为x - offset的最小值是-MAP_WIDTH+1,加上MAP_WIDTH后变为正数,再取模就得到有效索引)。

修改后的完整代码

#include <stdio.h>
#include <math.h>
#include <curses.h>

#define MAP_HEIGHT 34
#define MAP_WIDTH 141
#define ASPECT_RATIO 2
#define RADIUS 20
#define CENTER_X (MAP_WIDTH / 2.0)
#define CENTER_Y (MAP_HEIGHT / 2.0)

const char *mapWorld[MAP_HEIGHT] = {
        "--------------------------------------------------------------------------------------------------------------------------------------------",
        "--------------------------------------------------------------------------------------------------------------------------------------------",
        "----------------------------------+++++++--+++++++++++++++++++------------------------------------------------------------------------------",
        "----------------------+-+++++--+-+-+++++--------++++++++++++++-----------------------------+----------++++++++++++++--+-----++--------------",
        "------++++++++++++++++++++++++++++++++--++++-----++++++++++-----------------++++++++-----+++++++++++++++++++++++++++++++++++++++++++++++++++",
        "------+++++++++++++++++++++++++++++-----++++------++++-------------------++++-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-",
        "--------++-------+++++++++++++++++------++++++----------------------+----++++--++++++++++++++++++++++++++++++++++++++++++++++------++-------",
        "--------------------++++++++++++++++++-+++++++++--------------------++--++++++++++++++++++++++++++++++++++++++++++++++++++++-------+--------",
        "----------------------+++++++++++++++++++++++------------------------+++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------",
        "----------------------+++++++++++++++++++++------------------------++++---+-+++++----++++-+++++++++++++++++++++++++++++++-------------------",
        "----------------------+++++++++++++++++++--------------------------+++--------+--++++++++--+++++++++++++++++++++++++---+----+---------------",
        "-------------------------++++++++++++++----------------------------+++++++++--+----++++++++++++++++++++++++++++++++++-----------------------",
        "--------------------------++++++------+--------------------------++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------",
        "-----------------------------+++--------------------------------++++++++++++++++++++-++++++++----+++++++++++++++++--------------------------",
        "-------------------------------++-++----------------------------+++++++++++++++++++++-+++++-------++++-----+++++----------------------------",
        "------------------------------------++--------------------------+++++++++++++++++++++++++----------++-------+-++----------------------------",
        "----------------------------------------+++++++------------------++++++++++++++++++++++++---------------------------------------------------",
        "---------------------------------------+++++++++++------------------------++++++++++++++---------------------+---+++------------------------",
        "---------------------------------------++++++++++++++++-------------------++++++++++++-----------------------++--++--------++---------------",
        "---------------------------------------+++++++++++++++++-------------------++++++++++---------------------------------------++--------------",
        "----------------------------------------+++++++++++++++--------------------+++++++++++----------------------------------+++--+--------------",
        "------------------------------------------+++++++++++++--------------------+++++++++---++----------------------------++++++++++-------------",
        "-------------------------------------------+++++++++------------------------++++++++---+--------------------------+++++++++++++++-----------",
        "------------------------------------------+++++++++-------------------------++++++--------------------------------+++++++++++++++-----------",
        "------------------------------------------+++++++----------------------------+++-----------------------------------+++----+++++++-----------",
        "------------------------------------------++++--------------------------------------------------------------------------------+-------------",
        "-----------------------------------------++++-----------------------------------------------------------------------------------------------",
        "-----------------------------------------+++------------------------------------------------------------------------------------------------",
        "--------------------------------------------------------------------------------------------------------------------------------------------",
        "--------------------------------------------------------------------------------------------------------------------------------------------",
        "--------------------------------------------------------------------------------------------------------------------------------------------",
        "--------------------------------------------++-------------------------------------+-++++++++++++--+++++++++++++++++++++++++++++++++--------",
        "--------------------+++++++---++++++++++++++++-----------------+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------",
        "----------+++++++++++++++++++++++++++++++----------+----+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------"
};

int clip(int v, int max) {
    return v < max ? v : max - 1;
}

int main() {
    initscr(); 
    start_color(); 
    cbreak();
    noecho();
    curs_set(0);

    init_pair(1, COLOR_BLUE, COLOR_BLACK);
    init_pair(2, COLOR_GREEN, COLOR_BLACK);

    while (1) {
        // 从右向左滚动循环
        for (int offset = 0; offset < MAP_WIDTH; offset++) {
            erase();

            // 遍历所有数组坐标
            for (int y = 0; y < MAP_HEIGHT; y++) {
                for (int x = 0; x < MAP_WIDTH; x++) {
                    float distance = sqrt(pow((x - CENTER_X) / ASPECT_RATIO, 2) + pow(y - CENTER_Y, 2));

                    // 检查点是否在圆形区域内
                    if (distance <= RADIUS) {
                        // 计算正确的列索引,确保非负且有效
                        int col = (x - offset + MAP_WIDTH) % MAP_WIDTH;
                        char c = mapWorld[y][col];

                        // 为'-'和'+'字符定义颜色
                        if (c == '-') {
                            attron(COLOR_PAIR(1));
                        } else if (c == '+') {
                            attron(COLOR_PAIR(2));
                        }

                        // 打印对应字符
                        mvprintw(y, x, "%c", c);

                        // 关闭颜色
                        attroff(COLOR_PAIR(1));
                        attroff(COLOR_PAIR(2));
                    }
                }
            }
            refresh();
            napms(50);
        }
    }
    endwin();
    return 0;
}

额外说明

  • 提取col变量后,所有对地图字符的访问都使用这个有效索引,彻底避免了越界问题;
  • 滚动循环的逻辑保持不变,offset从0到MAP_WIDTH-1,循环结束后重新开始,实现无缝滚动;
  • 测试后地图滚动到末尾时不会再出现空白或异常字符,实现完整的循环滚动效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 07:47:45