2017-01-19 3 views
2

В настоящее время я делаю игру, для которой требуется много операторов if, чтобы выяснить, где пользователь нажимает и что-то делать. Он проверяет, щелкнет ли пользователь в указанных координатах. Код ниже работает отлично, но у меня возникают проблемы с эффективным методом для этого (не только для этого кода, но и для любого кода вообще).Как упростить несколько повторяющихся операторов if/else if в программировании на языке C

if((mx > 78) && (mx < 113) && (my > 157) && (my < 191)) ifff(0, 0, 78, 157, 113, 191); 
else if((mx > 116) && (mx < 150) && (my > 157) && (my < 191)) ifff(1, 0, 116, 157, 150, 191); 
else if((mx > 153) && (mx < 188) && (my > 157) && (my < 191)) ifff(2, 0, 153, 157, 188, 191); 
else if((mx > 196) && (mx < 230) && (my > 157) && (my < 191)) ifff(3, 0, 196, 157, 230, 191); 
else if((mx > 233) && (mx < 267) && (my > 157) && (my < 191)) ifff(4, 0, 233, 157, 267, 191); 
else if((mx > 270) && (mx < 303) && (my > 157) && (my < 191)) ifff(5, 0, 270, 157, 303, 191); 
else if((mx > 311) && (mx < 345) && (my > 157) && (my < 191)) ifff(6, 0, 311, 157, 345, 191); 
else if((mx > 348) && (mx < 384) && (my > 157) && (my < 191)) ifff(7, 0, 348, 157, 384, 191); 
else if((mx > 388) && (mx < 421) && (my > 157) && (my < 191)) ifff(8, 0, 388, 157, 421, 191); 

else if((mx > 78) && (mx < 113) && (my > 194) && (my < 229)) ifff(0, 1, 78, 194, 113, 229); 
else if((mx > 116) && (mx < 150) && (my > 194) && (my < 229)) ifff(1, 1, 116, 194, 150, 229); 
else if((mx > 153) && (mx < 188) && (my > 194) && (my < 229)) ifff(2, 1, 153, 194, 188, 229); 
else if((mx > 196) && (mx < 230) && (my > 194) && (my < 229)) ifff(3, 1, 196, 194, 230, 229); 
else if((mx > 233) && (mx < 267) && (my > 194) && (my < 229)) ifff(4, 1, 233, 194, 267, 229); 
else if((mx > 270) && (mx < 303) && (my > 194) && (my < 229)) ifff(5, 1, 270, 194, 303, 229); 
else if((mx > 311) && (mx < 345) && (my > 194) && (my < 229)) ifff(6, 1, 311, 194, 345, 229); 
else if((mx > 348) && (mx < 384) && (my > 194) && (my < 229)) ifff(7, 1, 348, 194, 384, 229); 
else if((mx > 388) && (mx < 421) && (my > 194) && (my < 229)) ifff(8, 1, 388, 194, 421, 229); 

else if((mx > 78) && (mx < 113) && (my > 231) && (my < 266)) ifff(0, 2, 78, 231, 113, 266); 
else if((mx > 116) && (mx < 150) && (my > 231) && (my < 266)) ifff(1, 2, 116, 231, 150, 266); 
else if((mx > 153) && (mx < 188) && (my > 231) && (my < 266)) ifff(2, 2, 153, 231, 188, 266); 
else if((mx > 196) && (mx < 230) && (my > 231) && (my < 266)) ifff(3, 2, 196, 231, 230, 266); 
else if((mx > 233) && (mx < 267) && (my > 231) && (my < 266)) ifff(4, 2, 233, 231, 267, 266); 
else if((mx > 270) && (mx < 303) && (my > 231) && (my < 266)) ifff(5, 2, 270, 231, 303, 266); 
else if((mx > 311) && (mx < 345) && (my > 231) && (my < 266)) ifff(6, 2, 311, 231, 345, 266); 
else if((mx > 348) && (mx < 384) && (my > 231) && (my < 266)) ifff(7, 2, 348, 231, 384, 266); 
else if((mx > 388) && (mx < 421) && (my > 231) && (my < 266)) ifff(8, 2, 388, 231, 421, 266); 

else if((mx > 78) && (mx < 113) && (my > 231) && (my < 266)) ifff(0, 3, 78, 231, 113, 266); 
else if((mx > 116) && (mx < 150) && (my > 231) && (my < 266)) ifff(1, 3, 116, 231, 150, 266); 
else if((mx > 153) && (mx < 188) && (my > 231) && (my < 266)) ifff(2, 3, 153, 231, 188, 266); 
else if((mx > 196) && (mx < 230) && (my > 231) && (my < 266)) ifff(3, 3, 196, 231, 230, 266); 
else if((mx > 233) && (mx < 267) && (my > 231) && (my < 266)) ifff(4, 3, 233, 231, 267, 266); 
else if((mx > 270) && (mx < 303) && (my > 231) && (my < 266)) ifff(5, 3, 270, 231, 303, 266); 
else if((mx > 311) && (mx < 345) && (my > 231) && (my < 266)) ifff(6, 3, 311, 231, 345, 266); 
else if((mx > 348) && (mx < 384) && (my > 231) && (my < 266)) ifff(7, 3, 348, 231, 384, 266); 
else if((mx > 388) && (mx < 421) && (my > 231) && (my < 266)) ifff(8, 3, 388, 231, 421, 266); 
+0

Ваш четвертый блок выражений 'else if' страдает от copy'n'paste-itis. Он имеет тот же диапазон y ('my> 231 && my <266'), что и третий блок, поэтому он никогда не будет использоваться, потому что, если диапазоны соответствуют третьему блоку, имеет приоритет, а если нет, он просто отнимает время, повторяя серию тестов, которые потерпят неудачу. –

ответ

2

Для этого существуют структуры данных, такие как interval trees, смотрите главу из Cormen или несколько лекций из MIT конечно алгоритмов об этой структуре данных.

3

Основная идея состоит в том, чтобы найти способ представления данных в каждой из строк/блоков в коде в некоторой структуре данных, а затем создать массив этих структур данных и перебрать их.

Самый простой способ - создать массив, в котором будут храниться данные, необходимые для каждого из этих условий.

Например,

[78, 113, 157, 191] # represents first if statement 

Затем, вы можете создать массив из 9 таких массивов, которые будут представлять 9 условия, которые вы имеете в каждом из вышеперечисленных разделов.

Затем вы можете создать массив из четырех таких массивов, где каждый член будет представлять каждый из разделов вашего кода.

Наконец, вы просто перебрать все из них, как:

for (i=0; i<4; i++) 
    for (j=0; j<9; j++) 
     if (mx > my_map[i][j][0]) && (mx < my_map[i][j][1]) ... 
      ifff(j, i, my_map[i][j][0], .... 

Вы можете использовать структуры вместо массивов, которые сделают более удобным для чтения, но я не могу привести пример, так как это не ясно из вашего кода, что должны представлять разные разделы.

1

Кажется, какая-то структура в ваших интервалах. ((mx > 78) && (mx < 113)) используется несколько раз ... Затем вы можете отразить эту структуру в коде, как:

if ((mx > 78) && (mx < 113) 
    if (condition on my) 
    else if (condition on my) 
    ... 
else if (condition on mx) 
    if (condition on my) 
    else if (condition on my) 
    ... 

Конечно, это нарушает регулярность чтения, но все имеет свою цену. Вы можете даже разлагаются более (идея заключается в том, чтобы проверить любое состояние один раз):

if (mx > 78) 
     if (mx < 113) 
      if (first condition on my) 
       if (second condition on my) 
    ... 
1

Как я отметил в комментарии, ваш четвертый блок else if заявлений страдает от copy'n'paste-ИТИС. Он имеет тот же y-диапазон (my > 231 && my < 266), что и третий блок. Следовательно, это никогда не будет использоваться, потому что, если диапазоны совпадают, третий блок имеет приоритет, а если нет, он просто теряет время, повторяя серию тестов, которые потерпят неудачу.

Однако, у вас есть достаточно четкая структура, которая может быть гораздо лучше, представленную парой таблиц, функцией поиска, и один вызовом функции ifff(), как это:

struct Range 
{ 
    int lo; 
    int hi; 
    int key; 
}; 

static const struct Range x_range[] = 
{ 
    { 78, 113, 0 }, 
    { 116, 150, 1 }, 
    { 153, 188, 2 }, 
    { 196, 230, 3 }, 
    { 233, 267, 4 }, 
    { 270, 303, 5 }, 
    { 311, 345, 6 }, 
    { 348, 384, 7 }, 
    { 388, 421, 8 }, 
}; 
enum { NUM_X_RANGE = sizeof(x_range)/sizeof(x_range[0]) }; 

static const struct Range y_range[] = 
{ 
    { 157, 191, 0 }, 
    { 194, 229, 1 }, 
    { 231, 266, 2 }, 
    { 268, 299, 3 }, /* Guessed range */ 
}; 
enum { NUM_Y_RANGE = sizeof(y_range)/sizeof(y_range[0]) }; 

static inline int range_lookup(int val, const struct Range *range, int num_ranges) 
{ 
    for (int i = 0; i < num_ranges; i++) 
    { 
     if (val > range[i].lo && val < range[i].hi) 
      return i; 
    } 
    return -1; 
} 

extern void ifff_range(int mx, int my); 
extern void ifff(int xkey, int ykey, int xlo, int ylo, int xhi, int yhi); 

void ifff_range(int mx, int my) 
{ 
    int xr = range_lookup(mx, x_range, NUM_X_RANGE); 
    int yr = range_lookup(my, y_range, NUM_Y_RANGE); 
    if (xr != -1 && yr != -1) 
     ifff(x_range[xr].key, y_range[yr].key, 
      x_range[xr].lo, y_range[yr].lo, 
      x_range[xr].hi, y_range[yr].hi); 
} 

В этих данных , ключевые значения в структуре идентичны индексу строки в массиве, поэтому ключ может быть удален из структуры. Существует множество способов, с помощью которых поиск может потерпеть неудачу. Например, mx == 114 или my == 192 всегда терпят неудачу.

Смежные вопросы