theme: cyanosis

Snipaste_2025-10-30_20-15-56.png

本章目标:掌握Rust条件判断和for循环,让颜色系统具备智能决策能力

条件判断,让程序拥有思考的艺术

想象一下,如果程序只会按部就班地执行代码,那该多么呆板!就像一个只会重复动作的机器人,永远不会根据情况做出调整。而条件判断就是给程序装上"大脑",让它能够观察、思考、决策。

在颜色世界中,条件判断更是无处不在:深色背景配浅色文字,浅色背景配深色文字;红色表示警告,绿色表示成功;根据时间切换主题色调…这些都需要程序具备"判断"的能力。

flowchart TD
    A[颜色输入] --> B{条件判断}
    B -->|亮度 > 128| C[使用深色文字]
    B -->|亮度 ≤ 128| D[使用浅色文字]
    B -->|红色分量高| E[警告样式]
    B -->|绿色分量高| F[成功样式]
    C --> G[智能颜色搭配]
    D --> G
    E --> G
    F --> G

1. 用户痛点:颜色搭配的智能化需求

想象这个场景:你在设计一个界面,需要在不同颜色的背景上显示文字。如果背景是深色,文字就应该是浅色;如果背景是浅色,文字就应该是深色。手动调整每一个颜色搭配,既费时又容易出错。

痛苦的现状

fn main() {
    println!("=== 痛苦的现状:手动颜色搭配 ===");
    
    // 每个背景色都要手动选择文字颜色
    let bg1 = (30, 30, 30);    // 深色背景
    let text1 = (255, 255, 255); // 手动选择白色文字
    
    let bg2 = (240, 240, 240);  // 浅色背景  
    let text2 = (0, 0, 0);      // 手动选择黑色文字
    
    let bg3 = (100, 100, 100);  // 中等亮度背景
    let text3 = (255, 255, 255); // 这个选择对吗?
    
    println!("背景1: {:?} -> 文字: {:?}", bg1, text1);
    println!("背景2: {:?} -> 文字: {:?}", bg2, text2);
    println!("背景3: {:?} -> 文字: {:?} (可能不够清晰)", bg3, text3);
    println!("每次都要手动判断,太麻烦了!");
}

我们需要什么

image.png

  • 程序能自动判断背景亮度
  • 根据亮度智能选择文字颜色
  • 支持不同的颜色主题和风格
  • 处理边界情况和特殊需求

2. Rust条件判断基础:if表达式的威力

什么是条件判断?
条件判断就像生活中的"如果…那么…"逻辑。比如:“如果下雨,那么带伞”、“如果饿了,那么吃饭”。在编程中,我们用这种逻辑让程序根据不同情况做出不同的反应。

Rust中的if特点

  • if表达式,不是语句,可以返回值
  • 条件必须是布尔类型,不会自动转换
  • 所有分支必须返回相同类型的值
  • 支持链式条件判断
true
false
条件表达式
布尔值判断
执行if分支
执行else分支
返回值
赋值给变量或直接使用

基础if语法演示

fn main() {
    println!("\n=== Rust条件判断基础 ===");
    
    let color_value = 128;
    
    // 基础if语句
    if color_value > 127 {
        println!("这是一个亮色 ({})", color_value);
    }
    
    // if-else语句
    if color_value > 127 {
        println!("亮色:适合深色文字");
    } else {
        println!("暗色:适合浅色文字");
    }
    
    // if作为表达式(Rust特色)
    let text_color = if color_value > 127 {
        "黑色文字"  // 亮背景用深色文字
    } else {
        "白色文字"  // 暗背景用浅色文字
    };
    
    println!("背景亮度: {} -> 推荐文字: {}", color_value, text_color);
}

重要概念解释

  • 表达式 vs 语句:表达式有返回值,语句执行动作
  • 布尔类型:只有truefalse两个值
  • 类型一致性:if和else分支必须返回相同类型

3. 颜色亮度计算:智能判断的基础

亮度计算的科学原理
人眼对不同颜色的敏感度不同,绿色最敏感,红色次之,蓝色最不敏感。因此计算亮度时需要加权处理,而不是简单的平均值。

标准亮度公式
亮度 = 0.299 × R + 0.587 × G + 0.114 × B

// 计算颜色亮度的函数
fn calculate_brightness(rgb: (u8, u8, u8)) -> f32 {
    let (r, g, b) = rgb;
    // 使用标准亮度公式,考虑人眼敏感度
    0.299 * r as f32 + 0.587 * g as f32 + 0.114 * b as f32
}

// 简化版本(适合初学者理解)
fn simple_brightness(rgb: (u8, u8, u8)) -> u8 {
    let (r, g, b) = rgb;
    // 简单平均值计算
    ((r as u16 + g as u16 + b as u16) / 3) as u8
}

fn main() {
    println!("=== 颜色亮度计算演示 ===");
    
    let colors = vec![
        ("纯黑", (0, 0, 0)),
        ("深灰", (64, 64, 64)),
        ("中灰", (128, 128, 128)),
        ("浅灰", (192, 192, 192)),
        ("纯白", (255, 255, 255)),
        ("纯红", (255, 0, 0)),
        ("纯绿", (0, 255, 0)),
        ("纯蓝", (0, 0, 255)),
    ];
    
    for (name, rgb) in colors {
        let brightness = calculate_brightness(rgb);
        let simple = simple_brightness(rgb);
        
        println!("{}: RGB{:?}", name, rgb);
        println!("  标准亮度: {:.1}", brightness);
        println!("  简单亮度: {}", simple);
        println!();
    }
}

代码解释

  • 类型转换as f32将整数转换为浮点数进行精确计算
  • 元组解构let (r, g, b) = rgb一次性获取三个颜色分量
  • 权重计算:不同颜色分量使用不同的权重系数

4. 智能文字颜色选择:条件判断实战

现在我们来解决开头的痛点,用条件判断实现智能的文字颜色选择:

// 智能选择文字颜色
fn choose_text_color(background: (u8, u8, u8)) -> (u8, u8, u8) {
    let brightness = calculate_brightness(background);
    
    // 亮度阈值:128是中间值
    if brightness > 128.0 {
        (0, 0, 0)       // 亮背景用黑色文字
    } else {
        (255, 255, 255) // 暗背景用白色文字
    }
}

// 更精细的文字颜色选择
fn smart_text_color(background: (u8, u8, u8)) -> (u8, u8, u8) {
    let brightness = calculate_brightness(background);
    
    if brightness > 200.0 {
        (0, 0, 0)         // 很亮:纯黑文字
    } else if brightness > 128.0 {
        (64, 64, 64)      // 较亮:深灰文字
    } else if brightness > 64.0 {
        (192, 192, 192)   // 较暗:浅灰文字
    } else {
        (255, 255, 255)   // 很暗:纯白文字
    }
}

// 显示颜色搭配效果
fn display_color_match(background: (u8, u8, u8), text: (u8, u8, u8), label: &str) {
    let (bg_r, bg_g, bg_b) = background;
    let (txt_r, txt_g, txt_b) = text;
    
    // 使用ANSI码显示背景色和文字色的搭配效果
    print!("\x1b[48;2;{};{};{}m", bg_r, bg_g, bg_b);  // 设置背景色
    print!("\x1b[38;2;{};{};{}m", txt_r, txt_g, txt_b); // 设置文字色
    print!("  {}  ", label);
    print!("\x1b[0m"); // 重置颜色
    
    println!(" 背景RGB({},{},{}) -> 文字RGB({},{},{})", 
             bg_r, bg_g, bg_b, txt_r, txt_g, txt_b);
}

fn main() {
    println!("=== 智能文字颜色选择演示 ===");
    
    let test_backgrounds = vec![
        ("深夜黑", (20, 20, 20)),
        ("炭灰色", (80, 80, 80)),
        ("中性灰", (128, 128, 128)),
        ("银白色", (200, 200, 200)),
        ("纯白色", (255, 255, 255)),
        ("深蓝色", (0, 50, 100)),
        ("亮黄色", (255, 255, 100)),
    ];
    
    println!("1. 基础智能选择:");
    for (name, bg_color) in &test_backgrounds {
        let text_color = choose_text_color(*bg_color);
        display_color_match(*bg_color, text_color, name);
    }
    
    println!("\n2. 精细智能选择:");
    for (name, bg_color) in &test_backgrounds {
        let text_color = smart_text_color(*bg_color);
        display_color_match(*bg_color, text_color, name);
    }
}

关键技术点

  • 多级条件判断:使用else if实现更精细的控制
  • 阈值设计:选择合适的亮度阈值来区分不同情况
  • 视觉反馈:通过ANSI颜色码直观展示搭配效果

5. 颜色状态判断:布尔逻辑的应用

布尔逻辑在颜色中的应用
在颜色处理中,我们经常需要判断颜色的各种状态和属性,这就需要用到布尔逻辑运算。

image.png

// 颜色属性判断函数集合
fn is_dark_color(rgb: (u8, u8, u8)) -> bool {
    calculate_brightness(rgb) < 128.0
}

fn is_light_color(rgb: (u8, u8, u8)) -> bool {
    calculate_brightness(rgb) > 128.0
}

fn is_grayscale(rgb: (u8, u8, u8)) -> bool {
    let (r, g, b) = rgb;
    r == g && g == b  // 三个分量相等就是灰度色
}

fn is_warm_color(rgb: (u8, u8, u8)) -> bool {
    let (r, g, b) = rgb;
    r > g && r > b  // 红色分量最大
}

fn is_cool_color(rgb: (u8, u8, u8)) -> bool {
    let (r, g, b) = rgb;
    b > r && b > g  // 蓝色分量最大
}

fn is_high_contrast(bg: (u8, u8, u8), fg: (u8, u8, u8)) -> bool {
    let bg_brightness = calculate_brightness(bg);
    let fg_brightness = calculate_brightness(fg);
    (bg_brightness - fg_brightness).abs() > 100.0  // 亮度差大于100
}

// 复合条件判断
fn analyze_color_properties(rgb: (u8, u8, u8)) -> String {
    let mut properties = Vec::new();
    
    // 使用多个布尔判断
    if is_dark_color(rgb) {
        properties.push("深色");
    } else {
        properties.push("浅色");
    }
    
    if is_grayscale(rgb) {
        properties.push("灰度");
    } else if is_warm_color(rgb) {
        properties.push("暖色调");
    } else if is_cool_color(rgb) {
        properties.push("冷色调");
    } else {
        properties.push("中性色调");
    }
    
    properties.join(" + ")
}

fn main() {
    println!("=== 颜色属性判断演示 ===");
    
    let test_colors = vec![
        ("深红色", (139, 0, 0)),
        ("天蓝色", (135, 206, 235)),
        ("中灰色", (128, 128, 128)),
        ("亮黄色", (255, 255, 0)),
        ("深紫色", (75, 0, 130)),
        ("浅粉色", (255, 182, 193)),
    ];
    
    for (name, color) in test_colors {
        println!("\n{}: RGB{:?}", name, color);
        println!("  属性分析: {}", analyze_color_properties(color));
        println!("  是否深色: {}", is_dark_color(color));
        println!("  是否灰度: {}", is_grayscale(color));
        println!("  是否暖色: {}", is_warm_color(color));
        
        // 测试对比度
        let white = (255, 255, 255);
        let black = (0, 0, 0);
        println!("  与白色对比度: {}", is_high_contrast(color, white));
        println!("  与黑色对比度: {}", is_high_contrast(color, black));
    }
}

布尔逻辑运算符

  • && - 逻辑与(AND):两个条件都为真
  • || - 逻辑或(OR):至少一个条件为真
  • ! - 逻辑非(NOT):取反
  • == - 相等比较
  • != - 不等比较
  • >, <, >=, <= - 大小比较

6. 简单渐变文字:条件判断与循环的初步结合

渐变效果的魅力
想象一下,如果我们能让文字呈现渐变色彩,那该多么有趣!通过结合条件判断和for循环,我们可以为每个字符计算不同的颜色。

image.png

核心知识点

  • for循环遍历:逐个处理字符串中的每个字符
  • enumerate():同时获取索引和元素
  • 条件分类:根据字符类型应用不同颜色
  • ANSI转义码:在终端中显示彩色效果
// 简单的RGB渐变文字函数
fn simple_gradient_text(text: &str) {
    let chars: Vec<char> = text.chars().collect();
    let len = chars.len();
    
    for (i, ch) in chars.iter().enumerate() {
        // 计算进度比例(0.0 到 1.0)
        let progress = i as f32 / len as f32;
        
        // 简单的红到蓝渐变
        let r = (255.0 * (1.0 - progress)) as u8;  // 红色逐渐减少
        let g = 100;                               // 绿色保持不变
        let b = (255.0 * progress) as u8;          // 蓝色逐渐增加
        
        // 使用条件判断处理特殊字符
        if ch.is_whitespace() {
            print!(" ");  // 空格保持原样
        } else {
            print!("\x1b[38;2;{};{};{}m{}", r, g, b, ch);
        }
    }
    println!("\x1b[0m");  // 重置颜色
}

// 根据字符类型选择颜色
fn colored_by_type(text: &str) {
    for ch in text.chars() {
        // 根据字符类型使用不同颜色
        let (r, g, b) = if ch.is_ascii_alphabetic() {
            (0, 255, 0)      // 字母用绿色
        } else if ch.is_ascii_digit() {
            (0, 100, 255)    // 数字用蓝色
        } else if ch.is_ascii_punctuation() {
            (255, 215, 0)    // 标点用金色
        } else {
            (255, 255, 255)  // 其他用白色
        };
        
        if ch.is_whitespace() {
            print!(" ");
        } else {
            print!("\x1b[38;2;{};{};{}m{}", r, g, b, ch);
        }
    }
    println!("\x1b[0m");
}

fn main() {
    println!("=== 🌈 简单渐变文字演示 ===");
    
    let welcome_text = "欢迎来到 Rust 世界";
    
    println!("\n1. 简单RGB渐变:");
    simple_gradient_text(welcome_text);
    
    println!("\n2. 按类型着色:");
    colored_by_type("Hello123, Rust编程! 2024年");
    
    println!("\n3. 条件判断在循环中的应用:");
    let test_text = "Code123!代码";
    print!("原文: {}", test_text);
    println!();
    print!("彩色: ");
    colored_by_type(test_text);
}

代码要点解析

1. 简单渐变算法

let progress = i as f32 / len as f32;  // 计算进度比例
let r = (255.0 * (1.0 - progress)) as u8;  // 红色逐渐减少
let b = (255.0 * progress) as u8;          // 蓝色逐渐增加
  • 进度计算:将字符位置转换为0-1的比例
  • 线性插值:使用简单的数学公式实现颜色过渡
  • 类型转换as u8将浮点数转为整数

2. 字符类型判断

if ch.is_ascii_alphabetic() {
    (0, 255, 0)      // 字母用绿色
} else if ch.is_ascii_digit() {
    (0, 100, 255)    // 数字用蓝色
}
  • 分类函数:使用Rust内置的字符分类函数
  • 颜色策略:为不同类型的字符分配不同颜色
  • 默认处理:为未匹配的情况提供白色

3. ANSI转义码使用

print!("\x1b[38;2;{};{};{}m{}", r, g, b, ch);
println!("\x1b[0m");  // 重置颜色
  • 真彩色输出:24位RGB颜色
  • 格式重置:确保颜色不会影响后续输出

实际应用

  • 终端工具的彩色输出
  • 日志级别区分
  • 代码语法高亮

条件判断与循环的结合

  1. 循环遍历 - 使用for循环处理每个字符
  2. 条件分支 - 根据字符类型选择不同处理
  3. 数学计算 - 使用简单公式实现渐变效果
  4. 视觉反馈 - 通过颜色变化展示程序逻辑

这个简单的例子展示了条件判断在实际应用中的强大能力,同时为下一章的循环学习做了很好的铺垫!


本章核心要点

条件判断的价值

  1. 智能决策 - 让程序根据情况做出不同反应
  2. 用户体验 - 自动优化颜色搭配,提升可读性
  3. 逻辑控制 - 实现复杂的业务逻辑和流程控制
  4. 系统灵活性 - 支持多种模式和个性化设置

Rust条件判断特色

  1. 表达式特性 - if可以返回值,代码更简洁
  2. 类型安全 - 条件必须是布尔类型,避免隐式转换
  3. 模式匹配 - 为复杂条件判断提供更优雅的解决方案
  4. 零成本抽象 - 编译时优化,运行时无额外开销

通过本章学习,你已经掌握了让程序"思考"的能力!条件判断是编程逻辑的基础,接下来我们将学习如何让程序"重复工作" - 循环控制。


更多文章和视频知识资讯,大家可以关注我的公众号、掘金和 B 站 。让我们一起成长,变得更强。我们下次再见~

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐