厉害
格式化一下代码,方便阅读
格式化一下代码,方便阅读
程序代码:
#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编辑过]
我就是真命天子,顺我者生,逆我者死!