我正在用 C# 创建一个解决魔方问题的项目。它将魔方的当前状态作为输入,并输出一系列动作以执行使用指定符号解魔方。
Cube 由 6 个长度为 9 的字符串数组组成:
private string[,] CubeState = new string[6,9] {
{ "WHITE", "WHITE", "WHITE", "WHITE", "WHITE", "WHITE", "WHITE", "WHITE", "WHITE"},
{ "BLUE", "BLUE", "BLUE", "BLUE", "BLUE", "BLUE", "BLUE", "BLUE", "BLUE"},
{ "RED", "RED", "RED", "RED", "RED", "RED", "RED", "RED", "RED"},
{ "GREEN", "GREEN", "GREEN", "GREEN", "GREEN", "GREEN", "GREEN", "GREEN", "GREEN"},
{ "ORANGE", "ORANGE", "ORANGE", "ORANGE", "ORANGE", "ORANGE", "ORANGE", "ORANGE", "ORANGE"},
{ "YELLOW", "YELLOW", "YELLOW", "YELLOW", "YELLOW", "YELLOW", "YELLOW", "YELLOW", "YELLOW" } };
你可以把它想象成一个折叠在一起形成立方体的网。
由于我使用的是控制台应用程序而不是 Windows 窗体应用程序,因此我必须通过将每个面写入彼此下方的控制台来表示立方体。我使用以下方法执行此操作PrintCube()
:
public void PrintCube()
{
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 9; j++)
{
Console.Write("--" + CubeState[i,j]);
if (j % 3 == 2 && j != 0)
{
Console.Write("\r\n");
}
}
Console.WriteLine("\r\n");
}
}
这使得求解立方体的标准输出如下:
目前,我正处于编码可以在立方体上执行的每个不同动作的阶段,但我遇到了障碍。
下面是执行操作的代码:
public void PerformOperation(CubeOperations operation)
{
string[,] newCubeState = CubeState;
string tempString;
switch (operation)
{
case CubeOperations.F:
for (int i = 6; i < 9; i++)
{
// Test 1
tempString = CubeState[4, (3 * (i - 6)) + 2];
newCubeState[4, (3 * (i - 6)) + 2] = CubeState[3, i - 6]; //258 012
newCubeState[3, i - 6] = CubeState[2, 3 * (i - 6)]; //012 036
newCubeState[2, 3 * (i - 6)] = CubeState[1, i]; //036 678
newCubeState[1, i] = tempString; //678 258
// Test 2
/*newCubeState[1, i] = CubeState[4, i];
newCubeState[2, i] = CubeState[1, i];
newCubeState[3, i] = CubeState[2, i];
newCubeState[4, i] = CubeState[3, i];*/
}
RotateFaceRight(newCubeState, Rubiks_Cube_Solver.CubeCenters.WHITE);
break;
case CubeOperations.R:
for (int i = 2; i < 9; i += 3)
{
// Test 1
tempString = CubeState[3, i];
newCubeState[3, i] = CubeState[5, 8 - i]; //258 630
newCubeState[5, i - 2] = CubeState[1, 10 - i]; //036 852
newCubeState[1, i] = CubeState[0, i]; //258 258
newCubeState[0, i] = tempString; //258 258
// Test 2
/*newCubeState[0, i] = CubeState[3, i];
newCubeState[1, i] = CubeState[0, i];
newCubeState[5, i] = CubeState[1, i - 2];
newCubeState[3, i - 2] = CubeState[5, i];*/
}
RotateFaceRight(newCubeState, Rubiks_Cube_Solver.CubeCenters.RED);
break;
case CubeOperations.U:
break;
case CubeOperations.L:
break;
case CubeOperations.B:
break;
case CubeOperations.D:
break;
case CubeOperations.FPRIME:
break;
case CubeOperations.RPRIME:
break;
case CubeOperations.UPRIME:
break;
case CubeOperations.LPRIME:
break;
case CubeOperations.BPRIME:
break;
case CubeOperations.DPRIME:
break;
case CubeOperations.F2:
break;
case CubeOperations.R2:
break;
case CubeOperations.U2:
break;
case CubeOperations.L2:
break;
case CubeOperations.B2:
break;
case CubeOperations.D2:
break;
default:
break;
}
CubeState = newCubeState;
}
我正在按顺序对操作进行编码,因此,到目前为止,我只完成了F操作,但我一生都无法弄清楚我在R操作上哪里出错了。
在魔方符号中,我们看到对已解出的立方体的操作R,从白色面朝外,蓝色面朝上,表示以下运动:
握住立方体,白色面朝外,蓝色面朝上。
将红色面顺时针旋转 90 度,使白色面的右侧移到蓝色面上,绿色移到白色上,黄色移到绿色上,蓝色移到黄色上。
执行这两个步骤会导致R操作。
要了解我们需要在代码中做什么才能实现这一点,让我们回到 excel 电子表格。
从白边开始,我们可以看到我们必须改变:
- 白面的索引2、5和 8到绿面的索引2、5 和 8 。
- 蓝脸的索引2、5和 8 分别对应白脸的索引*2、5 和 8*
- 然而,当我们到达黄色面时,由于网络中的面必须“翻转”来连接橙色、蓝色、绿色和红色的面,我们必须更改索引0、3 和 6。这些分别更改为蓝色面上的索引 8、5和 2 。如果您面前有一个立方体,则更容易思考为什么这是真的
- 在绿面上,我们将索引2、5 和 8更改为黄面上的索引 6、3和 0。同样,这是因为我们如何解释网络。
放大 Operation R的代码,我们可以看到我是如何实现这一点的:
case CubeOperations.R:
for (int i = 2; i < 9; i += 3)
{
//Test 1
tempString = CubeState[3, i];
newCubeState[3, i] = CubeState[5, 8 - i]; //258 630
newCubeState[5, i - 2] = CubeState[1, 10 - i]; //036 852
newCubeState[1, i] = CubeState[0, i]; //258 258
newCubeState[0, i] = tempString; //258 258
// Test 2
/*newCubeState[0, i] = CubeState[3, i];
newCubeState[1, i] = CubeState[0, i];
newCubeState[5, i] = CubeState[1, i - 2];
newCubeState[3, i - 2] = CubeState[5, i];*/
}
我在每一行旁边都有注释,说明发生了变化,其中//258 630
表示由newCubeState
索引2、5 和 8表示的面部分别更改为由CubeState
索引 6、3和 0表示的面部。
从上面的二维数组可以看出,第一个索引表示人脸变为[0] = "WHITE", [1] = "BLUE", [2] = "RED",[3] = "GREEN" , [4] = "橙色", [5] = "黄色"
知道了这一点,我们可以这样解释我的代码:
首先,绿色面上的第 2 个索引成为黄色面上的第 6 个索引。[绿色 -> 黄色]
二、黄脸第0个索引变成蓝脸第8个索引[YELLOW -> BLUE]
第三,蓝脸的第二个索引变成了白脸的第二个索引。[蓝色 -> 白色]
第四,白面的第二个索引变成了绿面的第二个索引。[白色-> 绿色]
请注意,由于某些奇怪的原因,即使它们是完全独立的变量,它似乎会影响CubeState[x,y]
我设置的时间newCubeState[i,j] = CubeState[x, y]
,因此,我需要在更改之前使用索引,这导致需要临时变量tempString
,但是,这不是手头的问题在这里。
第五,绿面上的第 5 个索引变成了黄面上的第 3 个索引。[绿色 -> 黄色]
六、黄面第3个索引变成蓝面第5个索引[YELLOW -> BLUE]
第七,蓝脸的第5个索引变成了白脸的第 5 个索引。[蓝色 -> 白色]
第八,白面的第5个索引变成了绿面的第 5 个索引。[白色-> 绿色]
第九,绿面上的第8 个索引变成了黄面上的第 0个索引。[绿色 -> 黄色]
十、黄面第6个索引变成蓝面第2个索引[YELLOW -> BLUE]
第十一,蓝脸的第8个索引变成了白脸的第8个索引。[蓝色 -> 白色]
第十二,白面的第8个索引变成了绿面的第 8 个索引。[白色-> 绿色]
这应该会产生以下输出:
白 - 白 - 绿
白 - 白 - 绿
白 - 白 - 绿
蓝色 - 蓝色 - 白色
蓝色 - 蓝色 - 白色
蓝色 - 蓝色 - 白色
红 - 红 - 红
红 - 红 - 红
红 - 红 - 红
绿色 - 绿色 - 黄色
绿色 - 绿色 - 黄色
绿色 - 绿色 - 黄色
橙色 - 橙色 - 橙色
橙色 - 橙色 - 橙色
橙色 - 橙色 - 橙色
蓝色 - 黄色 - 黄色
蓝色 - 黄色 - 黄色
蓝色 - 黄色 - 黄色
但是,我们看到情况并非如此:
出于某种奇怪的原因,我们看到第3面的第 8 个索引( GREEN)变成了BLUE而不是YELLOW,以及第5面的第 6 个索引( YELLOW)变成了WHITE而不是BLUE。
我不知道为什么会发生这种情况,我将非常感谢您的帮助。
它不应该引起任何问题,但这是我的RotateFaceRight()
方法:
private void RotateFaceRight(string[,] cube, CubeCenters faceCenterColour)
{
string[] face = new string[9];
int faceNumber = (int)faceCenterColour;
for (int i = 0; i < 9; i++)
{
face[i] = cube[(int)faceCenterColour, i];
}
/*
* 012 -> 630
* 345 -> 741
* 678 -> 852
*/
cube[faceNumber, 0] = face[6];
cube[faceNumber, 1] = face[3];
cube[faceNumber, 2] = face[0];
cube[faceNumber, 3] = face[7];
cube[faceNumber, 4] = face[4];
cube[faceNumber, 5] = face[1];
cube[faceNumber, 6] = face[8];
cube[faceNumber, 7] = face[5];
cube[faceNumber, 8] = face[2];
}
我的其余代码在这里:
立方体.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Rubiks_Cube_Solver
{
class Cube
{
private string[,] CubeState = new string[6, 9] {
{ "WHITE", "WHITE", "WHITE", "WHITE", "WHITE", "WHITE", "WHITE", "WHITE", "WHITE"},
{ "BLUE", "BLUE", "BLUE", "BLUE", "BLUE", "BLUE", "BLUE", "BLUE", "BLUE"},
{ "RED", "RED", "RED", "RED", "RED", "RED", "RED", "RED", "RED"},
{ "GREEN", "GREEN", "GREEN", "GREEN", "GREEN", "GREEN", "GREEN", "GREEN", "GREEN"},
{ "ORANGE", "ORANGE", "ORANGE", "ORANGE", "ORANGE", "ORANGE", "ORANGE", "ORANGE", "ORANGE"},
{ "YELLOW", "YELLOW", "YELLOW", "YELLOW", "YELLOW", "YELLOW", "YELLOW", "YELLOW", "YELLOW" } };
private readonly string[] CubeCenters = new string[] { "WHITE", "BLUE", "RED", "GREEN", "ORANGE", "YELLOW" };
private readonly string[] CubeSides = new string[] { "FRONT", "TOP", "RIGHT", "BOTTOM", "LEFT", "BACK" };
public Cube()
{
}
public void PerformOperation(CubeOperations operation)
{
string[,] newCubeState = CubeState;
string tempString;
switch (operation)
{
//Console.WriteLine("{0} -> {1}\nOld Face: {2} Old Item: {3}\nNew Face: {4} New Item: {5}\n\n", newCubeState[3, i], CubeState[5, 8 - i], 5, (8 - i), 3, (i));
case CubeOperations.F:
for (int i = 6; i < 9; i++)
{
// Test 1
tempString = CubeState[4, (3 * (i - 6)) + 2];
newCubeState[4, (3 * (i - 6)) + 2] = CubeState[3, i - 6]; //258 012
newCubeState[3, i - 6] = CubeState[2, 3 * (i - 6)]; //012 036
newCubeState[2, 3 * (i - 6)] = CubeState[1, i]; //036 678
newCubeState[1, i] = tempString; //678 258
// Test 2
/*newCubeState[1, i] = CubeState[4, i];
newCubeState[2, i] = CubeState[1, i];
newCubeState[3, i] = CubeState[2, i];
newCubeState[4, i] = CubeState[3, i];*/
}
RotateFaceRight(newCubeState, Rubiks_Cube_Solver.CubeCenters.WHITE);
break;
case CubeOperations.R:
for (int i = 2; i < 9; i += 3)
{
// Test 1
tempString = CubeState[3, i];
newCubeState[3, i] = CubeState[5, 8 - i]; //258 630
newCubeState[5, i - 2] = CubeState[1, 10 - i]; //036 852
newCubeState[1, i] = CubeState[0, i]; //258 258
newCubeState[0, i] = tempString; //258 258
// Test 2
/*newCubeState[0, i] = CubeState[3, i];
newCubeState[1, i] = CubeState[0, i];
newCubeState[5, i] = CubeState[1, i - 2];
newCubeState[3, i - 2] = CubeState[5, i];*/
}
RotateFaceRight(newCubeState, Rubiks_Cube_Solver.CubeCenters.RED);
break;
case CubeOperations.U:
for (int i = 0; i < 3; i++)
{
// Test 1
tempString = CubeState[4, i];
newCubeState[4, i] = CubeState[0, i]; //012 012
newCubeState[0, i] = CubeState[2, i]; //012 012
newCubeState[2, i] = CubeState[5, i]; //012 012
newCubeState[5, i] = tempString; //012 012
// Test 2
/*newCubeState[0, i] = CubeState[2, i];
newCubeState[2, i] = CubeState[5, i];
newCubeState[5, i] = CubeState[4, i];
newCubeState[4, i] = CubeState[0, i];*/
}
RotateFaceRight(newCubeState, Rubiks_Cube_Solver.CubeCenters.BLUE);
break;
case CubeOperations.L:
for (int i = 0; i < 7; i += 3)
{
// Test 1
tempString = CubeState[0, i];
newCubeState[0, i] = CubeState[1, i]; //036 036
newCubeState[1, i] = CubeState[5, i + 2]; //036 258
newCubeState[5, i + 2] = CubeState[3, i]; //258 036
newCubeState[3, i] = tempString; //036 036
// Test 2
/*newCubeState[0, i] = CubeState[1, i];
newCubeState[1, i] = CubeState[5, i];
newCubeState[5, i] = CubeState[3, i];
newCubeState[3, i] = CubeState[0, i];*/
}
RotateFaceRight(newCubeState, Rubiks_Cube_Solver.CubeCenters.ORANGE);
break;
case CubeOperations.B:
for (int i = 0; i < 3; i++)
{
// Test 1
tempString = CubeState[1, i];
newCubeState[1, i] = CubeState[2, (i * 3) + 2]; //012 258
newCubeState[2, (i * 3) + 2] = CubeState[3, i + 6]; //258 678
newCubeState[3, i + 6] = CubeState[4, (i * 3)]; //678 036
newCubeState[4, (i * 3)] = tempString; //036 012
// Test 2
/*newCubeState[1, i] = CubeState[2, i];
newCubeState[2, i] = CubeState[3, i];
newCubeState[3, i] = CubeState[4, i];
newCubeState[4, i] = CubeState[1, i];*/
}
RotateFaceRight(newCubeState, Rubiks_Cube_Solver.CubeCenters.YELLOW);
break;
case CubeOperations.D:
for (int i = 6; i < 9; i++)
{
// Test 1
tempString = CubeState[2, i];
newCubeState[2, i] = CubeState[0, i]; //678 678
newCubeState[0, i] = CubeState[4, i]; //678 678
newCubeState[4, i] = CubeState[5, i]; //678 678
newCubeState[5, i] = tempString; //678 678
// Test 2
/*newCubeState[0, i] = CubeState[4, i];
newCubeState[2, i] = CubeState[0, i];
newCubeState[5, i] = CubeState[2, i];
newCubeState[4, i] = CubeState[5, i];*/
}
RotateFaceRight(newCubeState, Rubiks_Cube_Solver.CubeCenters.GREEN);
break;
case CubeOperations.FPRIME:
break;
case CubeOperations.RPRIME:
break;
case CubeOperations.UPRIME:
break;
case CubeOperations.LPRIME:
break;
case CubeOperations.BPRIME:
break;
case CubeOperations.DPRIME:
break;
case CubeOperations.F2:
break;
case CubeOperations.R2:
break;
case CubeOperations.U2:
break;
case CubeOperations.L2:
break;
case CubeOperations.B2:
break;
case CubeOperations.D2:
break;
default:
break;
}
CubeState = newCubeState;
}
private void RotateFaceRight(string[,] cube, CubeCenters faceCenterColour)
{
string[] face = new string[9];
int faceNumber = (int)faceCenterColour;
for (int i = 0; i < 9; i++)
{
face[i] = cube[(int)faceCenterColour, i];
}
/*
* 012 -> 630
* 345 -> 741
* 678 -> 852
*/
cube[faceNumber, 0] = face[6];
cube[faceNumber, 1] = face[3];
cube[faceNumber, 2] = face[0];
cube[faceNumber, 3] = face[7];
cube[faceNumber, 4] = face[4];
cube[faceNumber, 5] = face[1];
cube[faceNumber, 6] = face[8];
cube[faceNumber, 7] = face[5];
cube[faceNumber, 8] = face[2];
}
public void PrintCube()
{
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 9; j++)
{
Console.Write("--" + CubeState[i, j]);
if (j % 3 == 2 && j != 0)
{
Console.Write("\r\n");
}
}
Console.WriteLine("\r\n");
}
}
}
}
CubeCenters.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Rubiks_Cube_Solver
{
enum CubeCenters
{
WHITE,
BLUE,
RED,
GREEN,
ORANGE,
YELLOW
}
}
CubeOperations.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Rubiks_Cube_Solver
{
enum CubeOperations
{
F,
R,
U,
L,
B,
D,
FPRIME,
RPRIME,
UPRIME,
LPRIME,
BPRIME,
DPRIME,
F2,
R2,
U2,
L2,
B2,
D2
}
}
程序.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Rubiks_Cube_Solver
{
class Program
{
static void Main(string[] args)
{
Cube cube = new Cube();
cube.PerformOperation(CubeOperations.R);
cube.PrintCube();
Console.ReadLine();
}
}
}