第28课:闰年判断器——学习闰年判断逻辑
🎯 本课目标
- 理解闰年的概念和判断规则
- 掌握复合条件判断的运用
- 学会用逻辑运算符组合条件
- 制作完整的闰年判断程序
- 扩展制作日期计算工具
🤔 趣味引入:时间的"秘密"
想象一下:为什么有些年份会多出一天?
- 🌍 地球绕太阳一圈需要365天5小时48分46秒
- 📅 平年只有365天,每年多出约6小时
- ⏰ 每4年累积约24小时,所以2月多一天
- 🎯 但是!整百年份要能被400整除才算闰年
这就是闰年的"秘密"——让日历跟得上地球的脚步!
今天,让我们一起用Python揭开闰年的奥秘!
🔧 第一部分:闰年判断基础
1.1 什么是闰年?
# 闰年基本概念
print("🎯 认识闰年")
print("=" * 50)
print("""
📋 闰年判断规则:
第一条:能被4整除的年份是闰年
例如:2020 ÷ 4 = 505(整除)→ 闰年 ✅
第二条:但不能被100整除
例如:1900 ÷ 100 = 19(整除)→ 不是闰年 ❌
第三条:除非能被400整除
例如:2000 ÷ 400 = 5(整除)→ 是闰年 ✅
总结规则:
能被4整除 AND(不能被100整除 OR 能被400整除)
""")
# 简单判断示例
def is_leap_year_simple(year):
"""简单判断闰年"""
if year % 4 == 0:
if year % 100 == 0:
if year % 400 == 0:
return True
else:
return False
else:
return True
else:
return False
# 测试年份
test_years = [1900, 2000, 2020, 2023, 2024, 2100]
print("📋 闰年测试:")
print("-" * 40)
print(f"{'年份':>6} {'判断':>10} {'结果':>10}")
print("-" * 40)
for year in test_years:
result = is_leap_year_simple(year)
leap_text = "闰年 ✅" if result else "平年 ❌"
print(f"{year:>6}年 {leap_text:>14}")
print("-" * 40)
1.2 优化闰年判断
# 优化闰年判断
print("\n📝 优化闰年判断")
print("=" * 50)
def is_leap_year_v1(year):
"""版本1:使用逻辑运算符"""
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
def is_leap_year_v2(year):
"""版本2:使用条件表达式"""
return (year % 400 == 0) or (year % 4 == 0 and year % 100 != 0)
def is_leap_year_v3(year):
"""版本3:使用calendar模块"""
import calendar
return calendar.isleap(year)
# 对比不同实现
print("📊 三种实现方式对比:")
print("-" * 50)
for year in [1900, 2000, 2020, 2024]:
r1 = is_leap_year_v1(year)
r2 = is_leap_year_v2(year)
r3 = is_leap_year_v3(year)
print(f"{year}年:v1={r1} v2={r2} v3={r3} 结果一致={r1==r2==r3}")
print("\n💡 推荐使用版本2:")
print(" return (year % 400 == 0) or (year % 4 == 0 and year % 100 != 0)")
print(" 既简洁又高效!")
📊 第二部分:闰年判断进阶
2.1 交互式闰年判断器
# 交互式闰年判断器
print("\n🎮 交互式闰年判断器")
print("=" * 50)
def get_leap_year_info(year):
"""获取闰年详细信息"""
is_leap = is_leap_year_v2(year)
info = {
"year": year,
"is_leap": is_leap,
"days_in_year": 366 if is_leap else 365,
"days_in_february": 29 if is_leap else 28,
"next_leap": None,
"previous_leap": None
}
# 查找下一个闰年
next_year = year + 1
while not is_leap_year_v2(next_year):
next_year += 1
info["next_leap"] = next_year
# 查找上一个闰年
prev_year = year - 1
while prev_year > 0 and not is_leap_year_v2(prev_year):
prev_year -= 1
info["previous_leap"] = prev_year if prev_year > 0 else None
return info
# 交互式查询
print("欢迎使用闰年判断器!")
print("=" * 40)
while True:
try:
year_input = input("\n请输入年份(输入0退出):")
year = int(year_input)
if year == 0:
print("👋 再见!")
break
if year < 0:
print("❌ 请输入公元后的年份!")
continue
info = get_leap_year_info(year)
print(f"\n{'='*50}")
print(f"{'📋 闰年分析报告':^50}")
print(f"{'='*50}")
if info["is_leap"]:
print(f"\n✅ {year}年是闰年!")
print(f" 全年有{info['days_in_year']}天")
print(f" 2月有{info['days_in_february']}天")
else:
print(f"\n❌ {year}年是平年")
print(f" 全年有{info['days_in_year']}天")
print(f" 2月有{info['days_in_february']}天")
print(f"\n📅 相邻闰年:")
print(f" 上一个闰年:{info['previous_leap']}")
print(f" 下一个闰年:{info['next_leap']}")
# 计算间隔
if info["is_leap"]:
gap_to_next = info["next_leap"] - year
gap_from_prev = year - info["previous_leap"]
print(f" 距上一个闰年:{gap_from_prev}年")
print(f" 距下一个闰年:{gap_to_next}年")
# 特殊说明
if year % 100 == 0 and year % 400 != 0:
print(f"\n⚠️ 特殊说明:{year}是整百年份但不被400整除")
print(f" 所以虽然是4的倍数,但不是闰年")
except ValueError:
print("❌ 请输入有效的年份!")
2.2 闰年区间查询
# 闰年区间查询
print("\n📈 闰年区间查询")
print("=" * 50)
def find_leap_years(start_year, end_year):
"""查找指定范围内的所有闰年"""
leap_years = []
for year in range(start_year, end_year + 1):
if is_leap_year_v2(year):
leap_years.append(year)
return leap_years
def count_leap_years(start_year, end_year):
"""统计闰年数量"""
leap_years = find_leap_years(start_year, end_year)
return len(leap_years)
def get_leap_year_distribution(start_year, end_year):
"""获取闰年分布统计"""
leap_years = find_leap_years(start_year, end_year)
distribution = {
"total_years": end_year - start_year + 1,
"leap_count": len(leap_years),
"normal_count": (end_year - start_year + 1) - len(leap_years),
"leap_ratio": len(leap_years) / (end_year - start_year + 1) * 100,
"first_leap": leap_years[0] if leap_years else None,
"last_leap": leap_years[-1] if leap_years else None,
"century_leaps": [],
"decades": {}
}
# 统计整百年闰年
for year in leap_years:
if year % 100 == 0:
distribution["century_leaps"].append(year)
# 按年代统计
for year in leap_years:
decade = (year // 10) * 10
if decade not in distribution["decades"]:
distribution["decades"][decade] = []
distribution["decades"][decade].append(year)
return distribution
# 交互式区间查询
print("欢迎使用闰年区间查询系统!")
print("=" * 40)
try:
start = int(input("起始年份:"))
end = int(input("结束年份:"))
if start > end:
print("❌ 起始年份不能大于结束年份!")
elif start < 0:
print("❌ 请输入公元后的年份!")
else:
distribution = get_leap_year_distribution(start, end)
print(f"\n{'='*60}")
print(f"{'📊 闰年区间分析报告':^60}")
print(f"{'='*60}")
print(f"\n📅 统计区间:{start}年 - {end}年")
print(f"📈 总年数:{distribution['total_years']}年")
print(f"✅ 闰年数:{distribution['leap_count']}年")
print(f"❌ 平年数:{distribution['normal_count']}年")
print(f"📊 闰年占比:{distribution['leap_ratio']:.2f}%")
if distribution['first_leap']:
print(f"\n🔝 首个闰年:{distribution['first_leap']}年")
print(f"🔚 末个闰年:{distribution['last_leap']}年")
if distribution['century_leaps']:
print(f"\n🏛️ 整百年闰年:")
for year in distribution['century_leaps']:
print(f" {year}年(能被400整除的特殊闰年)")
# 显示闰年列表
leap_years = find_leap_years(start, end)
if leap_years:
print(f"\n📋 闰年列表:")
# 每行显示10个
for i in range(0, len(leap_years), 10):
row = leap_years[i:i+10]
print(f" {'、'.join(str(y) for y in row)}")
# 按年代显示
print(f"\n📊 年代分布:")
for decade in sorted(distribution['decades'].keys()):
count = len(distribution['decades'][decade])
bar = "█" * count
print(f" {decade}s:{bar} {count}个闰年")
except ValueError:
print("❌ 请输入有效的年份!")
🎯 第三部分:日期计算应用
3.1 月份天数计算器
# 月份天数计算器
print("\n📅 月份天数计算器")
print("=" * 50)
def get_month_days(year, month):
"""获取某月的天数"""
if month < 1 or month > 12:
return None
# 大月(31天)
if month in [1, 3, 5, 7, 8, 10, 12]:
return 31
# 小月(30天)
elif month in [4, 6, 9, 11]:
return 30
# 二月(特殊处理)
elif month == 2:
if is_leap_year_v2(year):
return 29
else:
return 28
def get_month_name(month):
"""获取月份名称"""
month_names = {
1: "一月", 2: "二月", 3: "三月", 4: "四月",
5: "五月", 6: "六月", 7: "七月", 8: "八月",
9: "九月", 10: "十月", 11: "十一月", 12: "十二月"
}
return month_names.get(month, "未知月份")
# 交互式查询
print("欢迎使用月份天数计算器!")
print("=" * 40)
while True:
try:
year = int(input("\n请输入年份(输入0退出):"))
if year == 0:
print("👋 再见!")
break
month = int(input("请输入月份(1-12):"))
if month < 1 or month > 12:
print("❌ 月份应在1-12之间!")
continue
days = get_month_days(year, month)
month_name = get_month_name(month)
leap_text = "闰年" if is_leap_year_v2(year) else "平年"
print(f"\n📋 查询结果:")
print(f" {year}年({leap_text})")
print(f" {month_name}共有{days}天")
# 额外信息
if month == 2:
if days == 29:
print(f" 💡 因为{year}年是闰年,所以2月有29天!")
else:
print(f" 💡 因为{year}年是平年,所以2月有28天!")
# 季度信息
if month <= 3:
quarter = "第一季度"
elif month <= 6:
quarter = "第二季度"
elif month <= 9:
quarter = "第三季度"
else:
quarter = "第四季度"
print(f" 📊 属于{quarter}")
except ValueError:
print("❌ 请输入有效的数字!")
3.2 日期计算器
# 日期计算器
print("\n📆 日期计算器")
print("=" * 50)
class DateCalculator:
"""日期计算器类"""
def __init__(self):
self.month_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
def is_valid_date(self, year, month, day):
"""验证日期是否有效"""
if month < 1 or month > 12:
return False
max_day = self.get_month_days(year, month)
if day < 1 or day > max_day:
return False
return True
def get_month_days(self, year, month):
"""获取某月天数"""
if month == 2:
return 29 if is_leap_year_v2(year) else 28
return self.month_days[month - 1]
def days_in_year(self, year):
"""计算一年的天数"""
return 366 if is_leap_year_v2(year) else 365
def day_of_year(self, year, month, day):
"""计算某天是当年的第几天"""
total = 0
for m in range(1, month):
total += self.get_month_days(year, m)
total += day
return total
def days_between(self, y1, m1, d1, y2, m2, d2):
"""计算两个日期之间的天数"""
# 确保日期有效
if not (self.is_valid_date(y1, m1, d1) and self.is_valid_date(y2, m2, d2)):
return None
# 如果第一个日期更大,交换并返回负值
if (y1, m1, d1) > (y2, m2, d2):
return -self.days_between(y2, m2, d2, y1, m1, d1)
total_days = 0
# 计算整年的天数
for year in range(y1, y2):
total_days += self.days_in_year(year)
# 减去第一年已过的天数,加上第二年已过的天数
total_days -= self.day_of_year(y1, m1, d1)
total_days += self.day_of_year(y2, m2, d2)
return total_days
def get_season(self, month):
"""获取季节"""
if month in [3, 4, 5]:
return "春天 🌸"
elif month in [6, 7, 8]:
return "夏天 🌞"
elif month in [9, 10, 11]:
return "秋天 🍁"
else:
return "冬天 ❄️"
def get_weekday_name(self, year, month, day):
"""获取星期几(使用蔡勒公式)"""
if month < 3:
month += 12
year -= 1
K = year % 100
J = year // 100
h = (day + (13 * (month + 1)) // 5 + K + K // 4 + J // 4 - 2 * J) % 7
weekdays = ["星期六", "星期日", "星期一", "星期二", "星期三", "星期四", "星期五"]
return weekdays[h]
# 使用日期计算器
calc = DateCalculator()
print("欢迎使用日期计算器!")
print("=" * 40)
while True:
print("\n请选择功能:")
print("1. 查询某天是当年第几天")
print("2. 计算两个日期之间的天数")
print("3. 查询某天的星期")
print("4. 退出")
choice = input("\n请选择(1-4):")
if choice == "4":
print("👋 再见!")
break
elif choice == "1":
try:
year = int(input("年份:"))
month = int(input("月份:"))
day = int(input("日期:"))
if calc.is_valid_date(year, month, day):
day_num = calc.day_of_year(year, month, day)
total = calc.days_in_year(year)
remaining = total - day_num
season = calc.get_season(month)
print(f"\n📋 查询结果:")
print(f" {year}年{month}月{day}日")
print(f" 是当年的第{day_num}天")
print(f" 当年还剩{remaining}天")
print(f" 季节:{season}")
else:
print("❌ 无效的日期!")
except ValueError:
print("❌ 请输入有效的数字!")
elif choice == "2":
try:
print("\n📅 第一个日期:")
y1 = int(input("年份:"))
m1 = int(input("月份:"))
d1 = int(input("日期:"))
print("\n📅 第二个日期:")
y2 = int(input("年份:"))
m2 = int(input("月份:"))
d2 = int(input("日期:"))
days = calc.days_between(y1, m1, d1, y2, m2, d2)
if days is not None:
if days >= 0:
print(f"\n📊 从{y1}年{m1}月{d1}日到{y2}年{m2}月{d2}日")
print(f" 相隔{days}天")
# 换算成年月
years = days // 365
months = (days % 365) // 30
remaining_days = (days % 365) % 30
print(f" 约{years}年{months}个月{remaining_days}天")
else:
print(f"\n📊 从{y2}年{m2}月{d2}日到{y1}年{m1}月{d1}日")
print(f" 相隔{-days}天")
else:
print("❌ 无效的日期!")
except ValueError:
print("❌ 请输入有效的数字!")
elif choice == "3":
try:
year = int(input("年份:"))
month = int(input("月份:"))
day = int(input("日期:"))
if calc.is_valid_date(year, month, day):
weekday = calc.get_weekday_name(year, month, day)
season = calc.get_season(month)
print(f"\n📋 查询结果:")
print(f" {year}年{month}月{day}日是{weekday}")
print(f" 季节:{season}")
else:
print("❌ 无效的日期!")
except ValueError:
print("❌ 请输入有效的数字!")
else:
print("❌ 请选择1-4!")
🎮 第四部分:闰年知识问答
4.1 闰年知识问答游戏
# 闰年知识问答游戏
print("\n🎮 闰年知识问答")
print("=" * 50)
import random
def create_quiz():
"""创建题库"""
questions = [
{
"question": "地球绕太阳一圈需要多长时间?",
"options": ["A. 365天", "B. 365天5小时", "C. 366天", "D. 364天"],
"answer": "B",
"explanation": "地球公转周期约为365天5小时48分46秒"
},
{
"question": "闰年2月有多少天?",
"options": ["A. 28天", "B. 29天", "C. 30天", "D. 31天"],
"answer": "B",
"explanation": "闰年2月有29天,平年只有28天"
},
{
"question": "以下哪一年是闰年?",
"options": ["A. 1900年", "B. 2000年", "C. 2100年", "D. 2200年"],
"answer": "B",
"explanation": "2000能被400整除,是闰年;其他整百年不能被400整除"
},
{
"question": "为什么要有闰年?",
"options": [
"A. 为了让日历和季节同步",
"B. 为了多放假一天",
"C. 为了纪念某个事件",
"D. 为了方便计算"
],
"answer": "A",
"explanation": "闰年是为了弥补地球公转周期与日历年的差异"
},
{
"question": "闰年全年有多少天?",
"options": ["A. 364天", "B. 365天", "C. 366天", "D. 367天"],
"answer": "C",
"explanation": "闰年有366天,比平年多一天"
},
{
"question": "以下哪项不是闰年的判断条件?",
"options": [
"A. 能被4整除",
"B. 不能被100整除",
"C. 能被400整除",
"D. 能被2整除"
],
"answer": "D",
"explanation": "能被2整除是所有偶数的特征,不是闰年的特殊条件"
},
{
"question": "下一次闰年是什么时候?",
"options": [
"A. 2024年",
"B. 2025年",
"C. 2026年",
"D. 2027年"
],
"answer": "A",
"explanation": "2024能被4整除,是闰年"
},
{
"question": "一个世纪(100年)中有多少个闰年?",
"options": [
"A. 24个",
"B. 25个",
"C. 20个",
"D. 26个"
],
"answer": "A",
"explanation": "一般情况下每4年一个闰年,但整百年除外,所以一个世纪通常有24个闰年"
}
]
return questions
def run_quiz():
"""运行问答游戏"""
questions = create_quiz()
random.shuffle(questions)
score = 0
total = len(questions)
print("欢迎参加闰年知识问答!")
print(f"共{total}道题,每题10分")
print("=" * 50)
for i, q in enumerate(questions, 1):
print(f"\n📝 第{i}题(10分):")
print(q["question"])
for option in q["options"]:
print(f" {option}")
answer = input("\n请选择(A/B/C/D):").upper()
if answer == q["answer"]:
print("✅ 回答正确!")
score += 10
else:
print(f"❌ 回答错误!")
print(f"正确答案是:{q['answer']}")
print(f"💡 解释:{q['explanation']}")
print(f"📊 当前得分:{score}/{i*10}")
# 显示最终结果
print(f"\n{'='*50}")
print(f"{'🎯 问答结束!':^50}")
print(f"{'='*50}")
percentage = (score / (total * 10)) * 100
print(f"\n📊 最终得分:{score}/{total*10}")
print(f"📈 正确率:{percentage:.0f}%")
if percentage == 100:
print("🏆 满分!你是闰年专家!")
elif percentage >= 80:
print("🌟 优秀!你对闰年很了解!")
elif percentage >= 60:
print("👍 不错!继续学习!")
elif percentage >= 40:
print("💪 加油!多了解闰年知识!")
else:
print("📚 需要多学习哦!")
# 运行问答游戏
run_quiz()
📅 下节课预告
第29课:猜拳游戏V1.0——人机猜拳游戏
下节课你将学习:
- 综合运用条件判断和随机数
- 制作人机对战猜拳游戏
- 实现游戏计分系统
- 添加多轮对战功能
- 优化游戏交互体验
预习思考:
- 猜拳游戏的规则是什么?
- 如何判断胜负?
- 怎么让电脑随机出拳?
💬 给家长的话
亲爱的家长:
今天孩子学习了闰年判断,这是编程中复合条件判断的经典案例。通过这个项目,孩子学会了如何用逻辑运算符组合多个条件来解决实际问题。
孩子今天学会了:
- ✅ 理解闰年的概念和规则
- ✅ 掌握复合条件判断
- ✅ 制作闰年判断程序
- ✅ 计算日期相关问题
- ✅ 制作知识问答游戏
闰年判断的教育价值:
| 能力 | 在项目中的应用 | 培养价值 |
|------|---------------|---------|
| 逻辑思维 | 复合条件判断 | 条件组合 |
| 数学应用 | 取模运算 | 数学思维 |
| 天文知识 | 闰年原理 | 科学素养 |
| 日期计算 | 天数计算 | 实用技能 |
| 游戏设计 | 知识问答 | 寓教于乐 |
您可以这样做:
亲子互动:
- 天文科普:讲解地球公转和闰年的关系
- 日历观察:一起查看日历中的闰年
- 生日计算:计算家人的精确年龄
- 知识竞赛:进行闰年知识问答比赛
温馨提示:
- 闰年是天文和历法的结合
- 复合条件判断是重要的编程技能
- 鼓励孩子探索更多日期相关知识
- 用游戏的方式学习更有效
🏆 今日成就
完成了今天的学习,你:
📅 掌握了闰年判断
🔢 学会了日期计算
🧠 理解了复合条件
🎮 制作了知识问答
📊 分析了闰年分布
挑战任务:
- 制作万年历程序
- 添加节假日计算
- 制作生日倒计时
- 实现农历公历转换
🌟 编程心法
时间是流动的河流
闰年是时间的驿站
每四年一次的调整
让日历跟上地球的脚步
用代码判断闰年
用逻辑理解规律
条件组合是工具
天文知识是智慧
学会判断时间
更要珍惜时间
让每一分每一秒
都过得有意义
这是编程的启示
也是生活的真谛
记住:闰年不只是多了一天,更是人类智慧的体现。用编程理解世界的规律,用技术解决实际问题!
第28课结束。你现在已经是闰年判断专家了!
实践任务:
1. 制作万年历程序
2. 添加更多日期功能
3. 设计闰年知识游戏
4. 探索更多历法知识
下节课,让我们制作猜拳游戏,体验人机对战的乐趣!
第29课见!✊✋✌️