当只有两次调用时,每个循环调用函数四次

Function is being called four times per loop when there are only two calls to it

我对 C 语言编程还很陌生,总体上编程技能还很生疏。为了学习 C 并重新定位自己的编程,我正在挑战自己尝试使用 ncurses 制作一个简单的 rougelike。

我已经设置了一个 "log",我应该可以将消息推送到它 - 应该显示最近的 10 条消息。为了测试这一点,我已经做到了,每次玩家或非常简单的随机移动的暴民迈出一步时,都会推送一条日志消息说 "step [direction]"。然而,尽管他们每人只走了一步,但出于某种原因,有四条消息被推送到日志中。倒数第二个始终是角色移动的实际方向,我推测其他两个之一是暴徒移动,但我不知道其他两个的来源。有没有人在我的代码中发现任何可能导致此问题的明显问题?感谢所有帮助,谢谢!

(我认为唯一需要查看的主要相关部分应该是 main() 函数、pushToLog()printLog()moveCreature()。也就是说,有问题可能出在其他地方。我不确定。)

#include <stdlib.h>
#include <stdio.h>
#include <ncurses.h>
#include <unistd.h>
#include <string.h>

#define up 65
#define down 66
#define right 67
#define left 68
#define quit 113

struct creature {
  int x;
  int y;
  int hp;
  int maxhp;
};

void setupMap();
struct creature setupCreature();
void moveCreature();
void pushToLog();
void printLog();

int breakFlag = FALSE;

char mapShape[15][15];
char mapFeatures[15][15];
char outputLog[10][60];

int main(int argc, char *argv[]){
  struct creature player = setupCreature(4, 4, 100, 100);
  struct creature mob = setupCreature(5, 7, 100, 100);
  setupMap();
  initscr();
  noecho();
  curs_set(FALSE);

  while(1){
    for (int i = 0; i < 15; i++){
      for (int c = 0; c < 15; c++){
        mvprintw(c, i, "%c", mapShape[i][c]);
      }
    }
    mvprintw(player.y, player.x, "%c", '@');
    mvprintw(mob.y, mob.x, "%c", 'd');
    printLog();

    int input = getch();
    moveCreature(input, &player);

    int mobDir = rand() % (68 + 1 - 65) + 65;
    moveCreature(mobDir, &mob);

    refresh();
    usleep(300);

    if (breakFlag == TRUE){
      break;
    }
  }

  endwin();
  return 0;
}


void moveCreature(int dir, struct creature *subject){
  int next;

  if (dir == up){
    next = (subject->y - 1);
    if (mapShape[subject->x][next] != '#'){
      subject->y = next;
      pushToLog("step up     ");
    }
  }
  else if (dir == down){
    next = (subject->y + 1);
    if (mapShape[subject->x][next] != '#'){
     subject->y = next;
     pushToLog("step down     ");
    }
  }
  else if (dir == right){
    next =  (subject->x + 1);
    if (mapShape[next][subject->y] != '#'){
      subject->x = next;
      pushToLog("step right     ");
    }
  }
  else if (dir == left){
    next =  (subject->x - 1);
    if (mapShape[next][subject->y] != '#'){
      subject->x = next;
      pushToLog("step left     ");
    }
  }

  else if (dir == quit){
    breakFlag = TRUE;
  }

}

void pushToLog(char string[]){
  for (int i = 10; i > 0; i--){
    strcpy(outputLog[i], outputLog[i-1]);
  }
  strcpy(outputLog[0], string);
}

void printLog(){
  for (int i = 0; i < 10; i++){
    mvprintw(28-i, 0, outputLog[i]);
  }
}


struct creature setupCreature(int x,int y,int hp,int maxhp){

  struct creature frankenstien;

  frankenstien.x = x;
  frankenstien.y = y;
  frankenstien.hp = hp;
  frankenstien.maxhp = maxhp;

  return frankenstien;
}


void setupMap(){
  for (int i = 0; i < 15; i++){
    for (int c = 0; c < 15; c++){
      mapShape[i][c] = '.';
    }
  }
  for (int i = 0; i < 15; i++){
    mapShape[0][i] = '#';
    mapShape[14][i] = '#';
    mapShape[i][0] = '#';
    mapShape[i][14] = '#';
  }
}

你的问题出在输入阶段。您期望通过箭头键发出定向命令,但每次按键都会生成多个字节。除一个以外的所有命令均无效。

作为次要问题,您不拒绝无效命令。在读取每个命令字符后,您继续移动暴民,无论该命令是否有效。

总的结果是,当您按下箭头键时,程序会快速完成主循环的三次迭代,一次又一次,为一个有效的玩家移动生成日志消息,没有为两个无效玩家生成日志消息移动,并记录三个暴民移动中每一个的消息。

您可以通过记录无效命令或通过 运行 您在调试器中的程序检测到这一点。