Функция движения ладьи не находит прерываний

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

    void rook_white(piece A[])                                      // does WR check BK
{
cout << "Found White Rook ";
int k_x;                                                  // BK'S x coordinate
int k_y;                                                  // BK's y coordinate
bool check = false;
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x-x][m_y] == 'k')                 // Moving Left
{
k_x=m_x;
k_y=m_y;
goto al_1;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x+x][m_y] == 'k')                 // Moving Right
{
k_x=m_x;
k_y=m_y;
goto al_2;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x][m_y-y] == 'k')                 // Moving Up
{
k_x=m_x;
k_y=m_y;
goto al_3;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x][m_y+y] == 'k')                 // Moving Down
{
k_x=m_x;
k_y=m_y;
goto al_4;
}
}
}
al_1:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x-x][m_y] == '*')                   // Checking left
{
goto loop_exit;
}
}
}
al_2:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x+x][m_y] == '*')                    // Checking Right
{
goto loop_exit;
}
}
}
al_3:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x][m_y-y] == '*')                    // Checking Up
{
goto loop_exit;
}
}
}
al_4:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x][m_y+y] == '*')                    // Checking Down
{
goto loop_exit;
}
}
}
loop_exit:
check = false;
if (check == true)
{
ofstream fr(FVR,ios::app);
fr << "Black is in check by rook " << t_i << endl;
}
}

Функция ищет, где находится король по осям x и y. Затем он переходит к определенному алгоритму (al_1, al_2, …), в котором он ищет, есть ли что-нибудь между королем и ладьей.

Входной файл является чем-то вроде этого:

********
***k****
********
***q****
********
********
***R****
********

это не должно ничего выводить, пока

********
***k****
********
********
********
********
***R****
********

должен вывести «Черные находятся под контролем ладьи». (t_i — номер доски, на которой он рассматривается)

[T_i] является массивом struct, части структуры состоят из поля char [8] [8].

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

k_x и k_y — координаты короля.
m_x и m_y — это глобальные переменные, которые передаются из функции поиска, в которой найден фрагмент

вот сама программа с int main ()

#include <iostream>
#include <fstream>                  // chess
#include <cstdlib>
using namespace std;                                                       // PROGRAM CHECKS FOR CHESS CHEKS
const char FVD[]="5_input.txt";                                 // **************************************************
const char FVR[]="5_output.txt";                                // P - white pawn   (WP)      p - black pawn     (BP)
//---                                                           // R - white rook   (WR)      r - black rook     (BR)
//---                                                           // B - white bishop (WB)      b - black bishop   (BB)
int m_i=0;          // max i                                    // N - white knight (WN)      n - black knight   (BN)
int m_x=0;          //                                          // Q - white queen  (WQ)      q - black queen    (BQ)
int m_y=0;          //                                          // K - white king   (WK)      k - black king     (BK)
int t_i=0;          //                                          // **************************************************
struct piece
{
char field[8][8];
};
void read(piece A[])
{
ifstream fd(FVD);
int i=0;
m_i=0;
while(!fd.eof())
{
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
fd >> A[i].field[x][y];
}
}
fd.ignore();
i++;
m_i=i;
}
fd.close();
}
///  ----------------------------------------------BLACK KING IS IN CHECK--------------------------------------------------------------
void rook_white(piece A[])                                      // does WR check BK
{
cout << "Found White Rook ";
int k_x;                                                  // BK'S x coordinate
int k_y;                                                  // BK's y coordinate
bool check = false;
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x-x][m_y] == 'k')                 // Moving Left
{
k_x=m_x;
k_y=m_y;
goto al_1;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x+x][m_y] == 'k')                 // Moving Right
{
k_x=m_x;
k_y=m_y;
goto al_2;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x][m_y-y] == 'k')                 // Moving Up
{
k_x=m_x;
k_y=m_y;
goto al_3;
}
}
}
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(A[t_i].field[m_x][m_y+y] == 'k')                 // Moving Down
{
k_x=m_x;
k_y=m_y;
goto al_4;
}
}
}
al_1:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x-x][m_y] == '*')                   // Checking left
{
goto loop_exit;
}
}
}
al_2:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x+x][m_y] == '*')                    // Checking Right
{
goto loop_exit;
}
}
}
al_3:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x][m_y-y] == '*')                    // Checking Up
{
goto loop_exit;
}
}
}
al_4:
for(int x=0; x<k_x; x++)
{
for(int y=0; y<k_y; y++)
{
if(!A[t_i].field[m_x][m_y+y] == '*')                    // Checking Down
{
goto loop_exit;
}
}
}
loop_exit:
check = false;
if (check == true)
{
ofstream fr(FVR,ios::app);
fr << "Black is in check by rook " << t_i << endl;
}
}
///-----------------------------------------SEARCHING FOR THE CHECKS // CALLING FUNCTIONS --------------------------------------------
void search(piece A[])                                               // searches for piece and calls a function related to it
{
for(int i=0; i<m_i-1; i++)
{
for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if (A[i].field[x][y]=='R')
{
t_i=i;
m_x=x;
m_y=y;
rook_white(A);
}

}
}
}
}
int main()
{
piece A[10];
remove(FVR);            // clears the output before inputting new data because of ios::app
read(A);
search(A);
ofstream fr(FVR);
fr << "Done";
return 0;
}

0

Решение

Я сделаю то, что обычно не делаю — я дам вам полный круговой тур (потому что мне так хочется).


Вы начали с main() который должен прочитать произвольное количество полей (но на самом деле происходит сбой 11-го числа), и search() функция, которая предназначена для того, чтобы в конечном итоге перебирать все возможные шахматные фигуры … но ваша программа не проходит проверку на первую фигуру, белую ладью.

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

Итак, давайте урезать это. Во-первых, мы добавим «минимальный» в ваш пример кода.


Давайте использовать <vector> вместо двумерного массива. Векторы являются одним из большинство полезных вещей в C ++, и на самом деле практически нет причин для использования массивов в стиле C (за исключением, возможно, совместимости с C API).

#include <vector>
#include <iostream>

typedef std::vector< std::vector< char > > Field;

Field теперь псевдоним для вектора векторов chars. Это в основном так же, как двумерный массив (включая [][] адресации), но у него есть некоторые преимущества, как вы скоро увидите.


Ваш rook_white() (как вы это спроектировали) необходимо один поле и координаты X и Y ладьи. Позвольте мне немного настроить прототип вашей функции — мне нравится более выразительные имена идентификаторов.

void rook_white( Field const & field, unsigned rook_x, unsigned rook_y );

Поиск и удаление A[t_i].Пока мы работаем только над этим полем. Поиск и замены m_x с rook_x а также m_y с rook_y, Не слишком сложно. Также замените:

        ofstream fr(FVR,ios::app);
fr << "Black is in check by rook " << t_i << endl;

С:

        std::cout << "Black is in check by rook" endl;

На данный момент мы не беспокоимся о файловом вводе / выводе.


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

int main()
{
Field field( 8, std::vector< char >( 8, '*' ) );

std::vector< char >( 8, '*' ) создает временный вектор из 8 '8' символы. Field field( 8, /*...*/ ); создает Field состоящий из 8 копий этого временного вектора.

Теперь давайте разместим ваши кусочки.

    unsigned rook_x = 3;
unsigned rook_y = 6;
field[rook_x][rook_y] = 'R';

unsigned king_x = 3;
unsigned king_y = 1;
field[king_x][king_y] = 'k';

На данный момент я понял, ваш пример кода перепутал координаты «X» и «Y» в search() (сообщает о ладье в X = 6, Y = 3), но не имеет значения. Это не источник ваших проблем.

Теперь у нас есть поле и координаты для вызова вашей функции.

    rook_white( field, rook_x, rook_y );
return 0;
}

Этот способ написания main() это на самом деле не отражает то, что должно делать ваше окончательное приложение, а скорее настраивает тест для определенной функциональности, называется тест-водитель. Мы только что убрали более 50 строк ненужного кода из вашего примера, устраняя все виды потенциальных проблем.


Теперь давайте посмотрим на rook_white(), А не ___ ли нам?


Так как теперь у нас есть vector< vector< char > > вместо «тупого» массива мы могли бы сделать что-то изящное: заменить [] доступ с .at(), Причина? Если индекс до [] выходит за пределы допустимого, это может привести к сбою программы. Если индекс до .at() вне границ, это будут бросить исключение.

Так что пока .at() (немного) медленнее и обычно не используется в производственном коде, я рекомендую его для начинающих, потому что он не позволяет ошибкам «прятаться».

В этот момент вы должны изогнуть бровь и подумать про себя: «Почему он это предлагает?». Тогда вы должны посмотреть на свои петли, и …

for(int x=0; x<8; x++)
{
for(int y=0; y<8; y++)
{
if(field[rook_x-x][rook_y] == 'k')
{
k_x=rook_x;
k_y=rook_y;
goto al_1;
}
}
}

Да, точно. У тебя есть за пределами доступа на ваше поле.

rook_x / rook_y где-то посреди поля, но вы настаиваете на доступе к чему-либо до [rook_x - 7][rook_y] если вы не можете найти короля. Это был отрицательный показатель в вашем исходном коде. Так как я изменил координаты на unsigned (который вместо этого переполняется и становится действительно большой) вместо этого вы получите аварийное завершение (если вам повезет). Это было на самом деле непреднамеренно; Я просто заявляю, что не может быть отрицательным unsigned по привычке.

Но именно поэтому я предложил использовать vector<>«s .at() метод, пока вы еще учитесь: провалиться как можно раньше и как можно громче. Исключение лучше, чем неопределенное поведение.


Кроме того, вы делаете (во всех этих циклах) всегда зацикливаться x а также y, но только использовать один из двух переменных внутри петля. Это много потраченные впустую такты. То, что это не сломает ваш логик, это просто шанс …

На данный момент вы, вероятно, хотите полностью переработать ваш код. Но подождите, это еще не все.


Если вы «двигаетесь влево» в первом цикле и найдете там короля, вы goto al_1, Там вы зацикливаетесь (снова используя только один из двух счетчиков циклов), чтобы проверить наличие промежуточных фрагментов.

Первый цикл x == 0, проверка [rook_x - 0][rook_y]… ну угадай что, Вы находите, что белая ладья вмешивается там, так как нет '*' в этой области, так что вы переходите к loop_exit


И даже если бы ты не сделал эту ошибку, вы бы вышли из этого цикла и войти al_2, проверяя все остальные направления для ладьи, а также


И даже если бы всего этого не случилось, неважно, что произойдет, вы в конечном итоге столкнулись с этим:

loop_exit:
check = false;
if (check == true)
{
std::cout << "Black is in check by rook \n";
}

Хорошо, что check == true никогда не случится, право?


На данный момент я цитирую один из ваших комментариев …

…Я просто не понимаю [заявления о переключении] и не могу понять, как написать их как переключатель.

Мое предложение? Я полностью понимаю, почему вы хотите написать «что-то реальное» как можно быстрее. Учебники скучные. Но ты действительно следует потратить еще немного времени на то, чтобы «обернуть голову» основными понятиями. C и C ++ — это языки, которые не очень хорошо работают с «пробной версией». & ошибка «приближается изучать их. Просто слишком много может и не получится.

У нас есть список рекомендуемых учебников, если он вам не по вкусу.

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


И пожалуйста:

Не использовать goto если только вы абсолютно точно не знаете, что делаете.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]