十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

蓝桥杯单片机国赛真题剖析:从模块驱动到系统设计的实战指南

蓝桥杯单片机国赛真题剖析:从模块驱动到系统设计的实战指南 1. 项目概述从“真题”到“实战能力”的跨越拿到一份蓝桥杯单片机国赛的真题很多同学的第一反应可能是“刷题”——对照着题目要求把代码敲出来让功能跑通然后对照评分点看看能得多少分。这当然没错但如果你止步于此就错过了这份真题背后最宝贵的价值。作为一名带过好几届学生备赛的“老司机”我始终认为国赛真题的真正意义远不止于一道“题目”。它是一份浓缩了当时单片机技术应用热点、命题专家考察意图以及实际工程问题简化模型的“综合体检报告”。我们今天要做的不是简单地“做一遍”第十届国赛题而是像外科医生解剖一样把它层层剥开看看里面到底藏着哪些核心考点、设计思路和实战技巧最终把这些养分吸收转化成你解决任何陌生工程问题的底层能力。第十届国赛的题目通常具备承前启后的特点。它既会巩固之前几届考察过的基础核心技能如精准定时、矩阵键盘扫描、传感器数据采集与处理又会引入一些新的器件或更复杂的系统联动逻辑来拉开区分度。比如那一年是否重点考察了某种新型显示器件如OLED的驱动是否将常见的ADC采集玩出了新花样要求做实时滤波或复杂标度变换是否在控制逻辑中嵌套了状态机让系统行为更加智能这些才是我们复盘真题时需要死死盯住的关键。通过这道题我们不仅要学会“怎么做”更要悟透“为什么这么做”以及“下次遇到类似的该怎么办”。2. 核心需求解析与系统设计总览面对任何一道单片机赛题第一步绝不是打开编程软件而是拿出一张白纸进行需求拆解和系统设计。我们以第十届国赛一个典型的综合系统题为例具体题目细节可能因届次略有差异但方法论通用它可能要求设计一个“智能环境监测与控制系统”。我们需要把笼统的题目描述翻译成具体的、可执行的技术指标。2.1 功能性需求拆解首先我们把“智能环境监测与控制”这个大目标拆解成一个个独立的功能模块环境参数监测这是系统的“感知”部分。通常包括温度监测使用DS18B20或类似单总线数字温度传感器精度要求通常为±0.5℃。光照强度监测通过光敏电阻结合ADC模数转换器采集或者直接使用数字光照传感器如BH1750。有害气体/烟雾监测可能使用MQ-2等模拟量输出传感器通过ADC读取其电压值来判断浓度。显示需求所有监测数据需要在LCD12864或OLED屏幕上实时显示并可能要求有数值、曲线、报警状态等不同显示模式。人机交互这是系统的“控制”界面。按键输入4x4矩阵键盘或独立按键用于设置报警阈值、切换显示模式、手动控制设备等。声光报警当任何参数超限时需要触发蜂鸣器声音报警和LED光报警可能要求不同颜色或闪烁频率代表不同严重程度。控制执行这是系统的“执行”部分。继电器控制根据环境参数自动控制“加热器”模拟升温、“风扇”模拟降温、“加湿器”、“净化器”等负载的通断。这里负载通常用LED灯模拟。智能联动逻辑这是拉开差距的关键。例如“当温度过高且光照过强时先启动风扇若10秒后温度未下降则再启动加强制冷设备另一个LED”这就需要引入状态机和定时判断逻辑。数据通信与存储高阶需求国赛题有时会考察。EEPROM存储用于掉电保存用户设置的报警阈值。串口通信将监测数据上传到上位机虚拟串口屏或PC软件或接收上位机的控制指令。2.2 非功能性需求与设计约束除了“做什么”还要明确“做到什么程度”和“在什么限制下做”实时性数据刷新率如1秒1次、按键响应速度通常要求无抖动即时响应、控制决策延迟检测到超限到执行动作的时间都必须满足要求。稳定性程序不能跑飞、死机。尤其是在处理传感器通信如单总线、矩阵键盘扫描这些容易受干扰的部分代码必须健壮。资源限制蓝桥杯官方CT107D开发板基于IAP15F2K61S2单片机的硬件资源是固定的。我们需要仔细分配IO口、定时器、中断、内存等资源。例如定时器0用于系统时基1ms中断定时器1可能用于串口波特率发生器PWM输出可能用定时器2。外部中断可能用于按键唤醒等。可扩展性与可维护性代码结构要清晰模块化程度高。这样在调试或增加新功能时才不会牵一发而动全身。基于以上拆解我们可以绘制出一个简单的系统模块框图在脑海中或纸上明确各个模块之间的数据流和控制流。例如传感器模块采集数据 - 主循环处理数据 - 判断逻辑 - 驱动显示模块和报警模块 - 根据逻辑驱动执行模块。同时按键中断或扫描程序可以随时修改系统参数或状态。3. 硬件模块驱动深潜与代码抽象国赛真题的硬件平台是确定的因此吃透每一个片上资源和外设的驱动是写出高质量代码的基础。我们不能满足于“能跑”而要追求“稳定、高效、优雅”。3.1 矩阵键盘扫描的“无阻塞”与“长按连发”优化官方提供的键盘扫描例程往往是“扫描-延时消抖-等待释放”的阻塞式写法这在单任务系统中勉强可用但在需要实时刷新显示和采集数据的综合系统中会成为性能瓶颈。优化方案状态机非阻塞扫描我们利用系统1ms定时器中断在中断服务程序中设置一个标志位主循环中检测该标志每10-20ms执行一次扫描状态机。// 键盘状态机定义 typedef enum { KEY_STATE_IDLE, // 空闲态 KEY_STATE_DEBOUNCE, // 消抖态 KEY_STATE_PRESSED, // 确认按下态 KEY_STATE_REPEAT, // 长按连发态 KEY_STATE_RELEASE // 释放态 } KeyState_t; // 为每个按键或行列值维护一个状态机 KeyState_t key_state KEY_STATE_IDLE; uint8_t key_current_value 0xFF; // 当前扫描值 uint8_t key_last_value 0xFF; // 上次扫描值 uint16_t key_press_timer 0; // 按下计时器 uint16_t key_repeat_timer 0; // 连发计时器 // 在主循环中定期调用此函数 void Key_Scan_Task(void) { key_last_value key_current_value; key_current_value MatrixKey_Read(); // 读取当前行列值未按下为0xFF switch(key_state) { case KEY_STATE_IDLE: if(key_current_value ! 0xFF) { key_state KEY_STATE_DEBOUNCE; key_press_timer 20; // 消抖时间20ms } break; case KEY_STATE_DEBOUNCE: if(--key_press_timer 0) { if(key_current_value ! 0xFF key_current_value key_last_value) { key_state KEY_STATE_PRESSED; key_repeat_timer 500; // 首次长按判定时间500ms Key_Event_Handler(key_current_value, KEY_EVENT_PRESS); // 触发按下事件 } else { key_state KEY_STATE_IDLE; // 抖动回退 } } break; case KEY_STATE_PRESSED: if(key_current_value 0xFF) { key_state KEY_STATE_RELEASE; } else { if(--key_repeat_timer 0) { key_state KEY_STATE_REPEAT; key_repeat_timer 100; // 连发间隔100ms } } break; case KEY_STATE_REPEAT: if(key_current_value 0xFF) { key_state KEY_STATE_RELEASE; } else { if(--key_repeat_timer 0) { key_repeat_timer 100; Key_Event_Handler(key_current_value, KEY_EVENT_REPEAT); // 触发连发事件 } } break; case KEY_STATE_RELEASE: Key_Event_Handler(key_current_value, KEY_EVENT_RELEASE); // 触发释放事件 key_state KEY_STATE_IDLE; break; } }为什么这么做非阻塞扫描逻辑分散在多次主循环中每次只执行少量判断不占用大块CPU时间。精准消抖利用定时器计时比循环延时更准确且不干扰系统其他定时任务。功能丰富轻松区分短按、长按、连发为复杂人机交互如阈值连续调整提供了可能。3.2 传感器数据采集的“滤波”与“标度变换”传感器数据尤其是模拟传感器通常伴有噪声直接使用会导致显示跳变、控制误动作。一阶滞后滤波低通滤波这是比赛中实现简单且效果不错的滤波算法。Filtered_Value α * Raw_Value (1 - α) * Last_Filtered_Value其中α是滤波系数0α1取值越小滤波效果越强但响应越慢。在1ms中断中我们可以对ADC采样值进行滤波。#define ALPHA 0.2f // 滤波系数根据实际情况调整 uint16_t ADC_Filter(uint16_t new_sample) { static uint16_t filtered_val 0; // 注意浮点运算在51上较慢可改用整数运算优化filtered_val (new_sample * 2 filtered_val * 8) / 10; filtered_val (uint16_t)(ALPHA * new_sample (1 - ALPHA) * filtered_val); return filtered_val; }标度变换将ADC值如0-4095转换成有物理意义的数值如0.0-3.3V 0-100%湿度 0-1000 Lux照度。Physical_Value (ADC_Value - ADC_Min) * (Phys_Max - Phys_Min) / (ADC_Max - ADC_Min) Phys_Min这里的关键在于校准。题目中给出的“电压值”或“温度值”往往需要你根据参考点去反推ADC的上下限。例如题目说“当电压为1.5V时ADC读数为2048”那么你的ADC_Min对应0V可能就不是0需要计算。实操心得传感器数据处理部分一定要在代码中留出清晰的注释写明标度变换公式和校准参数。调试时先用固定电压源如开发板上的可调电阻分压测试你的ADC和变换程序确保从ADC读数到物理量显示的整个链路是正确的再去接真实传感器。这能帮你快速定位问题是硬件连接、驱动、还是数据处理逻辑。3.3 显示驱动的“分层”与“页面管理”当需要显示的内容很多数值、菜单、曲线、图标时直接向屏幕发送显示命令的代码会变得极其臃肿且难以维护。解决方案显示缓冲区 页面状态机建立显示缓冲区在内存中开辟一个数组disp_buf[行][列]完全对应屏幕的像素或字符位置。所有显示内容的更新都只操作这个缓冲区。定时刷新在定时器中断或主循环中定期如50ms调用一个Display_Refresh()函数将缓冲区的内容与屏幕当前内容对比只更新发生变化的部分。这可以避免屏幕闪烁和不必要的通信开销。页面管理定义不同的页面状态如主页、参数设置页、历史曲线页。每个页面有自己独立的绘制函数PageX_Draw()该函数只负责向disp_buf填充本页面该显示的内容。主循环根据当前页面状态调用对应页面的绘制和刷新函数。typedef enum { PAGE_MAIN, PAGE_SETTING, PAGE_GRAPH, PAGE_MAX } Page_t; Page_t current_page PAGE_MAIN; void Main_Loop(void) { while(1) { // ... 其他任务 switch(current_page) { case PAGE_MAIN: PageMain_Draw(); // 更新显示缓冲区 break; case PAGE_SETTING: PageSetting_Draw(); break; // ... } Display_Refresh(); // 统一刷新到屏幕 // ... } } // 在按键事件中切换页面 void Key_Event_Handler(uint8_t key, KeyEvent_t event) { if(event KEY_EVENT_PRESS) { if(key KEY_ENTER current_page PAGE_MAIN) { current_page PAGE_SETTING; } // ... 其他按键处理 } }这样做的好处是逻辑清晰切换页面简单且易于扩展新页面。4. 系统软件架构与多任务调度实践在只有一个主循环的单片机上如何让按键响应、显示刷新、数据采集、控制逻辑这些任务“同时”流畅运行这需要一种简单的协作式多任务调度思想通常称为“时间片轮询”或“基于状态机的超级循环”。4.1 定时器时基与任务调度器我们利用一个硬件定时器如定时器0产生精确的1ms中断在这个中断里更新一系列的时间戳或计数器。volatile uint32_t system_tick 0; // 系统运行毫秒数 void Timer0_ISR() interrupt 1 { system_tick; // 1ms加1 // ... 其他需要在中断中快速处理的事情如键盘扫描计时 }在主循环中我们不再使用delay_ms()这类阻塞函数而是通过检查system_tick或相关定时标志来非阻塞地执行各个任务。// 定义任务结构体 typedef struct { uint32_t last_run_tick; // 上次运行的时间戳 uint32_t interval; // 运行间隔ms void (*task_func)(void); // 任务函数指针 } Task_t; // 任务列表 Task_t task_list[] { {0, 20, Key_Scan_Task}, // 20ms扫描一次键盘 {0, 50, Sensor_Acquisition_Task}, // 50ms采集一次传感器 {0, 100, Display_Refresh_Task}, // 100ms刷新一次显示 {0, 500, Control_Logic_Task}, // 500ms执行一次控制逻辑 {0, 1000, System_Monitor_Task}, // 1s执行一次系统监控如看门狗喂狗 }; #define TASK_COUNT (sizeof(task_list)/sizeof(Task_t)) void main() { Sys_Init(); // 系统初始化包括定时器配置 while(1) { uint32_t now_tick system_tick; // 获取当前时间戳 for(uint8_t i0; iTASK_COUNT; i) { // 检查任务是否到执行时间 if(now_tick - task_list[i].last_run_tick task_list[i].interval) { task_list[i].task_func(); // 执行任务 task_list[i].last_run_tick now_tick; // 更新任务时间戳 } } // 这里可以放置一些需要一直运行的低优先级任务或进入低功耗模式 } }为什么有效这种架构保证了每个任务都能在预设的时间间隔内得到执行机会且不会互相阻塞。任务的执行间隔可以根据其紧急程度灵活设置按键扫描间隔短控制逻辑间隔可以稍长。整个系统是确定性的响应性非常好。4.2 控制逻辑中的状态机设计对于“当温度高于30度且持续5秒则打开风扇低于25度则关闭”这类需求简单的if-else会显得杂乱且难以处理更复杂的时序逻辑。使用有限状态机FSM是更优雅的方案。以风扇控制为例typedef enum { FAN_STATE_OFF, FAN_STATE_WAIT_HIGH, // 等待高温稳定 FAN_STATE_ON, FAN_STATE_WAIT_LOW // 等待低温稳定 } FanState_t; FanState_t fan_state FAN_STATE_OFF; uint32_t fan_timer 0; void Fan_Control_Task(float current_temp) { switch(fan_state) { case FAN_STATE_OFF: if(current_temp 30.0f) { fan_state FAN_STATE_WAIT_HIGH; fan_timer 5000; // 开始5秒计时假设此任务500ms执行一次则需计数10次 } break; case FAN_STATE_WAIT_HIGH: if(current_temp 30.0f) { fan_state FAN_STATE_OFF; // 温度回落取消 fan_timer 0; } else { if(--fan_timer 0) { fan_state FAN_STATE_ON; FAN_ON(); // 执行打开风扇动作 } } break; case FAN_STATE_ON: if(current_temp 25.0f) { fan_state FAN_STATE_WAIT_LOW; fan_timer 5000; // 低于25度开始5秒稳定计时 } break; case FAN_STATE_WAIT_LOW: if(current_temp 25.0f) { fan_state FAN_STATE_ON; // 温度回升保持开启 fan_timer 0; } else { if(--fan_timer 0) { fan_state FAN_STATE_OFF; FAN_OFF(); // 执行关闭风扇动作 } } break; } }这种设计将复杂的条件判断分解到明确的状态中逻辑清晰易于调试和扩展例如可以很容易地加入风扇调速、故障保护等新状态。5. 真题实战演练与代码模块化集成现在我们将上述所有技术点融入到一个模拟第十届国赛可能出现的“智能环境监测与控制”系统框架中。我们假设题目要求通过电位器模拟温度/光照输入ADC采集并显示按键设置阈值超阈值后控制LED模拟风扇/加热器并声光报警数据可通过串口上传。5.1 工程文件结构规划一个清晰的工程结构是团队协作和后期调试的基础。建议按如下方式组织Project/ ├── Inc/ (头文件) │ ├── config.h // 系统配置晶振频率、引脚定义等 │ ├── timer.h // 定时器驱动 │ ├── key.h // 键盘驱动状态机版 │ ├── lcd12864.h // 显示驱动 │ ├── adc.h // ADC驱动含滤波 │ ├── eeprom.h // EEPROM驱动 │ ├── uart.h // 串口驱动 │ ├── sensor.h // 传感器数据处理标度变换 │ └── system.h // 系统任务与状态机定义 ├── Src/ (源文件) │ ├── main.c // 主函数初始化超级循环 │ ├── timer.c │ ├── key.c │ ├── lcd12864.c │ ├── adc.c │ ├── eeprom.c │ ├── uart.c │ ├── sensor.c │ └── system.c // 任务调度、控制状态机 └── README.md // 工程说明在config.h中集中定义所有硬件相关的宏避免“魔术数字”散落在代码各处。// config.h 示例 #ifndef __CONFIG_H #define __CONFIG_H // 系统时钟 #define SYS_CLK 11059200UL // 引脚定义 sbit BUZZER P1^5; // 蜂鸣器 sbit RELAY_FAN P2^0; // 风扇继电器用LED模拟 sbit RELAY_HEAT P2^1; // 加热继电器 // ADC通道定义 #define ADC_CH_TEMP 0x01 // 温度传感器通道(P1.0) #define ADC_CH_LIGHT 0x03 // 光照传感器通道(P1.2) // 阈值默认值 #define DEFAULT_TEMP_HIGH 30.0f #define DEFAULT_TEMP_LOW 18.0f #endif5.2 主程序与任务调度核心实现main.c文件将变得非常简洁和清晰#include config.h #include system.h #include timer.h #include key.h #include lcd12864.h #include uart.h void main() { // 1. 系统基础初始化 Sys_Clock_Init(); // 时钟配置如有需要 Timer0_Init(); // 定时器0初始化1ms中断 UART_Init(); // 串口初始化用于调试或通信 EA 1; // 开启总中断 // 2. 外设初始化 LCD_Init(); Key_Init(); ADC_Init(); EEPROM_Init(); // 初始化IAP功能用于EEPROM // 3. 从EEPROM加载用户设置如果有 System_Load_Config(); // 4. 显示开机界面 LCD_Show_String(0, 0, Env Monitor V1.0); Delay_ms(1000); // 仅开机时用一次延时无妨 LCD_Clear(); // 5. 进入主循环超级循环 while(1) { // 任务调度器执行 Task_Scheduler_Run(); // 此处可以添加低优先级或后台任务 Idle_Task(); // 例如处理一些非实时性的计算 } }system.c中的任务调度器是核心// system.c #include system.h #include timer.h // 获取system_tick // 外部任务函数声明 extern void Key_Scan_Task(void); extern void Sensor_Acq_Task(void); extern void Display_Task(void); extern void Control_Task(void); extern void Comm_Task(void); Task_t task_list[] { {0, 10, Key_Scan_Task}, // 10ms高响应 {0, 100, Sensor_Acq_Task}, // 100ms {0, 200, Display_Task}, // 200ms显示刷新无需太快 {0, 500, Control_Task}, // 500ms {0, 1000, Comm_Task}, // 1000ms串口发送数据 }; void Task_Scheduler_Run(void) { uint32_t now Get_System_Tick(); // 从timer.c获取当前tick uint8_t i; for(i 0; i sizeof(task_list)/sizeof(Task_t); i) { if((now - task_list[i].last_run) task_list[i].interval) { task_list[i].task_func(); task_list[i].last_run now; } } }5.3 关键模块联调与数据流验证当所有模块编写完成后联调是关键。建议遵循以下顺序基础驱动测试单独测试每一个底层驱动。用UART_Printf自己实现或借助串口助手打印出ADC原始值、按键键值、EEPROM读写数据确保每个硬件都能正常工作。数据链路测试将传感器ADC值 - 滤波 - 标度变换 - 显示 这条链路打通。在屏幕上固定显示一个电压值用可调电阻改变输入看显示值是否线性、准确变化。控制逻辑测试屏蔽传感器用软件模拟一个变化的温度值观察风扇/加热器LED和蜂鸣器是否在设定的阈值点正确动作。同时测试按键修改阈值功能是否生效。系统整合与压力测试将所有功能开启长时间运行。观察是否有内存溢出变量异常、任务是否卡死、显示是否正常刷新。尝试快速连续按键看系统响应是否依然流畅。避坑指南联调中最常见的问题是变量共享冲突。例如在中断服务程序ISR中修改了一个变量在主循环中读取它。如果这个变量是大于8位的如int在8位单片机上其读写不是原子操作可能导致读到“半新半旧”的错误值。解决方案是如果可能在访问共享变量时暂时关闭中断EA 0; val shared_var; EA 1;使用“读-修改-写”原则时特别小心。对于频繁在ISR中更新的标志使用volatile关键字声明防止编译器优化。6. 国赛应试技巧与现场调试策略掌握了技术还需要有好的策略才能在现场比赛中发挥出来。6.1 审题与时间规划前1小时逐字阅读用笔划出所有“必须实现”的功能点、性能指标精度、响应时间、显示格式要求。这些是硬性得分点。划分模块立即在草稿纸上画出系统框图将题目要求映射到具体的硬件模块哪个按键、哪个LED、哪路ADC、显示什么内容。制定计划将4-5小时的比赛时间划分为几个阶段第一阶段1-1.5小时搭建工程框架编写所有底层驱动键盘、ADC、显示、定时器并完成单独测试。确保每个模块的基础功能正常。这是的压舱石这部分不稳后面全垮。第二阶段1.5-2小时实现核心业务逻辑。根据题目要求编写数据处理、状态判断、控制输出的代码。先实现主干功能让系统“跑起来”。第三阶段1小时完善人机交互。实现菜单设置、阈值调整、模式切换等。优化显示界面。第四阶段0.5-1小时整体联调、边界测试、优化稳定性。检查所有得分点撰写必要的注释。6.2 代码编写与调试技巧版本管理每完成一个主要功能或模块就在编译器里另存一个工程副本如Project_V1_Key_LCDProject_V2_With_ADC。当新代码导致系统崩溃时可以快速回退到上一个稳定版本。串口调试法充分利用板载的串口通常连接到CH340芯片。编写一个简单的UART_SendString和UART_SendHex函数。在程序关键位置如按键中断、ADC采样完成、状态切换时发送调试信息到电脑串口助手。这是定位问题最快的方法。LED调试法如果串口来不及准备用开发板上富余的LED来指示程序状态。例如让一个LED在主循环中闪烁表示程序活着另一个LED在定时器中断中翻转表示中断正常第三个LED在按键按下时亮起。分段编译不要一次性写几百行代码再编译。写一小段编译一次确保没有语法错误。特别是复杂的函数或中断服务程序。6.3 常见硬件问题快速排查比赛现场提供的开发板可能被频繁使用存在接触不良或隐性故障。LCD/OLED不显示检查对比度调节电位器如果有。用万用表检查背光电压。检查数据/命令引脚顺序是否与代码中一致。尝试降低通信速度如果程序支持。按键失灵或连击检查上拉电阻是否正常。检查矩阵键盘的行列线定义是否与代码扫描顺序匹配。务必加入消抖程序并现场调整消抖时间。ADC采样值不准或不变化检查参考电压源Vref是否稳定。检查模拟输入通道选择是否正确。测量实际输入电压与ADC读数换算后的电压对比。尝试对地并一个小电容104滤波。继电器LED模拟不动作检查三极管或驱动芯片的驱动电路是否正确。检查控制IO口模式准双向口即可和初始化电平。直接用杜邦线将IO口接到LED上看是否能点亮以区分是软件问题还是硬件问题。6.4 客观题备考要点国赛通常包含客观题选择题/填空题考察单片机基础知识、C语言、电路常识。复习核心C语言指针、数组、结构体、位运算、宏定义。尤其注意const、static、volatile关键字的含义。单片机结构IAP15F2K61S2的存储器结构ROM/RAM/EEPROM、特殊功能寄存器SFR、中断系统优先级、向量号、定时器/计数器工作模式、串口通信波特率计算。电路基础上拉/下拉电阻、LED限流电阻计算、三极管开关电路、运算放大器基本应用、ADC/DAC原理。通信协议I2C、SPI、单总线如DS18B20的时序图解读。答题技巧客观题往往考细节。遇到时序图题静下心来对照高低电平变化和时钟边沿遇到计算题如定时器初值、波特率把公式在草稿纸上列出来再计算遇到代码分析题注意变量的作用域和生命周期。回顾第十届乃至任何一届蓝桥杯单片机国赛真题其核心考察的从来不是某个奇技淫巧而是扎实的硬件驱动能力、清晰的系统设计思维、稳健的代码实现习惯以及临场的问题解决能力。通过这种“解剖式”的真题复盘我们真正要掌握的是一套应对嵌入式系统开发的通用方法论从需求分析到模块设计从驱动抽象到任务调度从状态机建模到系统调试。当你把这些思维和技巧内化后无论题目如何变化你都能从容地拆解它、实现它、优化它。这才是备战国赛带给你的比奖状更重要的财富。
返回列表