制作日記

こういうの作った方が、逃げにくいじゃない

反省しつつパズドラのリファクタリング

リファクタリングの結果、実ステップ数が210から160まで減った

チェック済みのフラグも消せた

ちゃんとシーケンス確認したら、消しても問題なかったね
フラグがないと気持ちが良いね

あとは、似たような処理を無理やり抽象化

あとは、list_for_each_entryみたいなマクロを2つにまとめた
マクロも使いまわすようにして、細々とした判定とかは関数ごとに行うように

おかげで、関数(関数マクロ)が17個から13個に減った
一個はwarning消去用に追加したから、5個消せた

それでも、各関数の実ステップ数は平均10ぐらいで、リファクタリング前から少し減った
良い感じ

ということで、パズドラのパズルの主要なアルゴリズムはこれぐらいで十分書ける
人や開発言語によっては、もっと短く書けるんだろうなー

そういや、定数は列挙型とかマクロに拘る必要なかったなー
マクロのとこはconstの変数にしとくべきだったか

#include
#include
#include

#define HEIGHT 5
#define WIDTH 6
#define ERASE_MIN_NUM 3

enum BALL_COLOR
{
RED,
BLUE,
YELLOW,
BLACK,
WHITE,
LAST_BALL_COLOR
};
enum BALL_INFO
{
COLOR,
ERASE,
LAST_BALL_INFO

};

struct ball
{
signed char info[LAST_BALL_INFO];
};
struct dir
{
int y;
int x;
};
struct print_info
{
signed char* table;
int ball_info;
};

int combo = 0;
struct ball balls[HEIGHT][WIDTH] = {{{{0,0}}}};
struct dir dir_table[] = {{0,1},{1,0}};
struct dir all_dir_table[] = {{0,1},{1,0},{0,-1},{-1,0}};
signed char color_table[] = {'R', 'B', 'Y', 'K', 'W', 'L'};
signed char erase_table[] = {'o','x'};
signed char* table_array[] = {color_table, erase_table};
char* column = "\n 0 1 2 3 4 5\n";

#define unused_obj(x) (void)(x)

#define for_each_ball(x, func) \
do{ \
int i, j; \
for (i = 0; i < HEIGHT; i++) \
for (j = 0; j < WIDTH; j++) \
func(i,j,x); \
}while(0)

#define for_each_dir(height, width, table, z, func) \
do{ \
int i, max = (int)(sizeof(table)/sizeof(table[0])); \
for (i = 0; i < max; i++) \
func(height, width, table[i].y, table[i].x, z); \
}while(0)

static void search_same_color_ball(int height, int width, int y, int x, int z);

static void init_ball(int height, int width, void* z)
{
unused_obj(z);
balls[height][width].info[COLOR] = (signed char)(rand() * 1.0 / RAND_MAX * (LAST_BALL_COLOR - 1));
}

static void init(void)
{
srand((unsigned int)time(NULL));
for_each_ball(0, init_ball);
}

static void print_ball(int height, int width, void* x)
{
if (!x) return;

struct print_info *tmp = (struct print_info*)x;
signed char *tmp_table = tmp->table;

if (!height && !width)
{
printf("\n%s\n", column);
}
if (!width)
{
printf("%d ", height);
}
char ball_color = tmp_table[balls[height][width].info[tmp->ball_info]];
printf(" %c ", ball_color);
if (width == WIDTH - 1)
{
printf("\n");
}
}

static void print_screen(int print_type)
{
for_each_ball((&(struct print_info){table_array[print_type], print_type}), print_ball);
}

static int count_line(int height, int width, int y, int x)
{
int tmp_height, tmp_width;
int same_color_num;
signed char current_color = balls[height][width].info[COLOR];

tmp_height = height + y;
tmp_width = width + x;
for (same_color_num = 1; ; same_color_num++,tmp_height += y, tmp_width += x)
{
if( (balls[tmp_height][tmp_width].info[COLOR] != current_color)
|| (tmp_height >= HEIGHT || tmp_height < 0)
|| (tmp_width >= WIDTH) || tmp_width < 0)
{
break;
}
}

tmp_height = height - y;
tmp_width = width - x;
for ( ; ; same_color_num++,tmp_height -= y, tmp_width -= x)
{
if( (balls[tmp_height][tmp_width].info[COLOR] != current_color)
|| (tmp_height >= HEIGHT || tmp_height < 0)
|| (tmp_width >= WIDTH) || tmp_width < 0)
{
break;
}
}
return same_color_num;
}

static void search_line(int height, int width, int y, int x, void* z)
{
unused_obj(z);
if (balls[height][width].info[ERASE] || (count_line(height, width, y, x) < ERASE_MIN_NUM)) return;
balls[height][width].info[ERASE] = 1;

for_each_dir(height, width, all_dir_table, balls[height][width].info[COLOR], search_same_color_ball);
}

static void search_same_color_ball(int height, int width, int y, int x, int z)
{
height += y;
width += x;
if ( (height >= HEIGHT || height < 0)
|| (width >= WIDTH || width < 0)
|| balls[height][width].info[ERASE]
|| balls[height][width].info[COLOR] != z) return;

for_each_dir(height, width, dir_table, 0, search_line);
}

static void search_ball(int height, int width, void* z)
{
if (balls[height][width].info[ERASE]) return;
unused_obj(z);

for_each_dir(height, width, dir_table, 0, search_line);
if (balls[height][width].info[ERASE])
{
combo++;
}
}

static void search_erase_ball()
{
for_each_ball(0, search_ball);
}

int main(void)
{
init();
print_screen(COLOR);
search_erase_ball();
print_screen(ERASE);
printf("combo:%d", combo);
return 0;
}

コメントの投稿

非公開コメント

プロフィール

Author:drab
霊夢改変キャラ
「12 3 ! {V} [_]」
公開中
L霊夢でもl_reimuでも好きなように読んでください

最新記事
最新コメント
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク