日历拼图算法

日历拼图算法前言一、日历拼图是什么?1. 不带星期2. 带星期二、主要思想三、主要代码1. 定义拼图块2. 定义底板3. 拼图块初始化4. 遍历拼图块找一个解总结前言前几天刷抖音,发现有人在玩日历拼图,看起来还挺好玩的。一个拼图号称能拼出全年365天,于是上某宝一看,还有难度更高一级的,带星期的玩法,于是入手了一个玩。别说,还挺有意思的,就是有点浪费时间,有时候得花半个小时的时间去拼当天的拼图。边玩边想,这个东西其实没什么技术含量,就是暴力法一直尝试,完全可以交给代码来完成。于是上 github 一
摘要由CSDN通过智能技术生成


前言

前几天刷抖音,发现有人在玩日历拼图,看起来还挺好玩的。一个拼图号称能拼出全年365天,于是上某宝一看,还有难度更高一级的,带星期的玩法,于是入手了一个玩。别说,还挺有意思的,就是有点浪费时间,有时候得花半个小时的时间去拼当天的拼图。

边玩边想,这个东西其实没什么技术含量,就是暴力法一直尝试,完全可以交给代码来完成。于是上 github 一搜,果然有大神写了代码,但大神用的是 C++,并且是不带星期的简单玩法。着手改造:

  • 代码全部改成 go
  • 加上星期
  • dfs 剪枝优化
  • 启动 http server
  • 添加前端页面

完整代码地址:
Github 地址:https://github.com/LeoNumber1/calender_puzzle
Gitee 地址:https://gitee.com/leono1/calender_puzzle

线上体验地址:点击体验


一、日历拼图是什么?

【日历拼图】是一款益智游戏,有带星期和不带星期两种。

1. 不带星期

底板为7乘7的格子,去掉右上角的两块和右下角的四块。拼图块总共有8个块,能拼出一年365天的日期。如下所示:
日历拼图简单版

2. 带星期

底板为7乘8的格子,去掉右上角的两块和左下角的四块。拼图块总共有10个块,能拼出365*7的日期。堪称“顶级难度”的日历拼图,据说有2604种拼法,如下所示:

日历拼图困难版

二、主要思想

  1. 初始化底板map;
  2. 底板中加入墙体和日期;
  3. 初始化拼图块puzzle;
  4. 每个拼图块顺时针旋转90°四次,再镜像后顺时针旋转90°四次,将每次的结果去重后保存,得到每个拼图块能拼的所有形状shape;
  5. 遍历每一个拼图块及其形状,在底板上找一个合适的位置放下;检查是否能将其放置在map上的xy位置处,左上角对齐xy,如果能放置,则放置,设置map对应区域;
  6. dfs 剪枝优化,如果有连通区域小于最小拼图块,则回溯;
  7. 重复步骤5,如果发现还有块不能放下,则回溯。直到所有的拼图块都能完美放入底板中。

三、主要代码

1. 定义拼图块

拼图块结构体代码如下:

type Puzzle struct {
   
	ShapeNum   *int // 当前拼图块有多少变种
	X, Y       *int // 当前在图形中,左上角右上角坐标
	ShapeIndex int  // 当前拼图的形状索引
	allShapes  [constant.PUZZLE_NUM]Shape // 所有不同的形状
}

// Shape struct for A block shape
type Shape struct {
   
	Height  int // 当前形状高
	Width   int // 当前形状宽
	MyShape [][]int // 当前形状
}

拼图块变换:

// Rotate 顺时针旋转90度
func (sh Shape) Rotate() Shape {
   
	arr := make([][]int, sh.Width)
	for i := range arr {
   
		arr[i] = make([]int, sh.Height)
		for j := range arr[i] {
   
			arr[i][j] = sh.MyShape[sh.Height-1-j][i]
		}
	}
	return Shape{
   
		Height:  sh.Width,
		Width:   sh.Height,
		MyShape: arr,
	}
}

// Flip 左右镜像翻转
func (sh Shape) Flip() Shape {
   
	arr := make([][]int, sh.Height)
	for i := range arr {
   
		arr[i] = make([]int, sh.Width)
		for j := range arr[i] 
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个使用C语言实现教学日历的示例代码,包括学期时间计算、课程表格生成和课程时间表计算等核心算法: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define MAX_WEEK_DAYS 7 #define MAX_WEEKS 20 // 学期开始日期 struct tm start_date = { .tm_year = 2022 - 1900, .tm_mon = 8, .tm_mday = 1 }; // 学期结束日期 struct tm end_date = { .tm_year = 2023 - 1900, .tm_mon = 0, .tm_mday = 20 }; // 课程表格 const char* course_table[MAX_WEEKS][MAX_WEEK_DAYS] = { {"", "数学", "语文", "", "", "", ""}, {"", "英语", "数学", "音乐", "", "", ""}, {"", "化学", "", "数学", "", "", ""}, {"", "物理", "", "数学", "", "", ""}, {"", "语文", "", "数学", "生物", "", ""}, {"", "英语", "", "化学", "数学", "", ""}, {"", "", "数学", "物理", "", "体育", ""}, {"", "", "语文", "历史", "", "化学", ""}, {"", "", "物理", "英语", "", "数学", ""}, {"", "", "数学", "语文", "", "英语", ""}, {"", "", "英语", "物理", "", "化学", ""}, {"", "", "生物", "数学", "语文", "英语", ""}, {"", "", "", "英语", "数学", "生物", ""}, {"", "", "", "化学", "英语", "历史", ""}, {"", "", "", "数学", "语文", "音乐", ""}, {"", "", "", "物理", "英语", "数学", ""}, {"", "", "", "英语", "数学", "化学", ""}, {"", "", "", "语文", "物理", "数学", ""}, {"", "", "", "数学", "英语", "生物", ""}, {"", "", "", "音乐", "数学", "语文", ""} }; // 根据日期计算周几 int calculate_weekday(struct tm date) { time_t t = mktime(&date); struct tm* tm = localtime(&t); return tm->tm_wday; } // 根据学期日期计算所有日期 void calculate_all_dates(struct tm start_date, struct tm end_date, struct tm** all_dates, int* num_dates) { int diff = difftime(mktime(&end_date), mktime(&start_date)) / 86400; *num_dates = diff + 1; *all_dates = (struct tm*)malloc(sizeof(struct tm) * (*num_dates)); struct tm current_date = start_date; for (int i = 0; i < *num_dates; i++) { (*all_dates)[i] = current_date; current_date.tm_mday++; mktime(&current_date); } } // 生成课程表格 void generate_course_table(struct tm* all_dates, int num_dates) { struct tm current_date; int current_week = 0; int current_weekday = 0; for (int i = 0; i < num_dates; i++) { current_date = all_dates[i]; current_weekday = calculate_weekday(current_date); if (current_weekday == 0) { current_week++; printf("\n第%d周\n", current_week); } printf("%d月%d日 %s\n", current_date.tm_mon + 1, current_date.tm_mday, course_table[current_week - 1][current_weekday]); } } // 计算课程时间表 void calculate_course_timetable(struct tm start_date, struct tm** course_timetable, int num_weeks, int num_weekdays) { *course_timetable = (struct tm*)malloc(sizeof(struct tm) * num_weeks * num_weekdays); struct tm current_date = start_date; int current_week = 0; int current_weekday = 0; for (int i = 0; i < num_weeks * num_weekdays; i++) { (*course_timetable)[i] = current_date; current_weekday++; if (current_weekday >= num_weekdays) { current_week++; current_weekday = 0; } current_date.tm_mday += 7; mktime(&current_date); } } int main() { int num_dates; struct tm* all_dates; calculate_all_dates(start_date, end_date, &all_dates, &num_dates); generate_course_table(all_dates, num_dates); struct tm* course_timetable; calculate_course_timetable(start_date, &course_timetable, MAX_WEEKS, MAX_WEEK_DAYS); free(all_dates); free(course_timetable); return 0; } ``` 该示例代码实现了教学日历的核心算法,包括了学期时间计算、课程表格生成和课程时间表计算等功能。其中,calculate_weekday函数用于根据日期计算周几,calculate_all_dates函数用于根据学期日期计算所有日期,generate_course_table函数用于生成课程表格,calculate_course_timetable函数用于计算课程时间表。通过这些算法,可以实现一个基本的教学日历应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值