我是 C 语言编程的新手,整体编程技能还很生疏。为了学习 C 并通过一般编程重新定位自己,我正在挑战自己尝试使用 ncurses 制作一个简单的 rougelike。
我已经设置了一个“日志”,我应该能够将消息推送到它 - 应该显示最近的 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] = '#';
}
}
最佳答案
你的问题出在输入阶段。您期望通过箭头键发出定向命令,但每次按键都会产生多个字节。作为命令,除一个外均无效。
作为次要问题,您不会拒绝无效命令。在读取每个命令字符后,您继续移动暴民,无论该命令是否有效。
总的结果是,当你按下一个箭头键时,程序会快速完成主循环的三个迭代,一个紧接着另一个,为一个有效的玩家移动生成日志消息,没有两个无效玩家移动的日志消息,并记录三个暴徒移动中的每一个的消息。
您可以通过记录无效命令或在调试器中运行您的程序来检测到这一点。
关于c - 当只有两次调用时,每个循环调用函数四次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41020564/