
1. 从零拆解这个练习到底在练什么很多人看到“双色球随机号码生成与下注对比”这个题目第一反应是“这不就是个随机数练习吗”。我刚开始带新人的时候也这么想过直到自己动手写了一遍才发现这个题目表面上是在练数组和循环实际上它是一道非常精巧的综合能力检测题。它把随机数生成、数组操作、集合运算、排序、边界条件处理、用户输入校验这几个编程基本功全部串在了一起而且每一个环节都有坑。先把这个练习的需求说清楚。双色球这个玩法大家应该都听说过它的号码结构是红球加蓝球红球从1到33里面选6个不重复的数字蓝球从1到16里面选1个数字。一注完整的号码就是“6个红球 1个蓝球”的组合。这个练习要做的事情分两块第一块是让程序随机生成若干注号码模拟“机选”第二块是让用户输入自己下注的号码然后跟开奖号码做对比判断中了几个红球、蓝球有没有中最后给出对应的奖级。为什么说它适合练手因为它涉及的数组操作非常典型。红球需要一个长度为6的数组来存蓝球单独一个变量或者长度为1的数组。生成随机号码的时候要保证6个红球互不重复这就涉及到了数组的查找和去重逻辑。对比号码的时候又要拿用户的红球数组去跟开奖的红球数组逐个比对统计命中个数这又是典型的数组遍历和计数操作。可以说数组的增、查、遍历、排序这几个核心操作在这个练习里全都能练到。再说循环逻辑。生成不重复的随机数最朴素的做法就是“生成一个、检查是否已存在、如果存在就重新生成”这本身就是一个循环嵌套循环的结构。外层循环控制生成6个红球内层循环负责去重检查。对比号码的时候用户的红球要跟开奖红球逐一比对这是双层循环。如果你想把用户输入的号码排序后再显示那还得写一个排序循环。所以这个练习对循环的训练是相当全面的尤其是循环的终止条件和嵌套循环的控制新手最容易在这里写出死循环或者逻辑漏洞。我个人的看法是这个练习的价值不在于写出一个能跑的版本而在于你能不能写出一个健壮的、边界情况都考虑到的版本。什么叫健壮比如用户输入了重复的红球怎么办用户输入了超出范围的数字怎么办用户输入了非数字字符怎么办随机生成的号码要不要排序对比结果怎么呈现才清晰这些问题在题目描述里可能没有明确写出来但一个合格的从业者在实际开发中一定会遇到也一定会去处理。这篇博文就是要把这些细节全部拆开让你不仅会写还能写得漂亮。适合谁来参考如果你是刚学完数组和循环的初学者这个练习是绝佳的巩固材料我会从最基础的思路开始讲每一步都解释清楚为什么这么做。如果你已经有一定基础可以重点关注后面的去重算法优化、边界条件处理和代码结构设计部分这些是区分“能跑”和“写得好”的关键。整个练习我会用Python来演示因为它的语法足够简洁能把注意力集中在逻辑本身而不是语法细节上但思路是通用的你用Java、C、JavaScript都能照着实现。2. 核心设计思路与方案选型2.1 为什么选择“数组循环”作为核心骨架这个练习的底层数据结构选择其实没有太多悬念数组或者叫列表是最自然的选择。红球有6个数字蓝球有1个数字用数组来存是最直观的。但这里有一个值得思考的问题红球数组到底应该存什么是存用户输入的原始顺序还是存排序后的顺序我见过很多初学者写的版本用户输入什么顺序就存什么顺序对比的时候也是按原始顺序去比。这样做逻辑上没错但显示结果的时候会很乱。比如开奖号码是“01 05 12 18 25 30”用户输入的是“30 01 25 05 18 12”虽然红球全中但显示出来两排数字顺序完全不一样看起来就不太直观。所以我的建议是无论是开奖号码还是用户号码生成或输入之后都统一做一次排序这样对比和展示都会清晰很多。排序本身也是一个循环练习一举两得。另一个设计决策是蓝球要不要单独处理。有些实现会把蓝球也塞进红球数组里变成7个元素的数组前6个是红球最后1个是蓝球。这样做的好处是只需要管理一个数组但坏处是逻辑上不够清晰对比的时候还要特别小心下标。我更推荐红球和蓝球分开存储红球用一个长度为6的数组蓝球用一个单独的整数变量。这样在对比的时候红球走红球的逻辑蓝球走蓝球的逻辑互不干扰代码可读性更高。2.2 随机数去重最容易被低估的难点生成6个不重复的随机红球这是整个练习里第一个真正的难点。很多人第一反应是写一个循环每次生成一个随机数然后检查这个数是否已经在数组里了如果不在就放进去如果在就重新生成。这个思路是对的但实现的时候有几个细节要注意。第一个细节是循环的终止条件。你不能用“循环6次”来作为终止条件因为如果某一次生成的数字重复了你重新生成那这一次循环就浪费了最终数组里可能不足6个数字。正确的做法是用一个while循环条件是“数组长度小于6”只要数组还没满6个就继续生成。每次生成一个数字后检查它是否已经在数组里如果不在就追加进去如果在就跳过继续下一轮循环。这样无论中间重复多少次最终一定能凑满6个不重复的数字。第二个细节是随机数的范围。红球是1到33所以随机数应该是random.randint(1, 33)这个函数是包含两端的也就是能取到1和33。蓝球是1到16用random.randint(1, 16)。这里千万不要写成random.randint(0, 33)或者random.randint(1, 32)范围写错了整个号码就全错了。第三个细节是去重检查的效率。用in操作符来检查一个数字是否在数组里在数组长度只有6的时候完全没问题性能可以忽略不计。但如果你想练一练算法思维可以思考一下如果红球范围是1到100万要选50万个不重复的数字那用in逐个检查就会非常慢。这时候更好的做法是用一个布尔标记数组或者集合来记录哪些数字已经被选过了。不过对于这个练习来说数组长度只有6用in就够了不需要过度设计。2.3 对比逻辑的两种实现路径对比用户号码和开奖号码统计红球命中个数这个逻辑有两种常见的实现方式。第一种是双层循环暴力比对外层遍历用户的红球内层遍历开奖的红球如果发现相等的就计数器加一。这种方式的优点是逻辑简单直接缺点是时间复杂度是O(n²)不过n只有6所以性能上完全无所谓。第二种方式是利用集合Set的交集运算。把用户的红球和开奖的红球都转成集合然后求交集交集的长度就是命中个数。这种方式代码更简洁一行就能搞定但前提是你得理解集合这个数据结构。对于初学者来说我建议先用双层循环实现一遍理解对比的本质然后再用集合的方式优化体会一下不同数据结构的表达力。蓝球的对比就简单多了直接判断两个整数是否相等就行。如果相等蓝球命中如果不相等蓝球没中。2.4 奖级判断规则要理清楚双色球的奖级规则是这样的一等奖是6红1蓝二等奖是6红0蓝三等奖是5红1蓝四等奖是5红0蓝或者4红1蓝五等奖是4红0蓝或者3红1蓝六等奖是2红1蓝、1红1蓝或者0红1蓝。这个规则看起来有点复杂但用代码实现的时候其实就是一串if-else判断。我建议把奖级判断写成一个独立的函数输入是红球命中个数和蓝球是否命中输出是奖级描述。这样做的好处是逻辑清晰而且如果以后规则变了只需要改这一个函数就行。写if-else的时候要注意判断顺序先从最高奖级开始判断因为一等奖的条件最严格如果先判断六等奖那6红1蓝也会满足“蓝球命中”的条件就会被错误地判成六等奖。所以顺序一定是先判断61再判断60再判断51以此类推从高到低依次判断。3. 核心细节解析与实操要点3.1 随机号码生成的完整实现与逐行解读先来看随机生成一注号码的完整代码。我会把每一行的意图都解释清楚这样你不仅能抄还能理解为什么这么写。import random def generate_one_ticket(): red_balls [] while len(red_balls) 6: num random.randint(1, 33) if num not in red_balls: red_balls.append(num) red_balls.sort() blue_ball random.randint(1, 16) return red_balls, blue_ball这段代码虽然短但每一行都有讲究。red_balls []初始化一个空数组用来存放红球。while len(red_balls) 6是循环条件只要数组里不足6个数字就继续循环。num random.randint(1, 33)生成一个1到33之间的随机整数。if num not in red_balls检查这个数字是否已经在数组里了如果不在就append进去如果在就什么都不做进入下一轮循环。这里用not in来判断是Python里非常简洁的写法其他语言可能需要写一个循环来逐个比对。red_balls.sort()这一行是我强烈建议加上的。虽然不加也不影响功能但加上之后号码会按从小到大排列显示出来更符合人们的阅读习惯。双色球的开奖号码通常也是按升序排列的所以排序之后你的输出会更专业。blue_ball random.randint(1, 16)生成蓝球范围是1到16。最后用return把红球数组和蓝球一起返回。注意这里返回的是一个元组包含一个列表和一个整数调用的时候可以用red, blue generate_one_ticket()来解包。注意random.randint(a, b)是包含b的也就是说random.randint(1, 33)有可能生成33。如果你用的是其他语言比如Java的Random.nextInt(33)它生成的是0到32需要加1才能变成1到33。这个差异一定要搞清楚否则号码范围就错了。3.2 用户输入处理别让程序因为一个空格就崩溃用户输入这部分是新手最容易忽略健壮性的地方。很多人写的代码是这样的user_red [] for i in range(6): num int(input(请输入第{}个红球.format(i1))) user_red.append(num)这段代码能跑但用户只要输入一个字母、一个空格、或者一个超出范围的数字程序就直接报错退出了。在实际使用中这是不可接受的。我们需要做输入校验确保用户输入的是合法的数字而且在正确的范围内而且没有重复。我的做法是写一个专门的输入函数把校验逻辑封装起来def input_red_balls(): red_balls [] while len(red_balls) 6: try: num int(input(请输入第{}个红球1-33.format(len(red_balls)1))) except ValueError: print(输入无效请输入一个整数。) continue if num 1 or num 33: print(红球范围是1到33请重新输入。) continue if num in red_balls: print(这个红球已经输入过了请换一个。) continue red_balls.append(num) red_balls.sort() return red_balls这段代码用try-except捕获了int()转换失败的情况如果用户输入的不是整数就提示重新输入。然后检查范围再检查是否重复。只有三个检查都通过了才会把数字加入数组。while len(red_balls) 6保证了不管中间有多少次无效输入最终一定能收集到6个合法的红球。蓝球的输入类似但不需要去重检查因为蓝球只有一个def input_blue_ball(): while True: try: num int(input(请输入蓝球1-16)) except ValueError: print(输入无效请输入一个整数。) continue if num 1 or num 16: print(蓝球范围是1到16请重新输入。) continue return num提示输入校验这部分代码看起来有点啰嗦但它是区分“玩具代码”和“可用代码”的分水岭。我建议你在练习的时候就养成写校验的习惯以后做任何涉及用户输入的功能都会受益。3.3 对比逻辑的实现与优化对比逻辑的核心是统计红球命中个数和判断蓝球是否命中。先用最直观的双层循环来实现def compare_tickets(user_red, user_blue, win_red, win_blue): red_hit 0 for u in user_red: for w in win_red: if u w: red_hit 1 break blue_hit (user_blue win_blue) return red_hit, blue_hit外层循环遍历用户的每一个红球内层循环遍历开奖的每一个红球如果发现相等计数器加一然后break跳出内层循环。这里的break很重要因为如果不跳出同一个用户红球可能会跟多个开奖红球匹配虽然在这个场景下不会因为开奖红球本身不重复但养成“找到就跳出”的习惯是好的。蓝球的判断更简单直接比较两个整数是否相等结果是一个布尔值。如果用集合来实现代码会更简洁def compare_tickets_set(user_red, user_blue, win_red, win_blue): red_hit len(set(user_red) set(win_red)) blue_hit (user_blue win_blue) return red_hit, blue_hitset(user_red) set(win_red)求的是两个集合的交集交集的长度就是共同元素的个数也就是红球命中个数。一行代码搞定非常优雅。但前提是你得理解集合的语义知道是求交集。对于初学者来说我建议两种方式都写一遍对比一下体会一下不同数据结构的表达力。3.4 奖级判断的完整规则表奖级判断用if-else链来实现顺序从高到低def get_prize_level(red_hit, blue_hit): if red_hit 6 and blue_hit: return 一等奖 elif red_hit 6 and not blue_hit: return 二等奖 elif red_hit 5 and blue_hit: return 三等奖 elif (red_hit 5 and not blue_hit) or (red_hit 4 and blue_hit): return 四等奖 elif (red_hit 4 and not blue_hit) or (red_hit 3 and blue_hit): return 五等奖 elif blue_hit and red_hit 2: return 六等奖 else: return 未中奖为了更清晰地展示规则我整理了一个表格奖级红球命中蓝球命中说明一等奖6是最高奖级二等奖6否红球全中蓝球未中三等奖5是差一个红球四等奖5否或者4红1蓝四等奖4是与5红0蓝同级五等奖4否或者3红1蓝五等奖3是与4红0蓝同级六等奖0-2是只要蓝球中就有奖未中奖其他否蓝球没中且红球不足3个这个表格建议你打印出来贴在显示器旁边写代码的时候对照着看不容易漏掉情况。特别注意四等奖和五等奖都有两种组合方式写if条件的时候要用or连接起来。4. 完整实操流程与代码实现4.1 项目结构设计与模块划分在动手写代码之前先想清楚整个程序的结构。我习惯把功能拆成独立的函数每个函数只做一件事。这样代码好读、好改、好测试。这个练习我拆成了以下几个函数generate_one_ticket()随机生成一注号码返回红球数组和蓝球input_red_balls()处理用户红球输入带校验input_blue_ball()处理用户蓝球输入带校验compare_tickets()对比两组号码返回命中情况get_prize_level()根据命中情况判断奖级format_ticket()把号码格式化成易读的字符串main()主流程控制这种拆分方式的好处是每个函数都可以单独测试。比如你可以先测试generate_one_ticket()能不能正确生成6个不重复的红球再测试输入函数能不能正确处理非法输入最后再组装起来。如果全部写在一个大函数里出了问题很难定位。4.2 号码格式化输出让结果一目了然号码的显示格式很重要。双色球的号码通常写成两位数字比如“01”而不是“1”这样看起来整齐。红球和蓝球之间用竖线或者加号分隔。我写了一个格式化函数def format_ticket(red_balls, blue_ball): red_str .join({:02d}.format(n) for n in red_balls) blue_str {:02d}.format(blue_ball) return {} {}.format(red_str, blue_str){:02d}.format(n)的意思是格式化为两位整数不足两位前面补零。比如1会变成“01”33还是“33”。 .join(...)把6个红球用空格连接起来。最后用“ ”连接红球和蓝球输出效果就是“01 05 12 18 25 30 07”这样的格式非常清晰。4.3 主流程的完整实现把上面所有函数组装起来主流程是这样的def main(): print( * 40) print(欢迎使用双色球模拟程序) print( * 40) # 生成开奖号码 win_red, win_blue generate_one_ticket() print(\n开奖号码已生成先不告诉你) # 用户输入下注号码 print(\n请输入你的下注号码) user_red input_red_balls() user_blue input_blue_ball() # 显示用户号码 print(\n你的号码, format_ticket(user_red, user_blue)) # 揭晓开奖号码 print(开奖号码, format_ticket(win_red, win_blue)) # 对比 red_hit, blue_hit compare_tickets(user_red, user_blue, win_red, win_blue) print(\n红球命中{} 个.format(red_hit)) print(蓝球命中{}.format(是 if blue_hit else 否)) # 判断奖级 level get_prize_level(red_hit, blue_hit) print(奖级{}.format(level)) if __name__ __main__: main()这个主流程的逻辑很清晰先生成开奖号码但不显示然后让用户输入号码输入完成后先显示用户的号码再揭晓开奖号码最后对比并给出结果。这个顺序是有意设计的先让用户输入完再揭晓模拟了真实的购买和开奖流程体验更好。4.4 批量机选一次生成多注号码有时候我们想一次机选多注号码比如买5注。这个功能很容易扩展只需要在generate_one_ticket()外面套一个循环def generate_multiple_tickets(count): tickets [] for i in range(count): red, blue generate_one_ticket() tickets.append((red, blue)) return tickets然后显示的时候遍历这个列表给每注编号tickets generate_multiple_tickets(5) for i, (red, blue) in enumerate(tickets, 1): print(第{}注{}.format(i, format_ticket(red, blue)))enumerate(tickets, 1)的意思是遍历列表同时给出索引索引从1开始。这样输出就是“第1注...”、“第2注...”这样很直观。4.5 参数计算与边界验证这个练习里涉及到的参数其实不多但每一个都要验证清楚。红球范围是1到33蓝球范围是1到16红球数量是6个蓝球数量是1个。这些数字在代码里出现了多次我建议用常量来定义而不是到处写魔法数字RED_MIN 1 RED_MAX 33 RED_COUNT 6 BLUE_MIN 1 BLUE_MAX 16这样如果以后规则变了比如红球范围变成1到35只需要改这几个常量就行不用满代码去找哪里写了33。这是一个很好的编程习惯建议从练习阶段就养成。验证的时候我一般会做几组测试测试场景输入预期结果正常输入6个不重复的1-33数字正常接受红球重复输入两个相同的数字提示重复要求重新输入红球超范围输入0或34提示范围错误非数字输入输入字母a提示输入无效蓝球超范围输入17提示范围错误蓝球正常输入1-16正常接受把这些边界情况都测一遍确保程序不会崩溃这是最基本的质量保证。5. 常见问题与排查技巧实录5.1 随机数去重相关的坑问题一生成的号码不足6个。这是最常见的bug。如果你用for i in range(6)来循环然后在循环里做去重检查当生成的数字重复时你可能会用continue跳过但这样循环次数就浪费了最终数组里可能只有4个或5个数字。正确的做法是用while len(red_balls) 6作为循环条件只要数组没满就继续不管中间重复多少次。问题二死循环。如果你不小心把去重条件写反了比如写成了if num in red_balls: red_balls.append(num)那就会导致重复的数字被加入数组而不重复的数字被跳过最终数组里全是重复数字而且永远凑不满6个不重复的程序就卡死了。排查的时候可以在循环里加一句print(len(red_balls))看看数组长度有没有在增长。问题三随机数范围写错。有人写random.randint(0, 33)结果生成了0但双色球红球最小是1。或者写random.randint(1, 32)结果永远生成不了33。这种错误很隐蔽因为大部分情况下生成的号码看起来是正常的只有偶尔出现边界值的时候才会暴露。建议在生成之后加一个断言assert 1 num 33如果越界就立刻报错。5.2 输入校验相关的坑问题四用户输入非数字导致程序崩溃。这是新手代码最常见的问题。int(input())遇到非数字输入会抛出ValueError如果不捕获程序直接退出。解决办法就是用try-except包裹起来捕获异常后提示用户重新输入。问题五用户输入重复红球。有些人只检查了范围忘了检查重复。结果用户输入了“01 01 02 03 04 05”程序也接受了但这样的号码在真实场景中是不合法的。解决办法是在加入数组之前用if num in red_balls检查一下。问题六输入了带空格的字符串。比如用户输入“ 5 ”前后有空格int( 5 )在Python里其实是能正常转换的因为int()会自动去除前后空格。但如果你用的是其他语言可能就需要先trim()一下。这个细节在不同语言里表现不一样要注意。5.3 对比逻辑相关的坑问题七红球命中数统计错误。如果你用双层循环对比但忘了在内层循环匹配成功后break在某些情况下可能会重复计数。虽然在这个场景下开奖红球本身不重复不会出现重复计数但养成“找到就跳出”的习惯是好的。另外如果你用集合求交集要注意集合会自动去重如果用户输入了重复红球虽然我们的输入校验已经阻止了这种情况集合会把重复的去掉导致命中数偏少。问题八蓝球判断写成了赋值。这是一个非常经典的笔误if user_blue win_blue用了单等号而不是双等号。在Python里这会直接报语法错误但在C/C里赋值表达式的值就是被赋的值如果win_blue非零条件就永远为真。排查的时候如果发现蓝球判断永远为真先检查是不是把写成了。问题九奖级判断顺序错误。如果你先判断六等奖蓝球命中那6红1蓝也会满足条件被错误地判成六等奖。正确的顺序一定是从高奖级到低奖级依次判断先判断最严格的条件。5.4 常见问题速查表问题现象可能原因排查方法解决方案号码不足6个循环条件写成了固定次数打印数组长度改用while循环程序卡死去重逻辑写反了打印每次生成的数字检查if条件输入字母崩溃没有捕获ValueError看报错信息加try-except红球重复被接受没有去重检查输入重复数字测试加in检查蓝球判断永远为真把写成了检查代码改成奖级判断错误判断顺序不对用61测试从高到低判断号码显示不整齐没有补零看输出用{:02d}格式化随机数范围错误randint参数写错生成大量号码看边界检查参数5.5 独家避坑技巧第一个技巧是用断言做自检。在生成号码之后加一句assert len(red_balls) 6和assert len(set(red_balls)) 6确保数组长度是6且没有重复。这样如果逻辑有问题程序会立刻报错而不是悄悄生成错误的号码。断言在开发阶段非常有用上线前可以去掉或者保留Python的断言可以通过-O参数禁用。第二个技巧是把随机种子固定下来做测试。random.seed(42)可以让每次运行生成的随机数序列都一样这样调试的时候结果可复现。比如你发现某次生成的号码有问题固定种子后就能反复重现方便定位。测试完成后再把种子那行去掉恢复真正的随机。第三个技巧是用集合来简化去重逻辑。虽然我前面推荐用数组加in检查来练基本功但在实际项目中更高效的做法是用集合red_balls set()然后while len(red_balls) 6: red_balls.add(random.randint(1, 33))。集合的add方法会自动去重不需要手动检查。最后用sorted(red_balls)转回有序列表。这种方式代码更短而且在大数据量下性能更好。第四个技巧是把奖级规则写成配置。如果你想让程序更灵活可以把奖级规则写成一个列表每个元素是一个条件函数和对应的奖级名称然后遍历这个列表找到第一个满足条件的就返回。这样如果规则变了只需要改配置不用改代码逻辑。不过对于这个练习来说if-else链已经足够了不需要过度设计。6. 代码优化与扩展方向6.1 从“能跑”到“好读”的重构当你把基本功能实现之后可以回头看看代码有没有可以优化的地方。我总结了几个重构方向。第一个是消除重复代码。比如红球输入和蓝球输入的校验逻辑很像都是“try-except 范围检查”可以抽成一个通用的input_number(prompt, min_val, max_val)函数红球和蓝球都调用它只是参数不同。这样代码量减少而且如果校验逻辑要改只需要改一个地方。第二个是用数据类来组织号码。Python的dataclass可以很方便地定义一个Ticket类包含red_balls和blue_ball两个字段还可以加上__str__方法来自定义显示格式。这样传递号码的时候就是一个对象而不是两个变量代码更清晰。不过对于初学者来说用元组或者字典也够了不一定要上dataclass。第三个是把常量集中管理。前面提到的RED_MIN、RED_MAX这些常量可以放在一个配置字典或者单独的模块里所有函数都从这里引用。这样如果规则变了只改一个地方。6.2 增加历史记录与统计功能如果你想把这个练习做得更有意思可以加一个历史记录功能。每次生成号码或者用户下注之后把号码和结果存到一个列表里程序退出前可以查看历史记录。更进一步可以统计一下“到目前为止机选了多少注”、“中奖率是多少”、“哪个奖级出现最多”。这些统计功能用数组和循环就能实现是对基础知识的又一次巩固。实现思路是维护一个history列表每次对比完成后把(user_red, user_blue, win_red, win_blue, red_hit, blue_hit, level)作为一个元组追加进去。查看历史的时候遍历这个列表格式化输出。统计的时候用字典来计数比如level_count {}然后level_count[level] level_count.get(level, 0) 1。这些都是很实用的数组和字典操作练习。6.3 模拟多期开奖与概率观察另一个有趣的扩展是模拟多期开奖观察一下各个奖级出现的频率。你可以写一个循环比如模拟10000期每期随机生成开奖号码和用户号码统计各奖级出现次数最后算一下概率。这个练习能让你直观感受到双色球的中奖概率有多低也能练习循环和统计。不过要注意这个模拟只是为了编程练习不要把它当成真实的概率计算。真实的双色球概率是可以用组合数学算出来的比如一等奖的概率是1除以C(33,6)乘以16大约是1/1772万。用程序模拟10000期可能连一个一等奖都遇不到这是正常的。6.4 用面向对象的方式重新实现如果你已经掌握了面向对象编程可以尝试用类来重新组织这个程序。比如定义一个Ticket类表示一注号码一个Lottery类表示开奖和对比的逻辑一个Game类控制整个流程。这样代码的职责更清晰也更容易扩展。不过对于初学者来说函数式的方式已经足够了面向对象是下一步的事情不用急着上。我个人的建议是先用函数式的方式把这个练习写熟确保每一个逻辑都理解透彻然后再用面向对象的方式重写一遍对比两种方式的优缺点。这样你对两种编程范式都会有更深的理解。7. 我的实操体会与几个小建议这个练习我前后写过好几遍每次都有新的收获。最开始写的时候只求能跑后来开始关注边界情况再后来开始关注代码结构和可读性。我发现一个规律越是简单的题目越能看出一个人的基本功。双色球这个题目看起来简单但如果你把输入校验、去重、排序、对比、奖级判断、格式化输出这些细节都做到位代码量其实不小而且每一处都有讲究。我个人的体会是写这种练习的时候不要急着一次写完。先想清楚数据结构再想清楚每个函数的输入输出然后再动手写。写完之后一定要测试边界情况不要只测正常流程。我见过太多人写的代码正常输入没问题一输入非法字符就崩溃这就是没有做边界测试的结果。另外一个小建议是把你写的代码保存下来过一段时间再回头看。你会发现当时觉得写得很好的代码现在看可能有很多可以改进的地方。这种“回头看”的过程就是进步的过程。我自己就保留了很多年前写的练习代码偶尔翻出来看看能明显感觉到自己的成长。最后再分享一个实用的小技巧如果你在调试随机数相关的代码可以把每次生成的号码打印出来观察一下有没有异常。比如连续生成100注号码看看有没有重复的红球组合有没有超出范围的数字。这种“批量测试”的方法比单次测试更容易发现隐藏的bug。