C
C
CodeInside2016-02-07 02:58:58
C++ / C#
CodeInside, 2016-02-07 02:58:58

How to remove a fragment of a condition?

Warning: not for the faint of heart! Complex algorithm and the same implementation :-(
Meaning of the question:
in my code (in some function that will be below) there is such a code fragment

if (y + 2 < SIZE && x - 1 >= 0 && way[step_num - 1].blocked < 2
    && field[x - 1][y + 2] == false)
  {
    way[step_num].y = way[step_num - 1].y + 2;
    way[step_num].x = way[step_num - 1].x - 1;
    way[step_num].setedByWay = 2;
    field[x - 1][y + 2] = true;
    chessIsMoved = true;
  }
  else if (y - 2 >= 0 && x + 1 < SIZE && way[step_num - 1].blocked < 3
    && field[x + 1][y - 2] == false)
  {
    way[step_num].y = way[step_num - 1].y - 2;
    way[step_num].x = way[step_num - 1].x + 1;
    way[step_num].setedByWay = 3;
    field[x - 1][y + 2] = true;
    chessIsMoved = true;
  }

The second line contains an expression for checking the value of an element of a two-dimensional array (field[x - 1][y + 2] == false). But sometimes, while checking this expression, the program goes beyond the boundaries of the array and gives an error. It turns out that you need to somehow separate the expression (make a sequence of checking expressions). But how? If you add the last expression to the if-a body, then when false is returned, you will not be able to proceed to the next check of expressions (I think you should not use labels, because then it will be painful and embarrassing to look at the code). If you remove the else before the next branch and still add labels (or try to solve this problem through a switch), then the application logic will be violated and, with a high probability, the wrong action that I need may be performed.
So, now what, how and why do I want to do it.
Exercise:Given an 8x8 chessboard and a chess horse. The program
should ask the user for the coordinates of the field cell and put
the horse there. The task of the program is to find and display the path of the knight, in which
he will bypass all the cells of the board, entering each cell only
once. (Since the process of finding a path for different initial cells
can be delayed, it is recommended that you first try out the problem on
a 6x6 field). The program must use recursion.

Whole code:
#include <iostream>
#include <conio.h>
#define SIZE 6//6x6 - размер доски
using namespace std;

struct coords {
  short x;
  short y;
  short blocked = 0;//неверное направление пути
  short setedByWay = 0;//направление, по которому конь переместился на данные координаты //(используется для отката)
             /*
             Направления:
             1 - down(2)->right(1)
             2 - down(2)->left(1)
             3 - up(2)->right(1)
             4 - up(2)->left(1)
             5 - down(1)->right(2)
             6 - down(1)->left(2)
             7 - up(1)->right(2)
             8 - up(1)->left(2)
             */
};

void getX(short* x);
void getY(short* y);
void setWay(coords* way, bool field[][SIZE], short step_num = 1);
bool setStep(coords* way, bool** field, short step_num);

void main()
{
  short x, y;//кординаты, по которым изначально ставится конь на доске
  coords way[SIZE*SIZE+1];//кординаты, по которым будет передвигаться конь
  bool field[SIZE][SIZE] = { false };//отображение заполнённости игрового поля (false - ячейка свободна, true - на данной ячейке был конь)
  getX(&x);
  getY(&y);

  while (x >= SIZE)
  {
    cout << "x must be <" << SIZE << '\n';
    getX(&x);
  }
  while (y >= SIZE)
  {
    cout << "y must be <" << SIZE << '\n';
    getY(&y);
  }

  //установка коня на начальную позицию (начало пути)
  way[0].x = x;
  way[0].y = y;

  setWay(way, field);
  for (short i = 0; i < SIZE*SIZE + 1; i++)
    cout << way[i].x << '\t' << way[i].y << endl;

  /*while ()
  {
    setStep(way, step_num);
  }*/


  _getch();
}

void getX(short* x)
{
  cout << "x->";
  cin >> *x;
}

void getY(short* y)
{
  cout << "y->";
  cin >> *y;
}

//записывает путь перемещения коня по доске в массив way
//step_num - номер перемещения (максимум SIZE^2) (индекс в массиве way), ибо 1 выполнение функции - 1 перемещение
void setWay(coords* way, bool field[][SIZE], short step_num)
{
  //координаты, на которых сейчас стоит конь (с которых нужно сделать переход)
  short y = way[step_num - 1].y;
  short x = way[step_num - 1].x;
  bool chessIsMoved = false;//true даёт разрешение на следующее перемещение коня
  //если нету выхода за границы поля и данный путь (с каждой проверкой увеличивается значение) не заблокирован
  //и поле, на которое планируется переход, нетронутое
  if (y + 2 < SIZE && x + 1 < SIZE && way[step_num - 1].blocked < 1
    && field[x + 1][y + 2] == false)
  {
    //запись координат в путь
    way[step_num].y = way[step_num - 1].y + 2;
    way[step_num].x = way[step_num - 1].x + 1;
    //установка пути, по которому выполнен переход на данную ячейку
    way[step_num].setedByWay = 1;
    //метка "ячейка занята"
    field[x + 1][y + 2] = true;
    //переход к следующему перемещению
    chessIsMoved = true;
  }
  else if (y + 2 < SIZE && x - 1 >= 0 && way[step_num - 1].blocked < 2
    && field[x - 1][y + 2] == false)
  {
    way[step_num].y = way[step_num - 1].y + 2;
    way[step_num].x = way[step_num - 1].x - 1;
    way[step_num].setedByWay = 2;
    field[x - 1][y + 2] = true;
    chessIsMoved = true;
  }
  else if (y - 2 >= 0 && x + 1 < SIZE && way[step_num - 1].blocked < 3
    && field[x + 1][y - 2] == false)
  {
    way[step_num].y = way[step_num - 1].y - 2;
    way[step_num].x = way[step_num - 1].x + 1;
    way[step_num].setedByWay = 3;
    field[x - 1][y + 2] = true;
    chessIsMoved = true;
  }
  else if (y - 2 >= 0 && x - 1 >= 0 && way[step_num - 1].blocked < 4
    && field[x - 1][y - 2] == false)
  {
    way[step_num].y = way[step_num - 1].y - 2;
    way[step_num].x = way[step_num - 1].x - 1;
    way[step_num].setedByWay = 4;
    field[x - 1][y + 2] = true;
    chessIsMoved = true;
  }
  else if (y + 1 < SIZE && x + 2 < SIZE && way[step_num - 1].blocked < 5
    && field[x + 2][y + 1] == false)
  {
    way[step_num].y = way[step_num - 1].y + 1;
    way[step_num].x = way[step_num - 1].x + 2;
    field[x + 2][y + 1] = true;
    way[step_num].setedByWay = 5;
    chessIsMoved = true;
  }
  else if (y + 1 < SIZE && x - 2 >= 0 && way[step_num - 1].blocked < 6
    && field[x - 2][y + 1] == false)
  {
    way[step_num].y = way[step_num - 1].y + 1;
    way[step_num].x = way[step_num - 1].x - 2;
    way[step_num].setedByWay = 6;
    field[x - 2][y + 1] = true;
    chessIsMoved = true;
  }
  else if (y - 1 >= 0 && x + 2 < SIZE && way[step_num - 1].blocked < 7
    && field[x + 2][y - 1] == false)
  {
    way[step_num].y = way[step_num - 1].y - 1;
    way[step_num].x = way[step_num - 1].x + 2;
    way[step_num].setedByWay = 7;
    field[x + 2][y - 1] = true;
    chessIsMoved = true;
  }
  else if (y - 1 >= 0 && x - 2 >= 0 && way[step_num - 1].blocked < 8
    && field[x - 2][y - 1] == false)
  {
    way[step_num].y = way[step_num - 1].y - 1;
    way[step_num].x = way[step_num - 1].x - 2;
    way[step_num].setedByWay = 8;
    field[x - 2][y - 1] = true;
    chessIsMoved = true;
  }
  else //если нету свободных клеток, на которые можно переместиться, - блокировка данного пути,метка "данная клетка свободна" и откат (возврат на шаг назад)
  {
    way[step_num - 2].blocked = way[step_num - 1].setedByWay;
    field[x][y] = false;
    setWay(way, field, step_num - 1);
  }

  //if (way[SIZE*SIZE].x != way[0].x && way[SIZE*SIZE].y != way[0].y)//если все ходы выполнены, но конь стоит не в нужном месте
  //	setWay(way, field, step_num - 1);//откат

  if (step_num == SIZE*SIZE && way[SIZE*SIZE].x != way[0].x && way[SIZE*SIZE].y != way[0].y)//полный возврат с рекурсии (ну и с функции) только при условии, если данная "итерация" - последняя и {конечная и начальная ячейки совпадают}
    return;

  if(chessIsMoved)
    setWay(way, field, step_num + 1);
}

I used to code shit in php and I know that it’s good to use exceptions in such situations, but we haven’t gone through this and I doubt that in c ++ this will be a solution.
PS: don't judge too harshly - I'm just learning (and yes, this is a procedural programming assignment, not OOP).

Answer the question

In order to leave comments, you need to log in

2 answer(s)
M
maaGames, 2016-02-07
@maaGames

In fact, this problem is solved differently. In chess number grinders, as in any number grinders, you should try to reduce the number of conditions to a minimum. Instead of checking for out-of-bounds matrix (and this is 4 checks, or two if unsigned numbers and overflow are used), the matrix itself is expanded by one on each side and a flag or other "blocking" value is written there.
Although, your condition check begins with checking for out-of-bounds array and the problem with the error should not have been from the beginning ... if the order in the two-dimensional array had not been mixed up. Actually field[y][x].

M
mamkaololosha, 2016-02-07
@mamkaololosha

This is a task for "Backtracking, backtracking". The condition says that it is necessary to use recursion. Cache paths. And when there is nowhere to go, finish the work. Then check the paths and look for the one in which the number of cells visited is 6*6.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question