初学者魔方(2.0版)具有3D图形和动画的C#应用程序 VS2022 .NET6

目录

介绍

术语

演示程序

控制按钮

鼠标动作

解决魔方

Cube的3D视图和相机初始化

旋转完整的魔方

用动画旋转立方体的一侧


介绍

最新版本2.0.0是对VS 2022.NET6的升级。

用于求解魔方的算法来自RubiksPlace.com网站How to Solve a Rubik's Cube, Guide for Beginners。并来自Ruwix.com网站如何解决魔方。

可以通过三种不同的方式查看文章和应用程序。

  • 帮助魔方初学者理解求解过程的演示程序。
  • 求解魔方的C#源代码示例。
  • 用于3D图形和动画的WPF C#源代码示例。

您可以在屏幕上玩立方体,也可以打乱自己的真实立方体并绘制屏幕的立方体以匹配您的立方体。然后按下Solve Step按钮,查看一次移动一个块以实现进度所需的旋转步骤。指令在两个相对旋转代码UFRBLD(上、前、右、后、左和下)中给出。并且,颜色代码为YRGOBW(黄色、红色、绿色、橙色、蓝色和白色)。

立方体从白面到黄面逐层求解。每一层都分为角和边缘。主要群体是:

  • 白边
  • 白角
  • 中间层边缘
  • 黄十字
  • 黄色角位置
  • 黄角角方向
  • 黄色边缘

每组分为步骤。每个步骤通常会将一个块移动到其位置。

Visual Studio环境中调试程序时,程序会生成一个跟踪文件RubiksCubeTrace.txt。该文件存储在当前目录中。如果您将目录结构保存在“Downlod source” zip文件(RubiksCube_src.zip)中,则当前目录将为“..\RubiksCube\Work”。如果您想要Visual Studio默认行为,请删除Work文件夹。该文件将保存在“..\RubiksCube\bin\Debug”中。如果您想要不同的工作目录,请转到项目属性中的调试选项卡并将其更改为您的目录。与1.0.0版本相比的变化是项目属性中的工作目录现在是空白的。

术语

可以公平地假设阅读本文的任何人都熟悉魔方。网上有很多关于如何解魔方的文章。这里给出的术语是为那些想要理解代码的人准备的。

立方体由27个方块组成。这些块中有20个是可移动的。六个是固定的,它们的面颜色代表立方体面颜色。一格是不可见的。20个可移动块分为8个角块和12个边缘块。角块有3个可见面,边缘块有2个可见面。立方体有六个面,每面有8个可移动面。总共有48个可移动的面。代码的3D图形部分显示这些块和块面并为其设置动画。代码的解决方案部分,操作块面数。

源代码类可以分为处理立方体在屏幕上的显示的类和解决谜题的类。显示类的名称中有3D。所有其他人都处理旋转面和求解立方体的逻辑。显示的主类是Cube3D,解决方案的主类是Cube

演示程序

要测试演示程序,请创建一个新文件夹,将附加的RubiksCube.exe复制到此文件夹并运行该程序。

控制按钮

侧面旋转:18个按钮可以以90度顺时针、180度或90度逆时针三种方式旋转魔方的六个侧面中的每一个。

朝上:六个颜色按钮可旋转整个立方体,使朝上与所选颜色相匹配。

正面:六个颜色按钮可旋转整个立方体,使正面与所选颜色相匹配。

用户魔方选定颜色:六个颜色按钮用于选择在屏幕上绘制魔方的颜色,以匹配您的真实魔方。在按下User Cube按钮后,这些按钮处于活动状态。请参阅下面的用户多维数据集注释。

求解步骤:按下求解步骤按钮将使程序运行一种算法以将求解推进一个求解步骤。

自动求解:按下自动求解按钮将使程序通过重复求解步骤动作来求解立方体,直到立方体处于求解状态。

保存解决方案:按保存解决方案按钮将把多维数据集的定义和解决方案步骤保存在一个文本文件中。本节末尾给出了此类文件的示例。程序在默认目录中创建SolutionSteps.txt文件。如果有文件,该文件将覆盖现有文件。创建文件后,将调用计算机中用于.txt文件的默认程序。通常它是记事本。如果要永久保存文件,请转到记事本中的另存为并以其他名称保存。立方体定义由六行组成,每个面一行。每条线有八种颜色的可移动面。第一个是左上角。其他的按顺时针顺序排列。解决方案是每个解决方案步骤一行。解决方案有两种方式:正面和正面的相关代码以及颜色代码。

加载解决方案:按下加载解决方案将加载一个立方体定义文本文件。它可以是使用保存解决方案按钮保存的文件。或者,它可以是任何由[]分隔的六行文本文件。每行由八个字母或单词组成。程序读取每个单词的第一个字母。字母必须为WBRGOY大写或小写。

重置:将立方体重置为已解决状态。

加扰:通过执行10次随机旋转来加扰立方体。

撤消:撤消上次旋转。

用户Cube按下用户Cube按钮允许您在屏幕上绘制多维数据集以匹配您的真实多维数据集。确保两个立方体的方向相同。从User Cube Selected Color六个按钮中选择颜色。使用正面和正面按钮旋转屏幕立方体。完成后按结束着色按钮。该程序将检查您是否输入了有效的多维数据集。如果多维数据集无效,将显示错误消息。更正错误并再次按结束着色。如果您不想更正错误,您唯一的选择是重置。

鼠标动作

全立方体旋转:左键单击立方体图片外的屏幕。按住左键并移动它。整个立方体图像将旋转。

一侧旋转:单击要旋转的一侧的任何面。如果单击了一个角面,请再次单击同一侧的其他三个角面中的任何一个。边缘面也是如此。面将旋转以将第一个面带到第二个面的位置。

用户立方体绘画。如果您处于用户立方体绘制模式,则鼠标只能用于绘制面。要旋转立方体,您必须使用Up FaceFront Face按钮。

2017/07/31 20:08:30 
Rubik’s Cube definition
Front  Up
White  Red     [White  Blue   White  Orange Red    Green  Green  Blue  ]
Blue   Yellow  [Orange White  Green  Orange Red    Red    Orange Green ]
Red    Yellow  [White  Yellow White  Red    Blue   Orange Green  White ]
Green  Yellow  [Blue   Yellow Green  Green  Blue   Yellow Red    White ]
Orange Yellow  [Yellow Green  Yellow Orange Yellow White  Yellow Red   ]
Yellow Orange  [Blue   Yellow Red    Red    Orange Blue   Orange Blue  ]
Rubik’s Cube solution steps
White Edges. White Red Edge. Move to position. White, Red, F, Color: R
White Edges. White Green Edge. Move to position. White, Green, L F, Color: O G
White Edges. White Orange Edge. Move to position. White, Orange, D L’ F, Color: Y B’ O
White Edges. White Blue Edge. Move to position. White, Blue, F’, Color: B’
White Corners. White Blue Red Corner. Rotate and move to position. White, Red, D’ F D - F’, Color: Y’ R Y - R’
White Corners. White Blue Orange Corner. Move to position. White, Blue, R’ D’ R, Color: O’ Y’ O
White Corners. White Green Orange Corner. Rotate and move to position. White, Orange, D’ R’ D’ - R, Color: Y’ G’ Y’ - G
White Corners. White Red Green Corner. Rotate and move to position. White, Green, D2 R’ D’ - R, Color: Y2 R’ Y’ - R
Mid Layer Edges. Green Orange Edge. Move to position (remove first step). Yellow, Green, R U’ R’ - U’ F’ U - F, Color: O Y’ O’ - Y’ G’ Y - G
Mid Layer Edges. Blue Red Edge. Move to position (adjust first step). Yellow, Red, U L’ U - L U F - U’ F’, Color: Y B’ Y - B Y R - Y’ R’
Mid Layer Edges. Blue Orange Edge. Move to position (remove first step). Yellow, Blue, L’ U L - U F U’ - F’, Color: O’ Y O - Y B Y’ - B’
Mid Layer Edges. Red Green Edge. Move to position (adjust first step). Yellow, Red, U2 R U’ - R’ U’ F’ - U F, Color: Y2 G Y’ - G’ Y’ R’ - Y R
Yellow Cross. Yellow Green Edge. Move from L shape to cross. Yellow, Green, F U R - U’ R’ F’, Color: G Y O - Y’ O’ G’
Yellow Corners Position. Yellow Red Green Corner. Rotate yellow face to position. Yellow, Red, U2, Color: Y2
Yellow Corners. Yellow Green Orange Corner. Shuffle three yellow corners. Yellow, Blue, L U L’ - U L U2 - L’ U2, Color: O Y O’ - Y O Y2 - O’ Y2
Yellow Corners. Yellow Green Orange Corner. Rotate 3 yellow corners into their place. Yellow, Blue, R’ U’ R - U’ R’ U2 - R U2, Color: R’ Y’ R - Y’ R’ Y2 - R Y2
Yellow Edges. Yellow Blue Edge. Rotate 3 edges to position. Yellow, Orange, R2 U R - U R’ U’ - R’ U’ R’ - U R’, Color: B2 Y B - Y B’ Y’ - B’ Y’ B’ - Y B’
Cube is Solved
Total number of steps: 86

解决魔方

Cube类是控制求解过程的主要类。立方体有六个面。每边有八个可移动的面。总共有48个可移动的面。Cube类有一个由48个整数组成的整数数组(FaceArray),表示可移动的面。Cube类和与Cube类关联的其他类操作这个面数组。有一些方法可以重置数组、加载数组、保存数组、旋转数组、测试数组和求解立方体。

面号为047。下图显示了所有面号。它们具有以下特性。

  • 与角相关的面数是偶数。
  • 与边相关的面数是奇数。
  • 面部颜色(0-白色、1-蓝色、2-红色、3-绿色、4-橙色、5-黄色)从面部编号FaceColor = FaceNo / 8获得。
  • 立方体侧面的面部位置是FacePos = FaceNo % 8。每侧的面部位置从左上角开始,顺时针围绕面部。
  • 当所有面数都等于它们在FaceArray中的位置时,立方体就解决了。FaceArray[FaceNo] == FaceNo

重置。FaceArray重置为已解决状态。

public void Reset()

获取颜色数组。返回面部颜色的整数数组。

public int[] ColorArray {get}

设置颜色数组。该软件测试有效魔方的颜色阵列。如果测试成功,则将颜色数组转换为人脸数组。如果测试失败,将引发ApplicationException

public int[] ColorArray {set}

多维数据集状态测试属性。8个属性可以测试多维数据集的解水平。

public bool AllBlocksInPlace
public bool AllWhiteEdgesInPlace
public bool AllWhiteCornersInPlace
public bool AllMidLayerEdgesInPlace
public bool YellowEdgesInCrossShape
public bool AllYellowEdgesInPlace
public bool AllYellowCornersInPosition
public bool AllYellowCornersInPlace

旋转阵列。FaceArray旋转一次或旋转数组。

public void RotateArray(int RotationCode)
public void RotateArray(int[] RotationSteps)

解决步骤。为了求解立方体,必须重复执行下一个求解步骤方法,直到求解立方体。

// create cube
Cube FullCube = new Cube();

try
    {
    // Load the cube with scrambled color array
    FullCube.ColorArray = ScrambledArray;

    // loop until solved
    For(;;)
        {
        // get next step
        SolutionStep SolveStep = FullCube.NextSolutionStep();

        // cube is solved
        if(SolveStep.StepCode == StepCode.CubeIsSolved) break;

        // perform the rotation steps
        FullCube.RotateArray(SolveStep.Steps);
        }
    }

// exception
catch (Exception Ex)
    {
    // report exception
    }

Cube3D视图和相机初始化

下面的初始化代码创建了一个3D视口、一个魔方的3D模型和一个透视相机。我们立方体的3D模型由Cube3D类表示。Cube3D类创建由Block3D类表示的27个块。每个块创建由BlockFace3D表示的6个块面。每个块面被分成由MashGeometry3D表示的三角形。不可见的块面是黑色的。可见块面具有灰色边缘和魔方六种颜色之一。3D对象的源代码是本文所附源代码的一部分。为了在屏幕上查看立方体,我们创建了一个观察立方体的相机。相机位于立方体的上方和右侧。结果是我们可以看到前脸、上脸和右脸。

<span id="ArticleContent">
// create Viewport3D and add it to CubeGrid parent
CubeViewPort3D = new Viewport3D()
	{
	Name = "mainViewport",
	ClipToBounds = true
	};
CubeGrid.Children.Clear();
CubeGrid.Children.Add(CubeViewPort3D);

// create ModelVisual3D and add it to Viewport3D
ModelVisual3D ModelVisual = new ModelVisual3D();
CubeViewPort3D.Children.Add(ModelVisual);

// create Model3DGroup with white ambiant light and attach it to ModelViual
Model3DGroup ModelGroup = new Model3DGroup();
ModelGroup.Children.Add(new AmbientLight(Colors.White));
ModelVisual.Content = ModelGroup;

// create our rubik's cube and attach it to ViewPort
RubiksCube3D = new Cube3D();
CubeViewPort3D.Children.Add(RubiksCube3D);

// camera position relative to the cube
// camera is looking directly to the cube
double PosZ = Cube3D.CameraDistance * Math.Sin(Cube3D.CameraUpAngle);
double Temp = Cube3D.CameraDistance * Math.Cos(Cube3D.CameraUpAngle);
double PosX = Temp * Math.Sin(Cube3D.CameraRightAngle);
double PosY = Temp * Math.Cos(Cube3D.CameraRightAngle);

// create camera and attach it to ViewPort
CubeViewPort3D.Camera = new PerspectiveCamera(new Point3D(PosX, -PosY, PosZ), 
	new Vector3D(-PosX, PosY, -PosZ), new Vector3D(0, 0, 1), Cube3D.CameraViewAngle);

// full cube motion transformation group allows the program to
// rotate the whole cube in any direction
Transform3DGroup FullCubeMotion = new Transform3DGroup();
RubiksCube3D.Transform = FullCubeMotion;
FullCubeZRotation = new AxisAngleRotation3D(new Vector3D(0, 0, 1), 0);
FullCubeMotion.Children.Add(new RotateTransform3D(FullCubeZRotation));
FullCubeXRotation = new AxisAngleRotation3D(new Vector3D(1, 0, 0), 0);
FullCubeMotion.Children.Add(new RotateTransform3D(FullCubeXRotation));
FullCubeYRotation = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 0);
FullCubeMotion.Children.Add(new RotateTransform3D(FullCubeYRotation));
</span>

旋转完整的魔方

旋转整个立方体非常简单。在初始化期间,我们创建了3AxisAngleRotation3D对象。每个轴一个对象。要旋转立方体,请设置这三个对象的Angle属性。角度以度为单位。该程序将范围保持在-180+180之间。

// rotate the full cube
FullCubeXRotation.Angle = XAngle;
FullCubeYRotation.Angle = YAngle;
FullCubeZRotation.Angle = ZAngle;

用动画旋转立方体的一侧

旋转立方体的一侧是通过将这一侧的所有9个块分组并旋转组来完成的。旋转是使用DoubleAnimation对象完成的。旋转是从零度到旋转角度度数。动画持续时间为RotateDuration90度为0.25秒,180度为0.5

// there are 18 rotation codes 3 for each cube face
// RotateFace 0=white, 1=blue, 2=red, 3=green, 4=orange, 5=yellow
int RotateFace = RotateCode / 3;

// create a transform group
RotateTransformGroup = new Transform3DGroup();

// attach the transform group object to all 9 blocks of the face to be rotated
for(int Index = 0; Index < Cube.BlocksPerFace; Index++)
	{
	RubiksCube3D.CubeFaceBlockArray[RotateFace][Index].Transform = RotateTransformGroup;
	}

// create axis rotation for the transform group
AxisAngleRotation3D AxisRot = new AxisAngleRotation3D(Cube3D.RotationAxis[RotateFace], 0);
RotateTransformGroup.Children.Add(new RotateTransform3D(AxisRot));

// start the animation
// note: AnimationArray is an array of 3 DoubleAnnimation objects.
// The three objects are 90Deg 0.25Sec, 180Deg 0.5Sec, -90Deg 0.25Sec
AxisRot.BeginAnimation(AxisAngleRotation3D.AngleProperty, AnimationArray[RotateCode % 3]);

动画完成后,我们清除上面创建的所有对象。

// clear all block children of the side that was rotated
RotateTransformGroup.Children.Clear();

// rotate the current face array of the cube object
RubiksCube3D.FullCube.RotateArray(RotateCode);

// set the color of all block faces of the cube
RubiksCube3D.SetColorOfAllFaces();

// reset the transform fields of each face that was part of the group
for(int Index = 0; Index < Cube.BlocksPerFace; Index++)
	RubiksCube3D.CubeFaceBlockArray[RotateCode / 3][Index].Transform = null;

https://www.codeproject.com/Articles/1199528/Rubik-s-Cube-for-Beginners-Version-2-0-Csharp-Appl

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LayeredForm : 支持窗体动画特效,透明,可以和LayeredControl实现任意透明效果等。。。包含LayeredWindowForm的功能 支持一部分带有Paint事件的普通控件,但是不能实现普通控件的背景透明效果! 控件类:Controls HotKey:支持全局热键绑定,事件驱动,可以开启和关闭 LayeredButton:按钮控件,支持按钮颜色设置,图片按钮,如果只设置一张正常状态下的按钮图片,则有鼠标移入加亮效果和鼠标按下变暗效果。边框设置,文字效果设置。 LayeredCheckButton:对LayeredButton的扩展,支持状态切换。 LayeredDragBar:支持对父容器的尺寸拖拽调整 LayeredFlashBox:支持透明Flash播放(当前本不可用,请勿使用!) LayeredLabel:对文字的显示,文字效果设置 LayeredListBox:支自定义列表项目,支持横向和纵向滚动,支持平滑滚动。 LayeredPanel:在Layered模式下的容器控件 LayeredPictureBox:支持Gif 播放,支持多张图片合成动画播放。播放Gif时候不要频繁暂停和播放动画,容易导致线程阻塞。 LayeredTextBox:Layered模式下的文本编辑器。支持水印文字设置 LayeredTrackBar:进度条控件,支持图片进度条定义 动画类:Animations 通过设置LayeredForm的Animation.Effect属性来定义窗体动画特效。 包含了以下特效类:BlindWindowEffect、FadeinFadeoutEffect、GradualCurtainEffect、LevelScrollEffect、RandomCurtainEffect、RotateZoomEffect、ThreeDTurn、ZoomEffect 可以通过实现IEffects接口来实现自定义特效 DirectUI类:DirectUI 包含几个DirectUI控件。用于对以上控件的扩展和美化。部分LayeredControl包含DUIControl属性可以向其添加DirectUI控件。支持通过集合编辑器里面添加,只是不能在集合编辑器里面绑定事件,需要手动写代码绑定。通过集合编辑器添加的控件不一定能马上在设计器里看到效果,因为会有图像缓存,可能需要尝试调整控件大小等方式强制控件重绘,就可以看到效果了。 LayeredControl可以支持在普通窗体上使用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值