Длинный и сложный код на Cи для поиска выхода из матрицы


Исходный код

//разметка матрицы
while ((founded==1)&&(mat[nx][ny]<=0)) {
  founded=0;
  iii=y-i;
  while (((i==0)&&(iii==y))||((iii<=y+i))){
   ii=x-i;
   while ((ii<=x+i)){
	if ((mat[ii][iii]==i)&&((ii<70)&&(ii>=0))&&((iii<70)&&(iii>=0))) {
	 bii=ii;
	 biii=iii;
	 if ((mat[bii+1][biii]==-1)&&(bii+1<70)&&(bii+1>=0)) {
	  mat[bii+1][biii]=i+1;
	  founded=1;
	 }
	 if ((mat[bii-1][biii]==-1)&&(bii-1<70)&&(bii-1>=0)) {
	  mat[bii-1][biii]=i+1;
	  founded=1;
	 }
	 if ((mat[bii][biii+1]==-1)&&(biii+1<70)&&(biii+1>=0)) {
	  mat[bii][biii+1]=i+1;
	  founded=1;
	 }
	 if ((mat[bii][biii-1]==-1)&&(biii-1<70)&&(biii-1>=0)) {
	  mat[bii][biii-1]=i+1;
	  founded=1;
	 }
	}
	ii++;
   }
   iii++;
  }
  i++;
 }
 if (mat[nx][ny]>=0) {
  if ((nx==40)&&(ny==57)) {
   nx=nx;
  }
  ik=i;

  ii=nx;
  iii=ny;
  <em>//поиск пути</em>while (ik>1) {
   if ((mat[ii-1][iii]==ik-1)&&(ii-1<70)&&(ii-1>=0)) {
	ii--;
	mat[ii][iii]=-3;
   }
   if ((mat[ii][iii-1]==ik-1)&&(iii-1<70)&&(iii-1>=0)) {
	iii--;
	mat[ii][iii]=-3;
   }
   if ((mat[ii+1][iii]==ik-1)&&(ii+1<70)&&(ii+1>=0)) {
	ii++;
	mat[ii][iii]=-3;
   }

   if ((mat[ii][iii+1]==ik-1)&&(iii+1<70)&&(iii+1>=0)) {
	iii++;
	mat[ii][iii]=-3;
   }
   ik--;
  }
   ax=ii*10+5;
   ay=iii*10+5;
  //out_to_file(mat,"d:\\out.txt");
  i++;
   ii=0;
   iii=0;
   while ((iii>-1)&&(iii<70)){
	ii=0;
	while ((ii>-1)&&(ii<70)){
	 if ((mat[ii][iii]>-1)||(mat[ii][iii]==-3)) {
	  mat[ii][iii]=-1;
	 }
	 ii++;
	}
	iii++;
   }
  nx=ax;
  ny=ay;
 }

Что не так в этом коде

Ни и чём не говорящие названия переменных

Названия iiiiibiiibii выбраны крайне неудачно, так как ничего не говорят о том, к какой координате матрицы они имеют отношение — x или y.

Ненужные переменные

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

Если переменные ничего не делают — от них необходимо избавиться, иначе они будут вносить путаницу.

Не оптимально выбраны операторы циклов

Везде по коду применяются циклы while, хотя по алгоритму здесь больше подходит for.

Сравни:

  iii=y-i;
  while (((i==0)&&(iii==y))||((iii<=y+i))) {
   // ...
   iii++;
  }

и

for (int iii=y-i; ((i==0)&&(iii==y))||((iii<=y+i)); iii++) {
      // ...
   }

Некорректная проверка на выход из диапазона

if ((mat[bii+1][biii]==-1)&&(bii+1<70)&&(bii+1>=0)) {

Здесь сначала выполняется доступ к клетке mat[bii+1][biii], а потом делается проверка на принадлежность bii+1 к правильному диапазону (bii+1<70)&&(bii+1>=0).

Аналогично с

if ((mat[ii-1][iii]==ik-1)&&(ii-1<70)&&(ii-1>=0)) {

Правильно будет так:

if ((bii+1<70)&&(bii+1>=0)&&(mat[bii+1][biii]==-1)) {
if ((ii-1<70)&&(ii-1>=0)&&(mat[ii-1][iii]==ik-1)) {

Почему нужно сначала проверять, потом обращаться.

Булевы выражения вычисляются слева направо. Сначала будет вычислена проверка, если она истинна, то только тогда вычислится выражение с обращением к ячейке. Если же проверка будет ложна, то обращения к ячейке вовсе не произойдёт.

Нарушены принципы единственного знания и единственной сущности

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

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

Магический литерал

В коде многократно применяется литерал 70.

Похоже, что он означает размер матрицы 70×70.

Если так, что следовало хотя бы поместить это значение в константу, а ещё лучше — в параметр функции, причём отдельно ширину и высоту.

Плохое форматирование

Чтение кода дополнительно затрудняется маленькими отступами, которые в некоторых местах и вовсе отсутствуют.

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

Вариант рефакторинга исходного кода

int markupMatrix(int** matrix, int width, int height, int i) {
   int found = 0;
   for (int iy = y - i; i == 0 && iy == y || iy <= y + i; iy++) {
      for (int ix = x - i; ix <= x + i; ix++) {
         if (ix < width && ix >= 0 && iy < height && iy >= 0 && matrix[ix][iy] == i) {
            founded = markupNeighbourCells(matrix, width, height, ix, iy, i);
         }
      }
   }
   return found;
}

int markupNeighbourCells(int** matrix, int width, int height, int ix, int iy, int i) {
   int found = 0;
   if (ix + 1 < width && ix + 1 >= 0 && matrix[ix + 1][iy] == -1) {
      matrix[ix + 1][iy] = i + 1;
      found = 1;
   }
   if (ix - 1 < width && ix - 1 >= 0 && matrix[ix - 1][iy] == -1) {
      matrix[ix - 1][iy] = i + 1;
      found = 1;
   }
   if (iy + 1 < height && iy + 1 >= 0 && matrix[ix][iy + 1] == -1) {
      matrix[ix][iy + 1] = i + 1;
      found = 1;
   }
   if (iy - 1 < height && iy - 1 >= 0 && matrix[ix][iy - 1] == -1) {
      matrix[ix][iy - 1] = i + 1;
      found = 1;
   }
   return found;
}

void resetCellWeights(int** matrix, int width, int height, int* ix, int* iy, int i) {
   for (int ik = i; ik > 1; ik--) {
      if (*ix - 1 < width && *ix - 1 >= 0 && matrix[*ix - 1][*iy] == ik - 1) {
         matrix[--*ix][*iy] =- 3;
      }
      if (*iy - 1 < height && *iy - 1 >= 0 && matrix[*ix][*iy - 1] == ik - 1) {
         matrix[*ix][--*iy] = -3;
      }
      if (*ix + 1 < width && *ix + 1 >= 0 && matrix[*ix + 1][*iy] == ik - 1) {
         matrix[++*ix][*iy] = -3;
      }
      if (*iy + 1 < height && *iy + 1 >= 0 && matrix[*ix][*iy + 1] == ik - 1) {
         matrix[*ix][++*iy] = -3;
      }
   }
}
// разметка матрицы
for (int found = 1; found == 1 && matrix[nx][ny] <= 0; i++) {
      found = markupMatrix(matrix, width, height, ix, iy, i);
   }

   if (matrix[nx][ny] >= 0) {
      ix = nx;
      iy = ny;
      // поиск пути
      resetCellWeights(matrix, width, height, &ix, &iy, i++);
      ax = ix * 10 + 5;
      ay = iy * 10 + 5;
      //out_to_file(matrix,"d:\\out.txt");
      while (iy = 0; iy > -1 && iy < height; iy++) {
	      for (ix = 0; ix > -1 && ix < width; ix++) {
	         if (matrix[ix][iy] > -1 || matrix[ix][iy] == -3) {
	            matrix[ix][iy] = -1;
	         }
	      }
      }
      nx = ax;
      ny = ay;
   }