注册 登录
编程论坛 C语言论坛

[原创] 不到 800 行代码,彻底搞定魔方还原问题

RockCarry 发布于 2018-12-09 21:28, 14273 次点击
今天进展比较顺利,彻底解决了魔方还原问题

总共代码不到 800 行,还原速度在 10s 左右,当然还可以进一步优化。

代码我放到 github 上了:

https://

一些符号的含义:
F - 正面,程序运行后白色的这一面
B - 背面,黄色面
L - 左面,紫色面(标准魔方应该是橙色,但是 windows 控制台无法显示橙色,用紫色替代)
R - 右面,红色面
U - 上面,蓝色面
D - 下面,绿色面


命令说明:

魔方操作命令:
f  - 正面顺时针旋转
f2 - 正面 180 度旋转
f' - 正面逆时针旋转

其他面以此类推:
f2 f' b b2 b' u u2 u' d d2 d' l l2 l' r r2 r'

init  - 魔方复位
rand  - 随机打乱魔方,可以直接 rand 或者 rand n,n 为随机打乱次数
input - 输入魔方状态,按照提示输入即可
solve - 自动还原魔方
help  - 帮助信息
exit  - 退出程序

所有命令都是用小写字母。



数据结构和算法说明:

数据结构方面,每个面都用简单的二维数组来表示。要点是六个面的旋转操作的实现,以及魔方状态的显示,和状态输入。

算法方面,主要是用到了启发式的广度优先搜索。要点在于魔方状态的评估函数,剪枝方法,搜索算法等。

当然,你还得懂魔方。


程序代码量不大,也写得足够精简,可仔细品味。如有不懂可以提问。


[此贴子已经被作者于2018-12-10 11:22编辑过]

46 回复
#2
RockCarry2018-12-09 21:33
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#pragma pack(1)
typedef struct tagCUBE {
    struct tagCUBE *parent;
    char f[3][3];
    char b[3][3];
    char u[3][3];
    char d[3][3];
    char l[3][3];
    char r[3][3];
    char op;
} CUBE;
#pragma pack()

typedef struct {
    int   stride;
    char *buffer;
} LINEITEM;

static void line_rotate90(LINEITEM item[5])
{
    int i, j;
    for (i=0; i<5; i++) {
        int   dst_idx    = (i+0) % 5;
        int   src_idx    = (i+1) % 5;
        char *dst_buf    = item[dst_idx].buffer;
        char *src_buf    = item[src_idx].buffer;
        int   dst_stride = item[dst_idx].stride;
        int   src_stride = item[src_idx].stride;
        for (j=0; j<3; j++) {
            *dst_buf = *src_buf;
            dst_buf += dst_stride;
            src_buf += src_stride;
        }
    }
}

static void surface_rotate90(char buf[3][3])
{
    char tmp[3][3];
    int  i, j;
    memcpy(tmp, buf, sizeof(tmp));
    for (i=0; i<3; i++) {
        for (j=0; j<3; j++) {
            buf[i][j] = tmp[3-j-1][i];
        }
    }
}

static void cube_init(CUBE *c)
{
    memset(c->f, 'w', sizeof(c->f));
    memset(c->b, 'y', sizeof(c->b));
    memset(c->u, 'b', sizeof(c->u));
    memset(c->d, 'g', sizeof(c->d));
    memset(c->l, 'o', sizeof(c->l));
    memset(c->r, 'r', sizeof(c->r));
}

static void cube_f(CUBE *c)
{
    char temp[3];
    LINEITEM lines[5] = {
        { 1,  temp          },
        { 3,  &(c->l[0][2]) },
        { 1,  &(c->d[0][0]) },
        {-3,  &(c->r[2][0]) },
        {-1,  &(c->u[2][2]) },
    };
    line_rotate90(lines);
    surface_rotate90(c->f);
}

static void cube_b(CUBE *c)
{
    char temp[3];
    LINEITEM lines[5] = {
        { 1,  temp          },
        { 3,  &(c->r[0][2]) },
        {-1,  &(c->d[2][2]) },
        {-3,  &(c->l[2][0]) },
        { 1,  &(c->u[0][0]) },
    };
    line_rotate90(lines);
    surface_rotate90(c->b);
}

static void cube_u(CUBE *c)
{
    char temp[3];
    LINEITEM lines[5] = {
        { 1,  temp          },
        { 1,  &(c->l[0][0]) },
        { 1,  &(c->f[0][0]) },
        { 1,  &(c->r[0][0]) },
        { 1,  &(c->b[0][0]) },
    };
    line_rotate90(lines);
    surface_rotate90(c->u);
}

static void cube_d(CUBE *c)
{
    char temp[3];
    LINEITEM lines[5] = {
        { 1,  temp          },
        { 1,  &(c->b[2][0]) },
        { 1,  &(c->r[2][0]) },
        { 1,  &(c->f[2][0]) },
        { 1,  &(c->l[2][0]) },
    };
    line_rotate90(lines);
    surface_rotate90(c->d);
}

static void cube_l(CUBE *c)
{
    char temp[3];
    LINEITEM lines[5] = {
        { 1,  temp          },
        { 3,  &(c->d[0][0]) },
        { 3,  &(c->f[0][0]) },
        { 3,  &(c->u[0][0]) },
        {-3,  &(c->b[2][2]) },
    };
    line_rotate90(lines);
    surface_rotate90(c->l);
}

static void cube_r(CUBE *c)
{
    char temp[3];
    LINEITEM lines[5] = {
        { 1,  temp          },
        { 3,  &(c->u[0][2]) },
        { 3,  &(c->f[0][2]) },
        { 3,  &(c->d[0][2]) },
        {-3,  &(c->b[2][0]) },
    };
    line_rotate90(lines);
    surface_rotate90(c->r);
}

enum {
    CUBE_OP_F,
    CUBE_OP_B,
    CUBE_OP_U,
    CUBE_OP_D,
    CUBE_OP_L,
    CUBE_OP_R,
};

static void (*g_op_tab[])(CUBE *c) = { cube_f, cube_b, cube_u, cube_d, cube_l, cube_r };
static void cube_op  (CUBE *c, int op) { (g_op_tab[op])(c); }
static void cube_rand(CUBE *c, int n ) { while (n-- > 0) cube_op(c, rand() % 6); }

static void cube_render(CUBE *c)
{
    char buffer[9][12] = {0};
    int  i, j;

    HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
    WORD wOldColorAttrs;
    CONSOLE_SCREEN_BUFFER_INFO csbiInfo;

    // save the current color
    GetConsoleScreenBufferInfo(h, &csbiInfo);
    wOldColorAttrs = csbiInfo.wAttributes;

    for (i=0; i<3; i++) for (j=0; j<3; j++) buffer[3+i][3+j] = c->f[i][j];
    for (i=0; i<3; i++) for (j=0; j<3; j++) buffer[3+i][9+j] = c->b[i][j];
    for (i=0; i<3; i++) for (j=0; j<3; j++) buffer[0+i][3+j] = c->u[i][j];
    for (i=0; i<3; i++) for (j=0; j<3; j++) buffer[6+i][3+j] = c->d[i][j];
    for (i=0; i<3; i++) for (j=0; j<3; j++) buffer[3+i][0+j] = c->l[i][j];
    for (i=0; i<3; i++) for (j=0; j<3; j++) buffer[3+i][6+j] = c->r[i][j];

    for (i=0; i<9; i++) {
        for (j=0; j<12; j++) {
            switch (buffer[i][j]) {
            case 'w': case 'W': SetConsoleTextAttribute(h, FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE); break;
            case 'y': case 'Y': SetConsoleTextAttribute(h, FOREGROUND_INTENSITY|FOREGROUND_RED|FOREGROUND_GREEN); break;
            case 'b': case 'B': SetConsoleTextAttribute(h, FOREGROUND_INTENSITY|FOREGROUND_BLUE ); break;
            case 'g': case 'G': SetConsoleTextAttribute(h, FOREGROUND_INTENSITY|FOREGROUND_GREEN); break;
            case 'o': case 'O': SetConsoleTextAttribute(h, FOREGROUND_RED|FOREGROUND_BLUE       ); break;
            case 'r': case 'R': SetConsoleTextAttribute(h, FOREGROUND_INTENSITY|FOREGROUND_RED  ); break;
            }
            printf(buffer[i][j] ? "# " : "  ");
        }
        printf("\n");
    }

    // restore the original color
    SetConsoleTextAttribute(h, wOldColorAttrs);
}

static int cube_check_fcross0(CUBE *cube)
{
    int checklist[][2] = {
        { cube->f[1][1], cube->f[0][1] },
        { cube->f[1][1], cube->f[1][0] },
        { cube->f[1][1], cube->f[1][2] },
        { cube->f[1][1], cube->f[2][1] },
    };
    int value = 0, i;
    for (i=0; i<4; i++) {
        value += (checklist[i][0] == checklist[i][1]);
    }
    return value;
}

static int cube_check_fcross1(CUBE *cube)
{
    int checklist[][2] = {
        { cube->l[1][1], cube->l[1][2] },
        { cube->u[1][1], cube->u[2][1] },
        { cube->r[1][1], cube->r[1][0] },
        { cube->d[1][1], cube->d[0][1] },
    };
    int value = 0, i;
    for (i=0; i<4; i++) {
        value += (checklist[i][0] == checklist[i][1]);
    }
    return value;
}

static int cube_check_fcorners(CUBE *cube)
{
    int checklist[][3][2] = {
        {
            { cube->f[1][1], cube->f[0][0] },
            { cube->l[1][1], cube->l[0][2] },
            { cube->u[1][1], cube->u[2][0] },
        },
        {
            { cube->f[1][1], cube->f[0][2] },
            { cube->u[1][1], cube->u[2][2] },
            { cube->r[1][1], cube->r[0][0] },
        },
        {
            { cube->f[1][1], cube->f[2][0] },
            { cube->l[1][1], cube->l[2][2] },
            { cube->d[1][1], cube->d[0][0] },
        },
        {
            { cube->f[1][1], cube->f[2][2] },
            { cube->r[1][1], cube->r[2][0] },
            { cube->d[1][1], cube->d[0][2] },
        },
    };
    int value = 0, i, j;
    for (j=0; j<4; j++) {
        value++;
        for (i=0; i<3; i++) {
            if (checklist[j][i][0] != checklist[j][i][1]) { value--; break; }
        }
    }
    return value;
}

static int cube_check_medges(CUBE *cube)
{
    int checklist[][2][2] = {
        {
            { cube->l[1][1], cube->l[0][1] },
            { cube->u[1][1], cube->u[1][0] },
        },
        {
            { cube->u[1][1], cube->u[1][2] },
            { cube->r[1][1], cube->r[0][1] },
        },
        {
            { cube->l[1][1], cube->l[2][1] },
            { cube->d[1][1], cube->d[1][0] },
        },
        {
            { cube->r[1][1], cube->r[2][1] },
            { cube->d[1][1], cube->d[1][2] },
        },
    };
    int value = 0, i, j;
    for (j=0; j<4; j++) {
        value++;
        for (i=0; i<2; i++) {
            if (checklist[j][i][0] != checklist[j][i][1]) { value--; break; }
        }
    }
    return value;
}

static int cube_check_bcross(CUBE *cube)
{
    int checklist[][2][2] = {
        {
            { cube->b[1][1], cube->b[0][1] },
            { cube->b[1][1], cube->b[2][1] },
        },
        {
            { cube->b[1][1], cube->b[1][0] },
            { cube->b[1][1], cube->b[1][2] },
        },
    };
    int value = 0, i, j;
    for (j=0; j<2; j++) {
        value += 2;
        for (i=0; i<2; i++) {
            if (checklist[j][i][0] != checklist[j][i][1]) { value -= 2; break; }
        }
    }
    return value;
}

static int cube_check_bsurface(CUBE *cube)
{
    int checklist[][2] = {
        { cube->b[1][1], cube->b[0][0] },
        { cube->b[1][1], cube->b[0][2] },
        { cube->b[1][1], cube->b[2][0] },
        { cube->b[1][1], cube->b[2][2] },
    };
    int value = 0, i;
    for (i=0; i<4; i++) {
        value += (checklist[i][0] == checklist[i][1]);
    }
    if (value == 2) value = 0;
    return value;
}

static int cube_check_bcorners(CUBE *cube)
{
    int checklist[][3][2] = {
        {
            { cube->b[1][1], cube->b[0][2] },
            { cube->l[1][1], cube->l[0][0] },
            { cube->u[1][1], cube->u[0][0] },
        },
        {
            { cube->b[1][1], cube->b[0][0] },
            { cube->u[1][1], cube->u[0][2] },
            { cube->r[1][1], cube->r[0][2] },
        },
        {
            { cube->b[1][1], cube->b[2][0] },
            { cube->r[1][1], cube->r[2][2] },
            { cube->d[1][1], cube->d[2][2] },
        },
        {
            { cube->b[1][1], cube->b[2][2] },
            { cube->l[1][1], cube->l[2][0] },
            { cube->d[1][1], cube->d[2][0] },
        },
    };
    int returned[4] = { 1, 1, 1, 1 };
    int value = 0, flag = 0, i, j;
    for (j=0; j<4; j++) {
        value++;
        for (i=0; i<3; i++) {
            if (checklist[j][i][0] != checklist[j][i][1]) { value--; returned[j] = 0; break; }
        }
    }
    for (i=0; i<4; i++) {
        if (returned[i] && returned[(i+1)%4]) flag = 1;
    }
    return flag ? value : 0;
}

static int cube_check_bedges(CUBE *cube)
{
    int checklist[][2][2] = {
        {
            { cube->u[1][1], cube->u[0][1] },
            { cube->b[1][1], cube->b[0][1] },
        },
        {
            { cube->d[1][1], cube->d[2][1] },
            { cube->b[1][1], cube->b[2][1] },
        },
        {
            { cube->l[1][1], cube->l[1][0] },
            { cube->b[1][1], cube->b[1][2] },
        },
        {
            { cube->r[1][1], cube->r[1][2] },
            { cube->b[1][1], cube->b[1][0] },
        },
    };
    int value = 0, i, j;
    for (j=0; j<4; j++) {
        value++;
        for (i=0; i<2; i++) {
            if (checklist[j][i][0] != checklist[j][i][1]) { value--; break; }
        }
    }
    return value;
}

static int cube_check_state(CUBE *cube, int flag)
{
    int (*pfn_check_tab[])(CUBE* cube) = {
        cube_check_fcross0 ,
        cube_check_fcross1 ,
        cube_check_fcorners,
        cube_check_medges  ,
        cube_check_bcross  ,
        cube_check_bsurface,
        cube_check_bcorners,
        cube_check_bedges  ,
        NULL,
    };
    int value = 0, cur, i;
    for (i=0; pfn_check_tab[i]; i++) {
        if (flag) {
            value += pfn_check_tab[i](cube);
            cur   += 4;
            if (cur >= flag) break;
        } else {
            cur    = pfn_check_tab[i](cube);
            value += cur;
            if (cur != 4) break;
        }
    }
    return value;
}

typedef struct {
    int   open ;
    int   close;
    int   size ;
    CUBE *cubes;
} TABLE;

static int search_table_create(TABLE *table, int size)
{
    table->size  = size;
    table->cubes = malloc(size * sizeof(CUBE));
    return table->cubes ? 0 : -1;
}

static void search_table_destroy(TABLE *table)
{
    if (table->cubes) {
        free(table->cubes);
        table->cubes = NULL;
    }
}

static int is_4same_ops(CUBE *cube)
{
    int curop = cube->op;
    int n     = 0;
    while (cube) {
        if (cube->op == curop) {
            if (++n == 4) {
                return 1;
            }
            cube = cube->parent;
        } else break;
    }
    return 0;
}

static int cut_branch(int newval, int cutval)
{
    return newval < cutval;
}

static CUBE* search(TABLE *table, CUBE *start, int state, char *oplist, int opnum, int cutval)
{
    CUBE *curcube ,*newcube;
    int   newstate, newvalue, i;

    start->parent = NULL;
    start->op     = -1;
    if (cube_check_state(start, 0) >= state) return start;

    // init search table
    table->open  = 0;
    table->close = 0;

    // put original cube into open table
    table->cubes[table->open] = *start;
    table->open++;

    while (table->close < table->open) {
        // check memory usage
        if (table->open + 6 >= table->size - 1) {
            printf("all table memory have been used !\n");
            break;
        }

        // dequeue a cube from open table
        curcube = &(table->cubes[table->close++]);

        // extend cubes check state and put new cubes into open table
        for (i=0; i<opnum; i++) {
            newcube = &(table->cubes[table->open]);
            memcpy (newcube, curcube, sizeof(CUBE));
            cube_op(newcube, oplist[i]);
            newcube->op     = oplist[i];
            newcube->parent = curcube;
            newstate = cube_check_state(newcube, 0    );
            newvalue = cube_check_state(newcube, state);
            if (newstate >= state) { // found
                return newcube;
            }
            if (is_4same_ops(newcube)) {
                continue;
            }
            if (cut_branch(newvalue, cutval)) {
                continue;
            }
            table->open++;
        }
    }
    return NULL;
}

static void print_solve_oplist(CUBE *cube)
{
    static char* optab[] = {
        "F" , "B" , "U" , "D" , "L" , "R" ,
        "F2", "B2", "U2", "D2", "L2", "R2",
        "F'", "B'", "U'", "D'", "L'", "R'",
    };
    char *oplist[256];
    int   last = -1, times = 0, i = 0, n = 0;
    while (cube) {
        if (cube->op >= 0) {
            if (last != cube->op) {
                if (last != -1) {
                    oplist[i++] = optab[last + times * 6];
                }
                last = cube->op;
                times= 0;
            } else {
                times++;
            }
        } else {
            if (last != -1) oplist[i++] = optab[last + times * 6];
        }
        cube = cube->parent;
    }
    printf("\noperation list:\n");
    while (--i >= 0) {
        printf("%s%s%s", oplist[i], i == 0 ? "" : " -> ", ++n % 12 == 0 ? "\n" : "");
    }
    printf("\n");
}

static void cube_solve(CUBE *c)
{
    TABLE t;

    if (search_table_create(&t, 1024*1024*16) != 0) {
        printf("failed to create cube search table !\n");
        return;
    }

    if (1) {
        static char oplisttab[][6] = {
            { CUBE_OP_F, CUBE_OP_U, CUBE_OP_D, CUBE_OP_L, CUBE_OP_R },
            { CUBE_OP_U, CUBE_OP_D, CUBE_OP_L, CUBE_OP_R, CUBE_OP_B },
            { CUBE_OP_B, CUBE_OP_R, CUBE_OP_U },
        };
        static int stepparams[][4] = {
            { 2 , 0, 5, 0 }, //+ fcross0
            { 4 , 0, 5, 2 }, //- fcross0
            { 8 , 0, 5, 2 }, //+-fcross1
            { 9 , 0, 5, 3 }, //+ fcorners
            { 10, 0, 5, 4 }, //..
            { 11, 0, 5, 5 }, //..
            { 12, 0, 5, 5 }, //- fcorners
            { 13, 1, 5, 6 }, //+ medges
            { 14, 1, 5, 6 }, //..
            { 15, 1, 5, 7 }, //..
            { 16, 1, 5, 8 }, //- medges
            { 18, 1, 5, 10}, //+ bcross
            { 20, 1, 5, 11}, //- bcross
            { 21, 1, 5, 11}, //+ bsurface
            { 24, 1, 5, 11}, //- bsurface
            { 26, 2, 3, 12}, //+ bcorners
            { 28, 2, 3, 12}, //- bcorners
            { 32, 2, 2, 12}, //+-bedges
            { 0 , 0, 0, 0 },
        };
        CUBE *start = c;
        CUBE *find  = NULL;
        int   i;
        for (i=0; stepparams[i][0]; i++) {
            find = search(&t, start, stepparams[i][0], oplisttab[stepparams[i][1]], stepparams[i][2], stepparams[i][3]);
            if (find) {
                if (find != start) {
                    start = find;
                    *c    =*find;
                    print_solve_oplist(find);
                    if (stepparams[i][0] != 32) cube_render(c);
                }
            } else {
                printf("can't solve !\n");
                goto done;
            }
        }
        printf("\ncube solved !\n");
    }

done:
    search_table_destroy(&t);
}

static void cube_input(CUBE *c)
{
    char str[256];

    printf("please input F surface of cube:\n");
    scanf("%c %c %c %c %c %c %c %c %c",
        &(c->f[0][0]), &(c->f[0][1]), &(c->f[0][2]),
        &(c->f[1][0]), &(c->f[1][1]), &(c->f[1][2]),
        &(c->f[2][0]), &(c->f[2][1]), &(c->f[2][2]));
    gets(str);

    printf("please input U surface of cube:\n");
    scanf("%c %c %c %c %c %c %c %c %c",
        &(c->u[0][0]), &(c->u[0][1]), &(c->u[0][2]),
        &(c->u[1][0]), &(c->u[1][1]), &(c->u[1][2]),
        &(c->u[2][0]), &(c->u[2][1]), &(c->u[2][2]));
    gets(str);

    printf("please input D surface of cube:\n");
    scanf("%c %c %c %c %c %c %c %c %c",
        &(c->d[0][0]), &(c->d[0][1]), &(c->d[0][2]),
        &(c->d[1][0]), &(c->d[1][1]), &(c->d[1][2]),
        &(c->d[2][0]), &(c->d[2][1]), &(c->d[2][2]));
    gets(str);

    printf("please input L surface of cube:\n");
    scanf("%c %c %c %c %c %c %c %c %c",
        &(c->l[0][0]), &(c->l[0][1]), &(c->l[0][2]),
        &(c->l[1][0]), &(c->l[1][1]), &(c->l[1][2]),
        &(c->l[2][0]), &(c->l[2][1]), &(c->l[2][2]));
    gets(str);

    printf("please input R surface of cube:\n");
    scanf("%c %c %c %c %c %c %c %c %c",
        &(c->r[0][0]), &(c->r[0][1]), &(c->r[0][2]),
        &(c->r[1][0]), &(c->r[1][1]), &(c->r[1][2]),
        &(c->r[2][0]), &(c->r[2][1]), &(c->r[2][2]));
    gets(str);

    printf("please input B surface of cube:\n");
    scanf("%c %c %c %c %c %c %c %c %c",
        &(c->b[0][0]), &(c->b[0][1]), &(c->b[0][2]),
        &(c->b[1][0]), &(c->b[1][1]), &(c->b[1][2]),
        &(c->b[2][0]), &(c->b[2][1]), &(c->b[2][2]));
    gets(str);
}

static void show_help(void)
{
    printf(
        "\n"
        "available commands:\n\n"
        "f f2 f' b b2 b' u u2 u' d d2 d' l l2 l' r r2 r'\n"
        "init rand input solve help exit\n\n"
        "note: all command is case sensitive.\n"
    );
}

int main(void)
{
    char cmd[128];
    char str[256];
    CUBE c;

    // init cube
    cube_init(&c);

    show_help();
    while (1) {
        cube_render(&c);
        printf("command: ");
        scanf("%s", cmd);
        if (strcmp(cmd, "f") == 0) {
            cube_f(&c);
        } else if (strcmp(cmd, "f2") == 0) {
            cube_f(&c); cube_f(&c);
        } else if (strcmp(cmd, "f'") == 0) {
            cube_f(&c); cube_f(&c); cube_f(&c);
        } else if (strcmp(cmd, "b" ) == 0) {
            cube_b(&c);
        } else if (strcmp(cmd, "b2") == 0) {
            cube_b(&c); cube_b(&c);
        } else if (strcmp(cmd, "b'") == 0) {
            cube_b(&c); cube_b(&c); cube_b(&c);
        } else if (strcmp(cmd, "u" ) == 0) {
            cube_u(&c);
        } else if (strcmp(cmd, "u2") == 0) {
            cube_u(&c); cube_u(&c);
        } else if (strcmp(cmd, "u'") == 0) {
            cube_u(&c); cube_u(&c); cube_u(&c);
        } else if (strcmp(cmd, "d" ) == 0) {
            cube_d(&c);
        } else if (strcmp(cmd, "d2") == 0) {
            cube_d(&c); cube_d(&c);
        } else if (strcmp(cmd, "d'") == 0) {
            cube_d(&c); cube_d(&c); cube_d(&c);
        } else if (strcmp(cmd, "l" ) == 0) {
            cube_l(&c);
        } else if (strcmp(cmd, "l2") == 0) {
            cube_l(&c); cube_l(&c);
        } else if (strcmp(cmd, "l'") == 0) {
            cube_l(&c); cube_l(&c); cube_l(&c);
        } else if (strcmp(cmd, "r" ) == 0) {
            cube_r(&c);
        } else if (strcmp(cmd, "r2") == 0) {
            cube_r(&c); cube_r(&c);
        } else if (strcmp(cmd, "r'") == 0) {
            cube_r(&c); cube_r(&c); cube_r(&c);
        } else if (strcmp(cmd, "init") == 0) {
            cube_init(&c);
        } else if (strcmp(cmd, "rand") == 0) {
            gets(str);
            cube_rand(&c, atoi(str) == 0 ? 100 : atoi(str));
        } else if (strcmp(cmd, "input") == 0) {
            cube_input(&c);
        } else if (strcmp(cmd, "solve") == 0) {
            cube_solve(&c);
        } else if (strcmp(cmd, "help") == 0) {
            show_help();
        } else if (strcmp(cmd, "exit") == 0) {
            break;
        } else {
            printf("unsupported command !\n");
        }
        printf("\n");
    }

    return 0;
}



[此贴子已经被作者于2020-3-13 09:23编辑过]

#3
RockCarry2018-12-09 21:34
代码直接贴出来吧

VC 可以编译运行,或者用 mingw 的 gcc 编译都可以
#4
RockCarry2018-12-09 21:46
只有本站会员才能查看附件,请 登录

编译好的测试程序
#5
幻紫灵心2018-12-09 22:02
有点强啊
#6
yyglxc2018-12-10 06:33
厉害!看看学习一下!
#7
zc25468859762018-12-10 10:56
回复 2楼 RockCarry
#8
RockCarry2018-12-10 11:13
一些符号的含义:
F - 正面,程序运行后白色的这一面
B - 背面,黄色面
L - 左面,紫色面(标准魔方应该是橙色,但是 windows 控制台无法显示橙色,用紫色替代)
R - 右面,红色面
U - 上面,蓝色面
D - 下面,绿色面


命令说明:

魔方操作命令:
f  - 正面顺时针旋转
f2 - 正面 180 度旋转
f' - 正面逆时针旋转

其他面以此类推:
f2 f' b b2 b' u u2 u' d d2 d' l l2 l' r r2 r'

init  - 魔方复位
rand  - 随机打乱魔方,可以直接 rand 或者 rand n,n 为随机打乱次数
input - 输入魔方状态,按照提示输入即可
solve - 自动还原魔方
help  - 帮助信息
exit  - 退出程序

所有命令都是用小写字母。


#9
caosule2018-12-10 18:16
#10
powerfrank2018-12-11 08:51
牛BI啊
#11
BlueGuy2019-04-13 23:37
厉害

格式化一下代码,方便阅读
程序代码:

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#pragma pack(1)
typedef struct tagCUBE
{
    struct tagCUBE* parent;
    char f[3][3];
    char b[3][3];
    char u[3][3];
    char d[3][3];
    char l[3][3];
    char r[3][3];
    char op;
} CUBE;
#pragma pack()

typedef struct
{
    int   stride;
    char* buffer;
} LINEITEM;

static void line_rotate90(LINEITEM item[5])
{
    int i, j;

    for (i = 0; i < 5; i++)
    {
        int   dst_idx    = (i + 0) % 5;
        int   src_idx    = (i + 1) % 5;
        char* dst_buf    = item[dst_idx].buffer;
        char* src_buf    = item[src_idx].buffer;
        int   dst_stride = item[dst_idx].stride;
        int   src_stride = item[src_idx].stride;

        for (j = 0; j < 3; j++)
        {
            *dst_buf = *src_buf;
            dst_buf += dst_stride;
            src_buf += src_stride;
        }
    }
}

static void surface_rotate90(char buf[3][3])
{
    char tmp[3][3];
    int  i, j;
    memcpy(tmp, buf, sizeof(tmp));

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            buf[i][j] = tmp[3 - j - 1][i];
        }
    }
}

static void cube_init(CUBE* c)
{
    memset(c->f, 'w', sizeof(c->f));
    memset(c->b, 'y', sizeof(c->b));
    memset(c->u, 'b', sizeof(c->u));
    memset(c->d, 'g', sizeof(c->d));
    memset(c->l, 'o', sizeof(c->l));
    memset(c->r, 'r', sizeof(c->r));
}

static void cube_f(CUBE* c)
{
    char temp[3];
    LINEITEM lines[5] =
    {
        { 1,  temp          },
        { 3,  &(c->l[0][2]) },
        { 1,  &(c->d[0][0]) },
        {-3,  &(c->r[2][0]) },
        {-1,  &(c->u[2][2]) },
    };
    line_rotate90(lines);
    surface_rotate90(c->f);
}

static void cube_b(CUBE* c)
{
    char temp[3];
    LINEITEM lines[5] =
    {
        { 1,  temp          },
        { 3,  &(c->r[0][2]) },
        {-1,  &(c->d[2][2]) },
        {-3,  &(c->l[2][0]) },
        { 1,  &(c->u[0][0]) },
    };
    line_rotate90(lines);
    surface_rotate90(c->b);
}

static void cube_u(CUBE* c)
{
    char temp[3];
    LINEITEM lines[5] =
    {
        { 1,  temp          },
        { 1,  &(c->l[0][0]) },
        { 1,  &(c->f[0][0]) },
        { 1,  &(c->r[0][0]) },
        { 1,  &(c->b[0][0]) },
    };
    line_rotate90(lines);
    surface_rotate90(c->u);
}

static void cube_d(CUBE* c)
{
    char temp[3];
    LINEITEM lines[5] =
    {
        { 1,  temp          },
        { 1,  &(c->b[2][0]) },
        { 1,  &(c->r[2][0]) },
        { 1,  &(c->f[2][0]) },
        { 1,  &(c->l[2][0]) },
    };
    line_rotate90(lines);
    surface_rotate90(c->d);
}

static void cube_l(CUBE* c)
{
    char temp[3];
    LINEITEM lines[5] =
    {
        { 1,  temp          },
        { 3,  &(c->d[0][0]) },
        { 3,  &(c->f[0][0]) },
        { 3,  &(c->u[0][0]) },
        {-3,  &(c->b[2][2]) },
    };
    line_rotate90(lines);
    surface_rotate90(c->l);
}

static void cube_r(CUBE* c)
{
    char temp[3];
    LINEITEM lines[5] =
    {
        { 1,  temp          },
        { 3,  &(c->u[0][2]) },
        { 3,  &(c->f[0][2]) },
        { 3,  &(c->d[0][2]) },
        {-3,  &(c->b[2][0]) },
    };
    line_rotate90(lines);
    surface_rotate90(c->r);
}

enum
{
    CUBE_OP_F,
    CUBE_OP_B,
    CUBE_OP_U,
    CUBE_OP_D,
    CUBE_OP_L,
    CUBE_OP_R,
};

static void (*g_op_tab[])(CUBE* c) = { cube_f, cube_b, cube_u, cube_d, cube_l, cube_r };
static void cube_op(CUBE* c, int op)
{
    (g_op_tab[op])(c);
}
static void cube_rand(CUBE* c, int n)
{
    while (n-- > 0)
    {
        cube_op(c, rand() % 6);
    }
}

static void cube_render(CUBE* c)
{
    char buffer[9][12] = {0};
    int  i, j;

    HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
    WORD wOldColorAttrs;
    CONSOLE_SCREEN_BUFFER_INFO csbiInfo;

    // save the current color
    GetConsoleScreenBufferInfo(h, &csbiInfo);
    wOldColorAttrs = csbiInfo.wAttributes;

    for (i = 0; i < 3; i++) for (j = 0; j < 3; j++)
    {
        buffer[3 + i][3 + j] = c->f[i][j];
    }

    for (i = 0; i < 3; i++) for (j = 0; j < 3; j++)
    {
        buffer[3 + i][9 + j] = c->b[i][j];
    }

    for (i = 0; i < 3; i++) for (j = 0; j < 3; j++)
    {
        buffer[0 + i][3 + j] = c->u[i][j];
    }

    for (i = 0; i < 3; i++) for (j = 0; j < 3; j++)
    {
        buffer[6 + i][3 + j] = c->d[i][j];
    }

    for (i = 0; i < 3; i++) for (j = 0; j < 3; j++)
    {
        buffer[3 + i][0 + j] = c->l[i][j];
    }

    for (i = 0; i < 3; i++) for (j = 0; j < 3; j++)
    {
        buffer[3 + i][6 + j] = c->r[i][j];
    }

    for (i = 0; i < 9; i++)
    {
        for (j = 0; j < 12; j++)
        {
            switch (buffer[i][j])
            {
                case 'w':
                case 'W':
                    SetConsoleTextAttribute(h, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
                    break;

                case 'y':
                case 'Y':
                    SetConsoleTextAttribute(h, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
                    break;

                case 'b':
                case 'B':
                    SetConsoleTextAttribute(h, FOREGROUND_INTENSITY | FOREGROUND_BLUE);
                    break;

                case 'g':
                case 'G':
                    SetConsoleTextAttribute(h, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
                    break;

                case 'o':
                case 'O':
                    SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_BLUE);
                    break;

                case 'r':
                case 'R':
                    SetConsoleTextAttribute(h, FOREGROUND_INTENSITY | FOREGROUND_RED);
                    break;
            }

            printf(buffer[i][j] ? "\2 " : "  ");
        }

        printf("\n");
    }

    // restore the original color
    SetConsoleTextAttribute(h, wOldColorAttrs);
}

static int cube_check_fcross0(CUBE* cube)
{
    int checklist[][2] =
    {
        { cube->f[1][1], cube->f[0][1] },
        { cube->f[1][1], cube->f[1][0] },
        { cube->f[1][1], cube->f[1][2] },
        { cube->f[1][1], cube->f[2][1] },
    };
    int value = 0, i;

    for (i = 0; i < 4; i++)
    {
        value += (checklist[i][0] == checklist[i][1]);
    }

    return value;
}

static int cube_check_fcross1(CUBE* cube)
{
    int checklist[][2] =
    {
        { cube->l[1][1], cube->l[1][2] },
        { cube->u[1][1], cube->u[2][1] },
        { cube->r[1][1], cube->r[1][0] },
        { cube->d[1][1], cube->d[0][1] },
    };
    int value = 0, i;

    for (i = 0; i < 4; i++)
    {
        value += (checklist[i][0] == checklist[i][1]);
    }

    return value;
}

static int cube_check_fcorners(CUBE* cube)
{
    int checklist[][3][2] =
    {
        {
            { cube->f[1][1], cube->f[0][0] },
            { cube->l[1][1], cube->l[0][2] },
            { cube->u[1][1], cube->u[2][0] },
        },
        {
            { cube->f[1][1], cube->f[0][2] },
            { cube->u[1][1], cube->u[2][2] },
            { cube->r[1][1], cube->r[0][0] },
        },
        {
            { cube->f[1][1], cube->f[2][0] },
            { cube->l[1][1], cube->l[2][2] },
            { cube->d[1][1], cube->d[0][0] },
        },
        {
            { cube->f[1][1], cube->f[2][2] },
            { cube->r[1][1], cube->r[2][0] },
            { cube->d[1][1], cube->d[0][2] },
        },
    };
    int value = 0, i, j;

    for (j = 0; j < 4; j++)
    {
        value++;

        for (i = 0; i < 3; i++)
        {
            if (checklist[j][i][0] != checklist[j][i][1])
            {
                value--;
                break;
            }
        }
    }

    return value;
}

static int cube_check_medges(CUBE* cube)
{
    int checklist[][2][2] =
    {
        {
            { cube->l[1][1], cube->l[0][1] },
            { cube->u[1][1], cube->u[1][0] },
        },
        {
            { cube->u[1][1], cube->u[1][2] },
            { cube->r[1][1], cube->r[0][1] },
        },
        {
            { cube->l[1][1], cube->l[2][1] },
            { cube->d[1][1], cube->d[1][0] },
        },
        {
            { cube->r[1][1], cube->r[2][1] },
            { cube->d[1][1], cube->d[1][2] },
        },
    };
    int value = 0, i, j;

    for (j = 0; j < 4; j++)
    {
        value++;

        for (i = 0; i < 2; i++)
        {
            if (checklist[j][i][0] != checklist[j][i][1])
            {
                value--;
                break;
            }
        }
    }

    return value;
}

static int cube_check_bcross(CUBE* cube)
{
    int checklist[][2][2] =
    {
        {
            { cube->b[1][1], cube->b[0][1] },
            { cube->b[1][1], cube->b[2][1] },
        },
        {
            { cube->b[1][1], cube->b[1][0] },
            { cube->b[1][1], cube->b[1][2] },
        },
    };
    int value = 0, i, j;

    for (j = 0; j < 2; j++)
    {
        value += 2;

        for (i = 0; i < 2; i++)
        {
            if (checklist[j][i][0] != checklist[j][i][1])
            {
                value -= 2;
                break;
            }
        }
    }

    return value;
}

static int cube_check_bsurface(CUBE* cube)
{
    int checklist[][2] =
    {
        { cube->b[1][1], cube->b[0][0] },
        { cube->b[1][1], cube->b[0][2] },
        { cube->b[1][1], cube->b[2][0] },
        { cube->b[1][1], cube->b[2][2] },
    };
    int value = 0, i;

    for (i = 0; i < 4; i++)
    {
        value += (checklist[i][0] == checklist[i][1]);
    }

    if (value == 2)
    {
        value = 0;
    }

    return value;
}

static int cube_check_bcorners(CUBE* cube)
{
    int checklist[][3][2] =
    {
        {
            { cube->b[1][1], cube->b[0][2] },
            { cube->l[1][1], cube->l[0][0] },
            { cube->u[1][1], cube->u[0][0] },
        },
        {
            { cube->b[1][1], cube->b[0][0] },
            { cube->u[1][1], cube->u[0][2] },
            { cube->r[1][1], cube->r[0][2] },
        },
        {
            { cube->b[1][1], cube->b[2][0] },
            { cube->r[1][1], cube->r[2][2] },
            { cube->d[1][1], cube->d[2][2] },
        },
        {
            { cube->b[1][1], cube->b[2][2] },
            { cube->l[1][1], cube->l[2][0] },
            { cube->d[1][1], cube->d[2][0] },
        },
    };
    int returned[4] = { 1, 1, 1, 1 };
    int value = 0, flag = 0, i, j;

    for (j = 0; j < 4; j++)
    {
        value++;

        for (i = 0; i < 3; i++)
        {
            if (checklist[j][i][0] != checklist[j][i][1])
            {
                value--;
                returned[j] = 0;
                break;
            }
        }
    }

    for (i = 0; i < 4; i++)
    {
        if (returned[i] && returned[(i + 1) % 4])
        {
            flag = 1;
        }
    }

    return flag ? value : 0;
}

static int cube_check_bedges(CUBE* cube)
{
    int checklist[][2][2] =
    {
        {
            { cube->u[1][1], cube->u[0][1] },
            { cube->b[1][1], cube->b[0][1] },
        },
        {
            { cube->d[1][1], cube->d[2][1] },
            { cube->b[1][1], cube->b[2][1] },
        },
        {
            { cube->l[1][1], cube->l[1][0] },
            { cube->b[1][1], cube->b[1][2] },
        },
        {
            { cube->r[1][1], cube->r[1][2] },
            { cube->b[1][1], cube->b[1][0] },
        },
    };
    int value = 0, i, j;

    for (j = 0; j < 4; j++)
    {
        value++;

        for (i = 0; i < 2; i++)
        {
            if (checklist[j][i][0] != checklist[j][i][1])
            {
                value--;
                break;
            }
        }
    }

    return value;
}

static int cube_check_state(CUBE* cube, int flag)
{
    int (*pfn_check_tab[])(CUBE * cube) =
    {
        cube_check_fcross0,
        cube_check_fcross1,
        cube_check_fcorners,
        cube_check_medges,
        cube_check_bcross,
        cube_check_bsurface,
        cube_check_bcorners,
        cube_check_bedges,
        NULL,
    };
    int value = 0, cur, i;

    for (i = 0; pfn_check_tab[i]; i++)
    {
        if (flag)
        {
            value += pfn_check_tab[i](cube);
            cur   += 4;

            if (cur >= flag)
            {
                break;
            }
        }
        else
        {
            cur    = pfn_check_tab[i](cube);
            value += cur;

            if (cur != 4)
            {
                break;
            }
        }
    }

    return value;
}

typedef struct
{
    int   open ;
    int   close;
    int   size ;
    CUBE* cubes;
} TABLE;

static int search_table_create(TABLE* table, int size)
{
    table->size  = size;
    table->cubes = malloc(size * sizeof(CUBE));
    return table->cubes ? 0 : -1;
}

static void search_table_destroy(TABLE* table)
{
    if (table->cubes)
    {
        free(table->cubes);
        table->cubes = NULL;
    }
}

static int is_4same_ops(CUBE* cube)
{
    int curop = cube->op;
    int n     = 0;

    while (cube)
    {
        if (cube->op == curop)
        {
            if (++n == 4)
            {
                return 1;
            }

            cube = cube->parent;
        }
        else
        {
            break;
        }
    }

    return 0;
}

static int cut_branch(int newval, int cutval)
{
    return newval < cutval;
}

static CUBE* search(TABLE* table, CUBE* start, int state, char* oplist, int opnum, int cutval)
{
    CUBE* curcube, *newcube;
    int   newstate, newvalue, i;

    start->parent = NULL;
    start->op     = -1;

    if (cube_check_state(start, 0) >= state)
    {
        return start;
    }

    // init search table
    table->open  = 0;
    table->close = 0;

    // put original cube into open table
    table->cubes[table->open] = *start;
    table->open++;

    while (table->close < table->open)
    {
        // check memory usage
        if (table->open + 6 >= table->size - 1)
        {
            printf("all table memory have been used !\n");
            break;
        }

        // dequeue a cube from open table
        curcube = &(table->cubes[table->close++]);

        // extend cubes check state and put new cubes into open table
        for (i = 0; i < opnum; i++)
        {
            newcube = &(table->cubes[table->open]);
            memcpy(newcube, curcube, sizeof(CUBE));
            cube_op(newcube, oplist[i]);
            newcube->op     = oplist[i];
            newcube->parent = curcube;
            newstate = cube_check_state(newcube, 0);
            newvalue = cube_check_state(newcube, state);

            if (newstate >= state)   // found
            {
                return newcube;
            }

            if (is_4same_ops(newcube))
            {
                continue;
            }

            if (cut_branch(newvalue, cutval))
            {
                continue;
            }

            table->open++;
        }
    }

    return NULL;
}

static void print_solve_oplist(CUBE* cube)
{
    static char* optab[] =
    {
        "F", "B", "U", "D", "L", "R",
        "F2", "B2", "U2", "D2", "L2", "R2",
        "F'", "B'", "U'", "D'", "L'", "R'",
    };
    char* oplist[256];
    int   last = -1, times = 0, i = 0, n = 0;

    while (cube)
    {
        if (cube->op >= 0)
        {
            if (last != cube->op)
            {
                if (last != -1)
                {
                    oplist[i++] = optab[last + times * 6];
                }

                last = cube->op;
                times = 0;
            }
            else
            {
                times++;
            }
        }
        else
        {
            if (last != -1)
            {
                oplist[i++] = optab[last + times * 6];
            }
        }

        cube = cube->parent;
    }

    printf("\noperation list:\n");

    while (--i >= 0)
    {
        printf("%s%s%s", oplist[i], i == 0 ? "" : " -> ", ++n % 12 == 0 ? "\n" : "");
    }

    printf("\n");
}

static void cube_solve(CUBE* c)
{
    TABLE t;

    if (search_table_create(&t, 1024 * 1024 * 16) != 0)
    {
        printf("failed to create cube search table !\n");
        return;
    }

    if (1)
    {
        static char oplisttab[][6] =
        {
            { CUBE_OP_F, CUBE_OP_U, CUBE_OP_D, CUBE_OP_L, CUBE_OP_R },
            { CUBE_OP_U, CUBE_OP_D, CUBE_OP_L, CUBE_OP_R, CUBE_OP_B },
            { CUBE_OP_B, CUBE_OP_R, CUBE_OP_U },
        };
        static int stepparams[][4] =
        {
            { 2, 0, 5, 0 },  //+ fcross0
            { 4, 0, 5, 2 },  //- fcross0
            { 8, 0, 5, 2 },  //+-fcross1
            { 9, 0, 5, 3 },  //+ fcorners
            { 10, 0, 5, 4 }, //..
            { 11, 0, 5, 5 }, //..
            { 12, 0, 5, 5 }, //- fcorners
            { 13, 1, 5, 6 }, //+ medges
            { 14, 1, 5, 6 }, //..
            { 15, 1, 5, 7 }, //..
            { 16, 1, 5, 8 }, //- medges
            { 18, 1, 5, 10}, //+ bcross
            { 20, 1, 5, 11}, //- bcross
            { 21, 1, 5, 11}, //+ bsurface
            { 24, 1, 5, 11}, //- bsurface
            { 26, 2, 3, 12}, //+ bcorners
            { 28, 2, 3, 12}, //- bcorners
            { 32, 2, 2, 12}, //+-bedges
            { 0, 0, 0, 0 },
        };
        CUBE* start = c;
        CUBE* find  = NULL;
        int   i;

        for (i = 0; stepparams[i][0]; i++)
        {
            find = search(&t, start, stepparams[i][0], oplisttab[stepparams[i][1]], stepparams[i][2], stepparams[i][3]);

            if (find)
            {
                if (find != start)
                {
                    start = find;
                    *c    = *find;
                    print_solve_oplist(find);

                    if (stepparams[i][0] != 32)
                    {
                        cube_render(c);
                    }
                }
            }
            else
            {
                printf("can't solve !\n");
                goto done;
            }
        }

        printf("\ncube solved !\n");
    }

done:
    search_table_destroy(&t);
}

static void cube_input(CUBE* c)
{
    char str[256];

    printf("please input F surface of cube:\n");
    scanf("%c %c %c %c %c %c %c %c %c",
            &(c->f[0][0]), &(c->f[0][1]), &(c->f[0][2]),
            &(c->f[1][0]), &(c->f[1][1]), &(c->f[1][2]),
            &(c->f[2][0]), &(c->f[2][1]), &(c->f[2][2]));
    gets(str);

    printf("please input U surface of cube:\n");
    scanf("%c %c %c %c %c %c %c %c %c",
            &(c->u[0][0]), &(c->u[0][1]), &(c->u[0][2]),
            &(c->u[1][0]), &(c->u[1][1]), &(c->u[1][2]),
            &(c->u[2][0]), &(c->u[2][1]), &(c->u[2][2]));
    gets(str);

    printf("please input D surface of cube:\n");
    scanf("%c %c %c %c %c %c %c %c %c",
            &(c->d[0][0]), &(c->d[0][1]), &(c->d[0][2]),
            &(c->d[1][0]), &(c->d[1][1]), &(c->d[1][2]),
            &(c->d[2][0]), &(c->d[2][1]), &(c->d[2][2]));
    gets(str);

    printf("please input L surface of cube:\n");
    scanf("%c %c %c %c %c %c %c %c %c",
            &(c->l[0][0]), &(c->l[0][1]), &(c->l[0][2]),
            &(c->l[1][0]), &(c->l[1][1]), &(c->l[1][2]),
            &(c->l[2][0]), &(c->l[2][1]), &(c->l[2][2]));
    gets(str);

    printf("please input R surface of cube:\n");
    scanf("%c %c %c %c %c %c %c %c %c",
            &(c->r[0][0]), &(c->r[0][1]), &(c->r[0][2]),
            &(c->r[1][0]), &(c->r[1][1]), &(c->r[1][2]),
            &(c->r[2][0]), &(c->r[2][1]), &(c->r[2][2]));
    gets(str);

    printf("please input B surface of cube:\n");
    scanf("%c %c %c %c %c %c %c %c %c",
            &(c->b[0][0]), &(c->b[0][1]), &(c->b[0][2]),
            &(c->b[1][0]), &(c->b[1][1]), &(c->b[1][2]),
            &(c->b[2][0]), &(c->b[2][1]), &(c->b[2][2]));
    gets(str);
}

static void show_help(void)
{
    printf(
            "\n"
            "available commands:\n\n"
            "f f2 f' b b2 b' u u2 u' d d2 d' l l2 l' r r2 r'\n"
            "init rand input solve help exit\n\n"
            "note: all command is case sensitive.\n"
          );
}

int main(void)
{
    char cmd[128];
    char str[256];
    CUBE c;

    // init cube
    cube_init(&c);

    show_help();

    while (1)
    {
        cube_render(&c);
        printf("command: ");
        scanf("%s", cmd);

        if (strcmp(cmd, "f") == 0)
        {
            cube_f(&c);
        }
        else if (strcmp(cmd, "f2") == 0)
        {
            cube_f(&c);
            cube_f(&c);
        }
        else if (strcmp(cmd, "f'") == 0)
        {
            cube_f(&c);
            cube_f(&c);
            cube_f(&c);
        }
        else if (strcmp(cmd, "b") == 0)
        {
            cube_b(&c);
        }
        else if (strcmp(cmd, "b2") == 0)
        {
            cube_b(&c);
            cube_b(&c);
        }
        else if (strcmp(cmd, "b'") == 0)
        {
            cube_b(&c);
            cube_b(&c);
            cube_b(&c);
        }
        else if (strcmp(cmd, "u") == 0)
        {
            cube_u(&c);
        }
        else if (strcmp(cmd, "u2") == 0)
        {
            cube_u(&c);
            cube_u(&c);
        }
        else if (strcmp(cmd, "u'") == 0)
        {
            cube_u(&c);
            cube_u(&c);
            cube_u(&c);
        }
        else if (strcmp(cmd, "d") == 0)
        {
            cube_d(&c);
        }
        else if (strcmp(cmd, "d2") == 0)
        {
            cube_d(&c);
            cube_d(&c);
        }
        else if (strcmp(cmd, "d'") == 0)
        {
            cube_d(&c);
            cube_d(&c);
            cube_d(&c);
        }
        else if (strcmp(cmd, "l") == 0)
        {
            cube_l(&c);
        }
        else if (strcmp(cmd, "l2") == 0)
        {
            cube_l(&c);
            cube_l(&c);
        }
        else if (strcmp(cmd, "l'") == 0)
        {
            cube_l(&c);
            cube_l(&c);
            cube_l(&c);
        }
        else if (strcmp(cmd, "r") == 0)
        {
            cube_r(&c);
        }
        else if (strcmp(cmd, "r2") == 0)
        {
            cube_r(&c);
            cube_r(&c);
        }
        else if (strcmp(cmd, "r'") == 0)
        {
            cube_r(&c);
            cube_r(&c);
            cube_r(&c);
        }
        else if (strcmp(cmd, "init") == 0)
        {
            cube_init(&c);
        }
        else if (strcmp(cmd, "rand") == 0)
        {
            gets(str);
            cube_rand(&c, atoi(str) == 0 ? 100 : atoi(str));
        }
        else if (strcmp(cmd, "input") == 0)
        {
            cube_input(&c);
        }
        else if (strcmp(cmd, "solve") == 0)
        {
            cube_solve(&c);
        }
        else if (strcmp(cmd, "help") == 0)
        {
            show_help();
        }
        else if (strcmp(cmd, "exit") == 0)
        {
            break;
        }
        else
        {
            printf("unsupported command !\n");
        }

        printf("\n");
    }

    return 0;
}




[此贴子已经被作者于2019-4-28 23:06编辑过]

#12
lihuahao哈2019-04-17 09:21
#13
她很美2019-04-17 15:42
牛批啊
#14
她很美2019-04-18 09:30
牛牛牛
#15
爱高数2019-05-24 11:32
我想请问一下,那54个色块是怎么定义的(来自菜鸟的疑问)。或者说魔方输入状态该输入什么。
#16
zhulei19782019-05-25 05:51
有一个错误:

1.cpp(438) : error C2440: '=' : cannot convert from 'void *' to 'struct tagCUBE *'

如何修改
#17
爱高数2019-05-26 15:22
回复 11楼 BlueGuy
请问一下 ,那魔方的六个面应该输入什么比如"F" ,"f"又或者是什么数字吗
#18
RockCarry2019-05-27 09:00
回复 16楼 zhulei1978
用 c 语言编译器编译。或者你做下强制类型转换就可以了。
#19
zhulei19782019-05-27 09:14
回复 18楼 RockCarry
好的
#20
爱高数2019-05-27 15:29
这程序分析了三分之二的函数,但就是找不到正确的输入格式,程序中scanf函数有点多,所以找不到正确的格式,我运行了两天,我试过输入FUBDLR(没有用过U2,U'之类的),也试过选用小写,用过数字,甚至用过函数中定义的gwblo之类的,但还是不成功,希望作者能帮我解答
#21
RockCarry2019-05-29 10:26
回复 20楼 爱高数
是不能编译,还是不知道怎么使用?
#22
爱高数2019-05-29 11:25
回复 21楼 RockCarry
您终于回我了,我在.c的环境下可以编译,也可以运行。

【其实就是不知道怎么使用】
【在输入input 的please input F B D ... surface of cube:   要输入六个面要怎样的输入】

代码中的指令f f2 f' b b2 b' u u2 u' d d2 d' l l2 l' r r2 r'我没用过,我用的都是大写的字母。
比如上面转90°后,前面九个色块,我输入的就是R R R F F F F F F,我这做法可能有点蠢,我试了好多方法,都是错的

本身对魔方和这个程序很感兴趣,这个程序很有意思,希望得到作者您的答复
#23
RockCarry2019-05-29 11:41
please input F surface of cube:
表示输入 F (正面)的颜色,格式为
r r r r r r r r
一行 9 个字符,用空格分隔,小写字母

颜色可以是
w - 白色
y - 黄色
b - 蓝色
g - 绿色
o - 橙色
r - 红色
#24
爱高数2019-05-29 12:48
回复 23楼 RockCarry
好的,谢谢 有问题 我再来
#25
ehszt2019-05-29 16:01
厉害,收藏!
#26
爱高数2019-05-29 19:23
回复 23楼 RockCarry
我又来了,@RockCarry
1.我看了您之前发的图,为什么我没有那个颜色方格?

2.当以您先前定义的白为前(w),蓝为顶(b),右为红(r)......
此时把魔方的顶上一层转180度
我输入的六面内容为

input 回车

F前:y y y w w w w w w
U上:b b b b b b b b b
D底:g g g g g g g g g
L左:r r r l l l l l l
R右:l l l r r r r r r
B后:w w w y y y y y y

solve 回车
为什么程序还是不能解决,
我有点蠢,是不是拿魔方的面的方向有问题,又或者输入指令次序是什么。
#27
RockCarry2019-05-30 09:04
F前:y y y w w w w w w
U上:b b b b b b b b b
D底:g g g g g g g g g
L左:r r r l l l l l l
R右:l l l r r r r r r
B后:w w w y y y y y y

l 是什么,输错了吧
#28
爱高数2019-05-30 09:49
回复 27楼 RockCarry
不好意思,写错了 是o      ,但还是不能解决,

我输入rand打乱后就可以解决,所以我像是我哪里做的不对。

因为不能显示色块,我也不知道😭哪里错了
#29
RockCarry2019-05-30 16:03
是方位不对吧,注意顺序。输入后屏幕上不是会显示吗,把你魔方与屏幕上显示的对一遍看看。
#30
爱高数2019-05-30 22:54
回复 29楼 RockCarry
嗯嗯,我再试试,正是因为电脑不显示色块(可能是这编译器不行吧),所以改起来很繁琐。谢谢,我再试试。。。
#31
gjj45542020-03-05 17:23
回复 楼主 RockCarry
请问输入怎么输入?
#32
return_02020-03-09 19:57
厉害厉害,顶!
#33
return_02020-03-09 19:58
对了,它。。。编译错误
#34
Mikotousaka2020-03-12 17:57
大佬大佬,你这程序怎么运行啊,是要写进单片机里去吗
#35
sword1saint2020-03-13 23:18
强悍如斯
#36
return_02020-03-17 20:21
我顶顶顶顶顶顶顶顶顶顶顶顶●●●●●●●●●●●●●顶顶顶顶
顶顶●●●●●●●●●●顶顶顶顶顶●●●●●顶顶顶顶顶顶顶
顶●●●●●●●●●●●顶顶顶顶顶顶●●●顶顶顶顶顶顶顶顶
顶顶顶●●●●●●●顶顶顶顶顶顶顶顶●●●顶顶顶顶顶顶顶顶
顶顶顶顶顶顶●●●顶顶顶顶顶顶顶●●●●●●●●●顶顶顶顶
顶顶顶顶顶顶●●●顶顶顶顶顶●●●●●●●●●●●顶顶顶顶
顶顶顶顶顶顶●●●顶顶顶顶●●●●●顶顶顶顶●●●●顶顶顶
顶顶顶顶顶顶●●●顶顶顶顶●●●●顶顶顶顶顶顶●●●顶顶顶
顶顶顶顶顶顶●●●顶顶顶顶●●●顶顶●●●顶顶●●●顶顶顶
顶顶顶顶顶顶●●●顶顶顶顶●●●顶顶●●●顶顶●●●顶顶顶
顶顶顶顶顶顶●●●顶顶顶顶●●●顶顶●●●顶顶●●●顶顶顶
顶顶顶顶顶顶●●●顶顶顶顶●●●顶顶●●●顶顶●●●顶顶顶
顶顶顶顶顶顶●●●顶顶顶顶●●●顶顶●●●顶顶●●●顶顶顶
顶顶顶顶顶顶●●●顶顶顶顶●●●顶顶●●●顶顶●●●顶顶顶
顶●●顶顶●●●●顶顶顶顶顶顶顶顶●●●●●●顶顶顶顶顶顶
顶●●●●●●●●顶顶顶顶顶顶顶●●●●顶●●●●顶顶顶顶
顶顶●●●●●●●顶顶顶顶顶顶●●●●顶顶顶●●●●顶顶顶
顶顶顶●●●●●●顶顶顶顶顶●●●●●顶顶顶顶●●●●顶顶
顶顶顶顶顶●●●顶顶顶顶顶●●●●●顶顶顶顶顶顶●●●●顶
顶顶顶顶顶顶顶顶顶顶顶顶●●●●●顶顶顶顶顶顶顶顶●●●●
顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶
顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶顶
#37
七分2020-03-18 13:22
我对这个挺感兴趣的,就是不太清楚怎么输入,还请楼主解答一下,比如说前面白色面最上面一层开始从左往右是r r r w w w w w w,这个应该怎么输入?
#38
七分2020-03-18 13:38
回复 30楼 爱高数
您好,想知道您搞定怎么输入了吗?
#39
return_02020-03-18 14:00
天知道怎么输入
#40
smitest2020-03-18 14:17
讲讲课呗
#41
return_02020-03-18 14:22
老兄,800行,你让我们细品代码斟酌如何输入啊。
#42
RockCarry2020-03-19 10:20
回复 41楼 return_0
命令说明:

魔方操作命令:
f  - 正面顺时针旋转
f2 - 正面 180 度旋转
f' - 正面逆时针旋转

其他面以此类推:
f2 f' b b2 b' u u2 u' d d2 d' l l2 l' r r2 r'

init  - 魔方复位
rand  - 随机打乱魔方,可以直接 rand 或者 rand n,n 为随机打乱次数
input - 输入魔方状态,按照提示输入即可
solve - 自动还原魔方
help  - 帮助信息
exit  - 退出程序

所有命令都是用小写字母。
#43
return_02020-03-19 10:27
谢谢,知道了
#44
return_02020-03-19 10:29
602行出错了
#45
maomao123452020-03-24 11:46
牛掰666
#46
maomao123452020-03-24 12:14
编译好像有问题
#47
万致远醉帥2020-03-25 12:31
1