2015-10-22 1 views
0

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

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 - номер платы, на которую он исследуется)

A [t_i] - это массив структур, элементы структуры состоят из поля char [8] [8].

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

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

здесь сама программа с ИНТОМ основных()

#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; 
} 
+5

'goto' ... почему? Кроме того, эта функция не компилируется ('t_i',' m_x', 'm_y' и, вероятно, больше не объявлены), и в ней отсутствует' main() ', поэтому мы не можем воспроизвести проблему. Вы даже не сообщили нам, что такое * наблюдаемый * выход, только вывод * ожидается *. Я не вижу там отладочной информации, которая может помочь вам определить, где фактическая обработка отличается от ожидаемой. – DevSolar

+0

@DevSolar , потому что я не могу придумать что-то еще, мне нужны разные циклы для вызова других циклов, чтобы закончить проверку. int main - это просто призывы функции, в которой он ищет. вся программа уже имеет длину более 300 строк, я не хочу группировать все. Наблюдаемый результат - ничто. Он ничего не выводит, как если бы между кусками было что-то. Но если вы удалите кусок, он все равно ничего не выводит. – iamtco

+3

Ну, прямо сейчас я занят * письмом * 'int main()', пытаясь понять, как заполнить 'piece A []', поэтому я вижу, что происходит. Если вы разместили [минимальный, полный, проверенный пример] (http://stackoverflow.com/help/mcve) (который является проверенным временем методом отладки при попытке выяснить проблему самостоятельно), я, вероятно, буду написав ответ уже ... – DevSolar

ответ

4

Я сделаю то, что я не» обычно делаю - я дам вам полный тур туда-обратно (потому что мне это нравится).


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

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

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


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

#include <vector> 
#include <iostream> 

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

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


Ваш 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 (который вместо этого переполняется и становится действительно большим), вместо этого вы получите потерю segfault (если вам повезет). Это было фактически непреднамеренно; Я просто объявляю вещи, которые не могут быть отрицательными unsigned от habbit.

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


Кроме того, вы (во всех этих петель) всегда цикл по 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 никогда не случится, верно?


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

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

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

We have a list of recommended textbooks, if the one you have isn't to your tastes.

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


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

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

+2

OP имеет счастливый день;) –

+0

Хороший ответ и хорошие рекомендации. – fjardon