在电视上看到的游戏,规则是:
移动1根(目前只看到1根的,或许有两根或以上,不过再多就比较难了)火柴,使给出的4位数成为最大(或最小)。
当然火柴不能弄断,也不能消失什么的,这点和偶们小学暑假作业的那种不一样。
因此这种题用偶擅长的穷举法来解是最合适不过的了。
生成的算法……随机产生!不过产生后可以根据输出的match参数判断题目大概的难度,match的越多应该就越难。
程序会用字符拼出火柴的摆放形状以便观察。
程序的使用方式是(假设编译为match.exe):
match
生成随机数并给出答案
match 数字
解得给出的数
程序在linux gcc上编译通过。

#include <stdio.h>
#include <stdlib.h>
// count of digits
#define DIGITS 4
// how many time(s) of movement allowed
#define MAXMOVE 1
#define WIDTH (DIGITS * 4)
#define HEIGHT 5

const unsigned char LED[10] = ...{ 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x27, 0x7F, 0x6F };
const unsigned char MASKS[7][3] = ...{
...{ 0x00, 0x10, 0x20 },
...{ 0x20, 0x21, 0x22 },
...{ 0x22, 0x23, 0x24 },
...{ 0x04, 0x14, 0x24 },
...{ 0x02, 0x03, 0x04 },
...{ 0x00, 0x01, 0x02 },
...{ 0x02, 0x12, 0x22 }
};
void print_num(int num)
...{
char buf[WIDTH][HEIGHT];
int i, j, k, mask, left;
memset(buf, 0, sizeof buf);
left = WIDTH - 4;
for ( i = 0; i < DIGITS; ++i, left -= 4 ) ...{
mask = LED[num % 10];
num /= 10;
for ( j = 0; j < 7; ++j, mask >>= 1 ) ...{
if ( mask & 1) ...{
for ( k = 0; k < 3; ++k ) buf[(MASKS[j][k] >> 4) + left][MASKS[j][k] & 0xF] = 1;
}
}
}
for ( j = 0; j < HEIGHT; ++j ) ...{
for ( i = 0; i < WIDTH; ++i ) ...{
if (buf[i][j]) printf("O"); else printf(" ");
}
printf(" ");
}
}
int is_valid(int led)
...{
int i;
for ( i = 0; i < 10; ++i ) if (led == LED[i]) return 1;
return 0;
}
int led_to_num(unsigned char *leds)
...{
int num = 0, i, j, mod = 1;
for ( i = 0; i < DIGITS; ++i ) ...{
for ( j = 0; j < 10; ++j ) ...{
if (leds[i] == LED[j]) ...{
num = num + j * mod;
break;
}
}
mod *= 10;
}
return num;
}
// do a move, change two digits' led, returns non-zero if it results valid numbers
int move(unsigned char* srcled, unsigned char* destled, int srcindex, int destindex)
...{
if ( ((*srcled) & (1 << srcindex))
&& !((*destled) & (1 << destindex)) ) ...{
// off the src pos
*srcled &= ~(1 << srcindex);
// light the dest pos
*destled |= (1 << destindex);
return is_valid(*srcled) && is_valid(*destled);
}
return 1; // not moved
}
void try_level(int level, unsigned char *leds, int *maxnum, int *minnum, int *match)
...{
unsigned char tmpleds[DIGITS];
int srcled, destled, srcindex, destindex;
int n;
for ( srcled = 0; srcled < DIGITS; ++srcled ) ...{
for ( destled = 0; destled < DIGITS; ++destled ) ...{
for ( srcindex = 0; srcindex < 7; ++srcindex ) ...{
for ( destindex = 0; destindex < 7; ++destindex ) ...{
if (srcled == destled && srcindex == destindex) continue; // the same
memcpy(tmpleds, leds, sizeof tmpleds);
if ( move(&tmpleds[srcled], &tmpleds[destled], srcindex, destindex) ) ...{
if (level == 0) ...{
n = led_to_num(tmpleds);
if ( n > *maxnum ) *maxnum = n;
if ( n < *minnum ) *minnum = n;
++(*match);
}
}
if (level > 0) try_level(level - 1, tmpleds, maxnum, minnum, match);
}
}
}
}
}
int main(int argc, char* argv[])
...{
unsigned char leds[DIGITS];
unsigned char tmpleds[DIGITS];
int maxnum = -1, minnum = 0x7FFFFFFF;
int match = 0;
int i;
int num, numtemp, m, mod;
srand(time(NULL));
if (argc == 2) sscanf(argv[1], "%d", &numtemp);
else numtemp = rand();
// generate leds
num = 0;
for (i = 0, m = numtemp, mod = 1; i < DIGITS; ++i) ...{
leds[i] = LED[m % 10];
num += (m % 10) * mod;
m /= 10;
mod *= 10;
}
try_level(MAXMOVE - 1, leds, &maxnum, &minnum, &match);
printf("number=%d movements=%d matches=%d maxnum=%d,minnum=%d ",
num, MAXMOVE, match, maxnum, minnum);
printf("NUMBER: ");
print_num(num);
printf("MAX: ");
print_num(maxnum);
printf("MIN: ");
print_num(minnum);
return 0;
}
346



被折叠的 条评论
为什么被折叠?



