2013-09-24 3 views
0

Вот мой код:Почему этот код генерирует исключение нарушения доступа?

#include <SFML/Window.hpp> 
#include <SFML/Graphics.hpp> 
#include <SFML/Text.hpp> 
#include <iostream> 

using namespace std; 

class Game 
{ 
    private: 

     bool kratka[9]; 
     bool tak; 

     sf::RenderWindow okno; 

     sf::Image ikolo; 
     sf::Image ikrzyz; 

     sf::Texture tkolo; 
     sf::Texture tkrzyz; 

     sf::Sprite kolo[9]; 
     sf::Sprite krzyz[9]; 

     sf::Sprite minkz; 
     sf::Sprite minko; 

     sf::Vector2f vec; 
     sf::Vector2i mouse; 

     sf::Font font; 

     sf::Text Gracz1; 
     sf::Text Gracz2; 

     sf::Text wynik1; 
     sf::Text wynik2; 

     sf::Texture tkrata; 
     sf::Texture spowtorz; 

     sf::Sprite powtorz; 
     sf::Sprite skrata[9]; 
     int ikr[9]; // zmienne odpowiadajace za logiczna wartosc kraty 
     int rzad[8]; //kombinacje rzedow 

     int player1; 
     int player2; 

     string sp1; 
     string sp2; 

     void update_licznik(); 

     static const int krata=150; 

     void process(); 
     void update(); 
     void render(); 

     bool jestna(sf::Sprite &sp); 
     bool gracz; 

    public: 
     Game(); 
     void run(); 
}; 

Game::Game():okno(sf::VideoMode(800,600,32),"Kolko i krzyzyk") 
{ 
    tkrata.loadFromFile("sprites/kratka.png"); 
    ikolo.loadFromFile("sprites/kolo.png"); 
    ikrzyz.loadFromFile("sprites/krzyz.png"); 
    spowtorz.loadFromFile("sprites/powtorz.png"); 
    ikrzyz.createMaskFromColor(sf::Color(255,255,255),0); 
    ikolo.createMaskFromColor(sf::Color(255,255,255),0); 

    okno.setFramerateLimit(30); 

    tkolo.loadFromImage(ikolo); 
    tkrzyz.loadFromImage(ikrzyz); 

    minkz.setTexture(tkrzyz); 
    minkz.setPosition(670,270); 
    minkz.setScale(0.7,0.7); 

    minko.setTexture(tkolo); 
    minko.setPosition(0,270); 
    minko.setScale(0.7,0.7); 

    for(int i=0;i<3;i++) 
    { 
     for(int j=0;j<3;j++) 
     { 
      kolo[3*i+j].setTexture(tkolo); 
      krzyz[3*i+j].setTexture(tkrzyz); 
      kolo[3*i+j].setPosition(i*150+175,j*150+75); 
      krzyz[3*i+j].setPosition(i*150+175,j*150+75); 
     } 
    } 

    font.loadFromFile("sprites/poseiAOE.ttf"); 
    Gracz1.setFont(font); 
    Gracz1.setString("Gracz 1"); 
    Gracz1.setCharacterSize(70); 

    Gracz2.setFont(font); 
    Gracz2.setString("Gracz 2"); 
    Gracz2.setCharacterSize(70); 
    Gracz2.setPosition(650,0); 

    wynik1.setFont(font); 
    wynik2.setFont(font); 
    wynik1.setCharacterSize(300); 
    wynik2.setCharacterSize(300); 
    wynik1.setPosition(25,0); 
    wynik2.setPosition(700,0); 

    powtorz.setTexture(spowtorz); 
    powtorz.setPosition(640,440); 

    player2=0; 
    player2=0; 

    for(int i=0;i<9;i++) 
    { 
     ikr[i]=0; 
     rzad[i]=0; 
    } 
    for(int i=0;i<3;i++) 
    { 
     for(int j=0;j<3;j++) 
     { 
      skrata[3*i+j].setTexture(tkrata); 
      skrata[3*i+j].setPosition(i*150+175,j*150+75); 
     } 
    } 


} 

void Game::update_licznik() 
{ 
    sp1=to_string(player1); 
    sp2=to_string(player2); 
    wynik1.setString(sp1); 
    wynik2.setString(sp2); 
} 


bool Game::jestna(sf::Sprite &sp) 
{ 
    vec=sp.getPosition(); 
    mouse=sf::Mouse::getPosition(okno); 

    if(mouse.x>vec.x && mouse.x<vec.x+krata && mouse.y>vec.y && mouse.y<vec.y+krata) 
     return true; 
    else 
     return false; 
} 

void Game::process() 
{ 
    sf::Event zdarzenie; 
    while(okno.pollEvent(zdarzenie)) 
    { 
     for(int i=0;i<9;i++) 
     { 
      if(zdarzenie.type==sf::Event::MouseButtonPressed && jestna(skrata[i]) && ikr[i]==0) 
      { 
       gracz=!gracz; 
       if(gracz) 
        ikr[i]++; 
       else 
        ikr[i]--; 
      } 
      if(zdarzenie.type==sf::Event::MouseButtonPressed && jestna(powtorz)) 
      { 
       for(int i=0;i<9;i++) 
       { 
        ikr[i]=0; 
       } 
      } 
     } 

     if(zdarzenie.type==sf::Event::Closed) 
      okno.close(); 
    } 
} 

void Game::update() 
{ 
    update_licznik(); 
    rzad[0]=ikr[0]+ikr[1]+ikr[2]; 
    rzad[1]=ikr[0]+ikr[3]+ikr[6]; 
    rzad[2]=ikr[2]+ikr[5]+ikr[8]; 
    rzad[3]=ikr[6]+ikr[7]+ikr[8]; 
    rzad[4]=ikr[3]+ikr[4]+ikr[5]; 
    rzad[5]=ikr[1]+ikr[4]+ikr[7]; 
    rzad[6]=ikr[0]+ikr[4]+ikr[8]; 
    rzad[7]=ikr[2]+ikr[4]+ikr[6]; 
    for(int i=0;i<8;i++) 
    { 
     if(rzad[i]==3) 
     { 
      player1++; 
      rzad[i]=0; 
      for(int i=0;i<9;i++) 
       ikr[i]=0; 

     } 
     if(rzad[i]==-3) 
     { 
      player2++; 
      rzad[i]=0; 
      for(int i=0;i<9;i++) 
       ikr[i]=0; 
     } 
    } 
} 

void Game::render() 
{ 
    okno.clear(); 
    for(int i=0;i<9;i++) 
    { 
     okno.draw(skrata[i]); 
     if(ikr[i]==1) 
      okno.draw(kolo[i]); 
     if(ikr[i]==-1) 
      okno.draw(krzyz[i]); 
    } 
    okno.draw(Gracz1); 
    okno.draw(Gracz2); 
    okno.draw(wynik1); 
    okno.draw(wynik2); 
    okno.draw(powtorz); 
    okno.draw(minkz); 
    okno.draw(minko); 
    okno.display(); 
} 

void Game::run() 
{ 
    while(okno.isOpen()) 
    { 
     process(); 
     update(); 
     render(); 
    } 
} 

int main() 
{ 
    Game game; 
    game.run(); 
    return 0; 
} 

Каждый раз, когда я запускаю этот код, я получаю следующее исключение:

Unhandled exception at 0x505D4361 (msvcr110d.dll) in Gra1.exe: 0xC0000005: Access violation reading location 0xCCCCCCCC 
+0

Вы должны уменьшить свой код, чтобы получить [sscce] (http://sscce.org/). Это помогает определить, где вы терпите крах. Кроме того, отладчик поможет ** LOT **. – Hiura

+0

В конструкторе 'Game'' rzad [i] = 0; 'будет переполнение в последней итерации из-за' rzad [8] '. Кроме того, вы дважды инициализируете 'player2', вы опускаете' player1'. – ch0kee

ответ

-1

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

Вышеприведенный код не должен компилироваться из-за того, что SFML/Text.hpp не является допустимым заголовком.

using namespace std; - это, в основном, плохо, и если это сделано в глобальном масштабе, это просто неправильно. Пространства имен доступны для: a) предотвращения конфликтов имен и b) делают его очевидным, откуда начинается класс, поэтому в большинстве случаев вам не должно быть using пространства имен.

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

Как отметил ch0kee в комментариях, rzad столкнется с переполнением. К сожалению, приложение все еще может работать, из-за того, что доступ к элементу после последнего в массиве гарантированно является допустимым указателем, и если вы присвоите ему 0, вам может повезти в некоторых случаях. Несмотря на то, что «указатель» будет действителен, вы не должны писать или читать его содержимое. Вы можете предотвратить такие проблемы, используя std::vector или с C++ 11 std::array, который связывает данные с его размером, что позволяет проводить точную и более полную проверку ошибок.

В proccess() и update() вы используете for петлю для перебора массивов, но вы используете несколько раз превышают индексную переменную i, таким образом, затмевают другой индекс. Вы должны всегда использовать разные индексы для вложенных циклов, а не только для того, чтобы можно было использовать индексы выше, но также и для уменьшения путаницы.

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

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

+0

Вы правы с использованием информации о пространстве имен, но в этом случае кажется, что это всего лишь один большой файл mama cpp, поэтому для тестирования просто проще использовать пространство имен, а не печатать. Но вы правы, НИКОГДА не добавляйте инструкцию 'using' внутри файла заголовка. –

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