到目前为止,我将采用您的解决方案,并尝试就如何处理它给出一些具体的指示 - 但当然,通常有许多不同的方法可以解决这个问题,所以这绝不是唯一的方法!
第一个关键问题(如您所知!)是您只打印从本月 1 日开始的行的内容,因为这条线:
if days[i] == start_month
坚持当前的整体设计,我们知道我们需要为每一行打印一些东西,所以显然这样的条件是行不通的。让我们尝试删除它。
首先,以数字而不是字符串的形式知道月份从一周中的哪一天开始会更方便,因此我们可以轻松计算与另一天的偏移量。让我们这样做:
# e.g. for 1st July 2021 this was a Thursday, so we get `4`.
start_of_month_weekday = (Date.today - Date.today.mday + 1).cwday
接下来(这也是关键的一步!),我们可以利用上面的信息找出“星期几,星期几?”
这是该计算的第一个版本,到目前为止已合并到您的解决方案中:
require 'date'
days = %w[Mon Tue Wed Thu Fri Sat Sun]
puts " #{Date::MONTHNAMES[Date.today.month]} #{Date.today.year}"
i = 0
# e.g. for 1st July 2021 this was a Thursday, so we get `4`.
start_of_month_weekday = (Date.today - Date.today.mday + 1).cwday
while i < days.size
print days[i]
day_of_month = i - start_of_month_weekday + 2 # !!!
while day_of_month <= 31
print " #{day_of_month}"
day_of_month += 7
end
i += 1
puts
end
这输出:
July 2021
Mon -2 5 12 19 26
Tue -1 6 13 20 27
Wed 0 7 14 21 28
Thu 1 8 15 22 29
Fri 2 9 16 23 30
Sat 3 10 17 24 31
Sun 4 11 18 25
不错!现在我们到了某个地方!
我会让你弄清楚其余的......但这里有一些线索,我接下来要解决的问题:
print " #{day_of_month}"如果天数小于 1,此代码需要打印一个“空格”。这可以通过一个简单的if语句来完成。
- 同样,由于您希望此日历在网格中整齐排列,因此您需要此代码始终打印两个字符宽的东西。
sprintf是你的朋友在这里!查看页面一半左右的“宽度示例”。
- 您已经硬编码
31了该月的天数。当然,这应该是固定的。(使用Date图书馆!)
- 有趣的是,您如何
strftime("%a")在一个地方使用,但在上面一行中却笨拙地构建了日历标题! 查看格式化日期的文档;它非常灵活。我认为您可以使用:Date.today.strftime("%B %Y").
- 如果您想为当月的当天添加一些颜色(或背景颜色?),请考虑执行类似的操作,或使用库来协助。
- 使用
while循环可以正常工作,但非常不可靠。在 99% 的情况下,Ruby 有更好的工具来完成这项工作;这是一种非常有表现力的语言——迭代器为王!(我猜您在 ruby 之前首先学习了另一种语言?看到while循环和/或for循环是您对另一种语言更熟悉的一种死赠品。)while i < days.size您可以使用外部 while 循环()而不是days.each_with_index. 而不是内部的while循环(while j < 31),你可以使用day_of_month.step(31, 7)(这太酷了!!)。