• 【魔方代码】1200行C语言代码实现“魔方”程序,学会它买魔方的钱都省了,拿走不谢~


    嗨!这里是蜜糖~~

    蜜糖相信很多人在学生时期应该都玩过魔方,上大学或者工作之后却玩的很少了,所以今天蜜糖就给大家带来一款与众不同的魔方——代码版魔方,有电脑就能玩~莱茨狗
    在这里插入图片描述
    看到这个你是不是心动了呢,不要急,因为代码比较多,所以我就不贴出来了,结尾放了文件,感兴趣的小伙伴可以自行下载研究,蜜糖这里给大家简单的讲解一下,方便大家理解。
    文字有点难以理解,可以根据代码来进行学习~

    操作方法

    1.鼠标左键拖动能观察不同角度下的魔方。

    2.鼠标右键拖动能拧动魔方。

    简单说明

    这个程序主要讲如何判断哪些面是要展示出来的以及如何判断点在哪个面的哪个小平面上,以及旋转时的逻辑。

    要判断哪些面是要展示出来的,就需要投影面的法向量 m 和每个面的法向量 n,若 m * n 为负数,说明这两个向量夹角为钝角,也就是不用展示出来,反之就要展示出来。

    数学基础就这么两句话,但是要用代码实现出来得有几十行,这里我将魔方 8 个顶点固定住,6 个面的法向量也是固定的,略一计算,我们只需要根据投影面的法向量的 x,y,z 值的正负就能判断 6 个面中哪些面是要展示出来的。

    这里判断正负要注意,c 语言中的浮点数无法表示 0,最接近 0 的浮点数是 2^(-128),因此浮点数的 0 会比 0 略大或者略小,我这里用一个宏 ZERO 表示 0,只要浮点数比这个宏大就是大于 0。

    同时在透视投影中,当观察点没有倾斜一定角度无法看到侧面,这个倾斜的角度的 cos 值为魔方边长的一半除以观察点到投影面的距离。

    也就是当观察点在某一个平面上,就只能看到距离最近的两个点形成的直线,看不到这个平面上的其他点。这时候 ZERO 值就表示能看到侧面的最小 cos 值。魔方数学模型
    判断点在哪个面的哪个小平面上需要建一个模型,不然你不知道一个平面的起点在哪里,也就不能判断每个小平面的位置。

    魔方的 8 个顶点中,头四个表示底部,尾四个表示顶部,逆时针挨个排序,在空间直角坐标系中,魔方中心点为原点,x 轴正方向为右边平面的法向量,也就是 Right 表示的平面,y 轴正方向为后面平面的法向量,也就是 Back 表示的平面,z 轴正方向为上平面的法向量,也就是 Up 平面。用 8 个顶点来表示平面为:

    前面(Front):0、1、5、4

    后面(Back):3、2、6、7

    左面(Left):0、3、7、4

    右面(Right):1、2、6、5

    上面(Up):4、5、6、7

    下面(Down):0、1、2、3

    判断时先根据投影面得到每个魔方面的二维点值,对于魔方面的每个角,可以连接顶点与点中的地方构成一个二维向量 i,再从这个顶点往两边做两个二维向量求这两个二维向量与 i 的夹角余弦值,余弦值可以表示 180 度以内的角的大小,若这两个余弦值有一个比两边向量夹角的余弦值要小,说明点中的点与某条边所形成的夹角比这个顶点的夹角要大,也就是点在平面外。对任意多边形都可以用这个方法判断点是否在平面内,判断次数为多边形顶点的个数。

    判断完点是否在平面内后判断在该平面的位置,每个平面的起点上面已经给出,根据每个平面的起点与点中的位置构成一个向量,起点与两边的向量的 1/3 长度为横纵坐标单位向量。

    这里做个简单的数学计算,a,b 是两个不平行的二维向量,m、n 为常数,m * a + n * b = c,c 为点中的位置与起点构成的二维向量,求出 m、n 就能得到点在平面内的位置。这方法只对平行投影有效,透视投影则将一个面的横纵方向各分为三个平面,判断点在第 m 个横平面的第 n 个纵平面,根据 m,n 值求出点在平面上的坐标。

    旋转时的逻辑比以上两个都要复杂,我的做法是用一个数组保存六个面的颜色,旋转时先画出旋转时的效果,旋转结束后改变颜色数组。

    代码文件

    头文件及宏定义

    #include 
    #include 
    #include 
    #define WIDTH 640						// 窗口宽度
    #define HEIGHT 480						// 窗口高度
    #define PI 3.14159265					// π
    #define SIDE (min(WIDTH, HEIGHT) / 4)	// 正方体边长
    #define GAMEPAD (SIDE / 2)				// 手柄,控制面旋转幅度的量
    #define ZERO 0.1				// 对于浮点数来说的 0 值
    #define PIECE 180						// 将一个 π 分为 PIECE 份
    COLORREF DifferentColor = RGB(193, 181, 62);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    源代码文件

    • 链接:https://pan.baidu.com/s/1QNYjOjRRPQmZF1srOF3VOQ?pwd
    • 提取码:dkjy

    总结

    好了,大家尽情玩耍,可能会有一点点难度,但是蜜糖相信对学编程的你们来说都是小菜一碟,大家都可以尝试研究一下,说不定还能发现新大陆,希望大家可以得到自己想要的知识以及快乐,也希望大家可以给蜜糖一个关注,非常感谢大家!!!

    视频

    还有一个视频版本,希望给予一点小小的赞,鞠躬~!@#@!!
    视频入口:https://www.bilib1500行代码实现一个魔方,学会之后以后买魔方都省了!

    后续蜜糖还会发布更多的项目源码以及学习资料,希望大家可以持续关注,有什么问题可以回帖留言,我尽量回答。
    需要C/C++学习资料以及其他项目的源码的可以加粉丝裙下载【706913185】。想要了解程序员未来的发展有兴趣的也可加群闲聊。希望和大家一起共同学习进步!!!
    在这里插入图片描述

  • 相关阅读:
    Spring AOP实现 | 代理模式分析
    Java8 判空这样写,惊艳,又骚气
    pH响应UV交联壳聚糖水凝胶/氨基葡聚糖基生物杂化水凝胶NMPA-CS壳聚糖水凝胶的制备
    我自己理解的JAVA反射
    【C++笔试强训】第二十八天
    冒泡排序(Bubble Sort)
    大数据ClickHouse进阶(三):TTL深入了解
    RegexBuddy的正则直接运用到QString
    flutter系列之:flutter中常用的GridView layout详解
    第四章 二叉树
  • 原文地址:https://blog.csdn.net/weixin_45713725/article/details/126746970