2017-10-19 180 views
-2

我是一个新手,我遇到了一个问题,我似乎无法修复。也就是说,我有这两个独立的代码工作块,但如果我使用它们两个程序崩溃(返回错误代码3221225477)。C++:添加一个逻辑上正确的if语句崩溃我的程序

#include <conio.h> 
#include <iostream> 
#include <string> 
#include <windows.h> 
#include <chrono> 
#include <thread> 
#include <vector> 
#include <time.h> 

#define KEY_UP 72 
#define KEY_DOWN 80 
#define KEY_LEFT 75 
#define KEY_RIGHT 77 
#define ENTER 13 

using namespace std; 

struct set { 
int speed=0; 
bool obs=0; 
} settings; 

void gotoyx(int y, int x) { //moves the console cursor 
COORD coord; 
coord.X = x; 
coord.Y = y; 
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); 
} 

void setup() { //used to determine the snake's speed, expressed as delay between movement 
int c = 0; 
string o1=">SLOW", o2=" MEDIUM", o3=" FAST"; 
while(settings.speed==0) 
{ 
    c = 0; 
    gotoyx(c, c); //sets cursor at top-left 
    cout << "Please choose your speed setting:\n"<< o1 << endl << o2 << endl << o3 << endl; 
    switch((c=getch())) { 
    case KEY_UP: 
     if(o2.at(0)=='>'){ 
      o1[0]='>'; 
      o2[0]=' '; 
     } 
     else if(o3.at(0)=='>'){ 
      o2[0]='>'; 
      o3[0]=' '; 
     } 
     break; 
    case KEY_DOWN: 
     if(o1.at(0)=='>'){ 
      o2[0]='>'; 
      o1[0]=' '; 
     } 
     else if(o2.at(0)=='>'){ 
      o3[0]='>'; 
      o2[0]=' '; 
     } 
     break; 
    case ENTER: 
     if(o1.at(0)=='>') { 
      cout << "You chose SLOW.\n"; 
      settings.speed=160; 
     } 
     else if(o2.at(0)=='>') { 
      cout << "You chose MEDIUM.\n"; 
      settings.speed=120; 
     } 
     else { 
      cout << "You chose FAST.\n"; 
      settings.speed=80; 
     } 
     settings.obs=1; 
     cout << "Press a key to continue."; 
     getch(); 
     break; 
    default: 
     break; 
    } 
} 
} 

void draw_border() { 
for(int i=0; i<80; i++){ //80 fills screen vertically - TOP 
    cout<<"#"; 
} 
for(int i=0; i<23; i++){ //25 fills screen horizontally (2 used for top and bottom) 
    cout<<"#"; 
    for(int i=0; i<78; i++){ 
    cout<<" "; 
    } 
    cout<<"#"; 
} 
for(int i=0; i<80; i++){ //80 fills screen vertically - BOTTOM 
    cout<<"#"; 
} 
} 

void ShowConsoleCursor(bool showFlag) { //blinking-underscore-with-console 
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); 

CONSOLE_CURSOR_INFO  cursorInfo; 

GetConsoleCursorInfo(out, &cursorInfo); 
cursorInfo.bVisible = showFlag; // set the cursor visibility 
SetConsoleCursorInfo(out, &cursorInfo); 
    } 

int keypad(int out){          //reads arrow keys during game 
    if (GetAsyncKeyState(VK_UP) & 0x8000 && out!=1) { //MSB set if currently pressed 
     out=0;           //if nothing is pressed it returns 
    }             //the last pressed button 
    else if (GetAsyncKeyState(VK_DOWN) & 0x8000 && out!=0) { 
     out=1; 
    } 
    else if (GetAsyncKeyState(VK_LEFT) & 0x8000 && out!=3) { 
     out=2; 
    } 
    else if (GetAsyncKeyState(VK_RIGHT) & 0x8000 && out!=2) { 
     out=3; 
    } 
    return out;           
} 

int main() { 
ShowConsoleCursor(false);        //disable blinking console cursor 
setup(); 
int tmp=0, cntr_g=0, cntr_o=0; 
system("cls");           //clear screen after inital setup 
draw_border(); 
gotoyx(tmp, tmp);          //using cursor to scroll to console top 
vector<vector<int>> snake_pos;       //tracks snake location 
snake_pos.emplace(snake_pos.begin(), std::initializer_list<int>{13,40}); 
int y = snake_pos[0][0];        //Y coordinate of snake head 
int x = snake_pos[0][1];        //X coordinate of snake head 
gotoyx(y, x); 
cout<<"*"; 
int key, boost_y, boost_x, obstacle_y, obstacle_x; 
bool b_flag=0; 
vector<vector<int>> boost (1, vector<int>(2, 0)); 
vector<vector<int>> obstacle (1, vector<int>(2, 0)); 
while(1){ 
    key=keypad(key); 
    if (key==0) { 
     snake_pos.emplace(snake_pos.begin(), std::initializer_list<int> {y-1, x}); 
    } 
    else if (key==1) { 
     snake_pos.emplace(snake_pos.begin(), std::initializer_list<int> {y+1, x}); 
    } 
    else if (key==2) { 
     snake_pos.emplace(snake_pos.begin(), std::initializer_list<int> {y, x-1}); 
    } 
    else if (key==3) { 
     snake_pos.emplace(snake_pos.begin(), std::initializer_list<int> {y, x+1}); 
    } 

    y = snake_pos[0][0]; x = snake_pos[0][1];   //updating snake head coordinates 

    if (y==0 | y==24 | x==0 | x==80) {     //checking whether player hit wall 
     return 0; 
    } 
    for (tmp=1; tmp!=snake_pos.size()-1; ++tmp) {  //checking whether player hit self 
     if (y==snake_pos[tmp][0] && x==snake_pos[tmp][1]) { 
      return 0; 
     } 
    } 

    //check if obstacle was hit [not here yet] 

    ++cntr_g;           //generating growth boost block 
    if (cntr_g==settings.speed/5) { 
     label_growth: 
     srand(time(NULL)); 
     boost_x=(rand()%78)+1; 
     boost_y=(rand()%23)+1; 
     for (tmp=0; tmp!=snake_pos.size()-1; ++tmp) { 
      if (boost_y==snake_pos[tmp][0] && boost_x==snake_pos[tmp][1]) { 
       goto label_growth; 
      } 
     } 
     gotoyx(boost_y, boost_x); cout<<"O"; 
     boost.emplace_back(std::initializer_list<int> {boost_y, boost_x}); 
     cntr_g=0; 
    } 

    /* 
    ++cntr_o;            //generating obstacle block 
    if ((cntr_o==settings.speed/4) && (settings.obs==1)) { //also check if obs enabled 
     label_obstacle: 
     srand(time(NULL)); 
     obstacle_x=(rand()%78)+1; 
     obstacle_y=(rand()%23)+1; 
     for (tmp=0; tmp!=snake_pos.size()-1; ++tmp) {  //check overlap with snake 
      if (obstacle_y==snake_pos[tmp][0] && obstacle_x==snake_pos[tmp][1]) { 
       goto label_obstacle; 
      } 
     } 
     for (tmp=0; tmp!=boost.size()-1; ++tmp) {   //check overlap with boosts 
      if (obstacle_y==boost[tmp][0] && obstacle_x==boost[tmp][1]) { 
       goto label_obstacle; 
      } 
     } 
     gotoyx(obstacle_y, obstacle_x); cout<<"X"; 
     obstacle.emplace_back(std::initializer_list<int> {obstacle_y, obstacle_x}); 
     cntr_o=0; 
    }*/ 

    gotoyx(y, x); cout<<"*"; b_flag=0;     //updating graphics for new snake 
    for (tmp=0; tmp!=boost.size()-1; ++tmp) {   
     if (y==boost[tmp][0] && x==boost[tmp][1]) { 
      boost.erase(boost.begin()+tmp); 
      b_flag=1; 
      break; 
     } 
    } 
    if (b_flag==0){          //if snake didn't grow, last block stays 
     gotoyx(snake_pos.back()[0], snake_pos.back()[1]); cout<<" "; 
     snake_pos.pop_back(); 
    } 

    std::this_thread::sleep_for(std::chrono::milliseconds(settings.speed)); 
} 

return 0; 
} 

即是说,问题在于if语句的增长块部分和障碍块部分。程序(游戏)在其中一个被注释掉时按预期工作,但如果两个都被留下,则不会如此。事实上,即使只是在cntr_o++;中没有以下if语句就足以使其崩溃。

+2

我建议你将你的代码分成更小的方法,它会更容易阅读和调试。 – Neo

+0

你应该至少删除那个大的评论块。或者它与问题有关?这只是太多的意大利面 – user463035818

+0

你为什么要比较一个布尔值到1? –

回答

0

编译器是变幻莫测的东西。您的代码可能不正确,并且由于编译器布置内存的偶然方式而仍然不会崩溃。这是“未定义行为”的结果。未定义的行为会导致程序崩溃,但它也可能没有可观察的效果。

虽然您的代码对于随便调试来说有点过于混乱,但您可能会发现调试器可能会有所帮助。 如果您能够使用clang,我建议添加-Wall -Wextra和-fsanitize = address -fsanitize = undefined来捕获一些较简单的问题。