C如何在后台运行循环

时间:2017-09-17 11:46:56

标签: c

我正在制作一个“Clicker-Game”。这是我和学校一起做的第一部真正的比赛。我完成了所有游戏代码,但我想在后台循环,每秒后添加geldps(每秒钱数)。 我试过线程,但我真的不明白它,直到明年我们才会知道,所以我问,如果有人能告诉我一个更好的方法在后台制作一个独立于主要的循环程序,并且可以每秒将geldps添加到geld。谢谢。 PS:我很抱歉德国的变数。问你,如果你不知道sth的意思或什么,那可能不是很有条理和一切。

#include <stdio.h>

int geldps=0,geld=0;

int main()
{
 int stand=0, oil=0, Mine=0, Bank=0,standzahl=100, Minezahl=500, Bankzahl=1000, oilzahl=10000, Werkzeug=0, Werkzeugzahl=10;
char input, input2;
float faktor;
do
{
    system("cls");
    faktor=1+Werkzeug/10;
    printf("%c%c%c%c%c%c%c%c%c%c%c\n",201,205,205,205,205,205,205,205,205,205,187);
    printf("   %d$\n",geld);
    printf("%c%c%c%c%c%c%c%c%c%c%c\n",200,205,205,205,205,205,205,205,205,205,188);
    printf(" Space to get money\n U to go to Upgrades\n Escape to leave");
    input=getch();
    if(input==32)
    {
        geld=geld+faktor;
        continue;
    }
    if(input == 117 || input == 85)
    {
        system("cls");
        do
        {
            system("cls");
            printf(" 0 - Tools(10 for 1 more Money)(%d)(%d$)\n 1 - Lemon Stands(%d)(%d$)\n 2 - Mines(%d)(%d$)\n 3 - Banks(%d)(%d$)\n 4 - Oil Refinerys(%d)(%d$)\nBackspace to go back", Werkzeug, Werkzeugzahl, stand, standzahl, Mine, Minezahl, Bank, Bankzahl, oil, oilzahl);
            input2=getch();
            if(input2== 48)
            {
                if(geld<Werkzeugzahl)
                {
                    system("cls");
                    printf("Not enough money(%d/%d$)\n",Werkzeugzahl,geld);
                    system("pause");
                    continue;
                }
                geld=geld-Werkzeugzahl;
                Werkzeug++;
                Werkzeugzahl=Werkzeugzahl+Werkzeugzahl/10;
            }
            if(input2== 49)
            {
                if(geld<standzahl)
                {
                    system("cls");
                    printf("Not enough money(%d/%d$)\n",standzahl,geld);
                    system("pause");
                    continue;
                }
                geld=geld-standzahl;
                stand++;
                standzahl=standzahl+standzahl/10;
            }
            if(input2== 50)
            {
                if(geld<Minezahl)
                {
                    system("cls");
                    printf("Not enough money(%d/%d$)\n",Minezahl,geld);
                    system("pause");
                    continue;
                }
                geld=geld-Minezahl;
                Mine++;
                Minezahl=Minezahl+Minezahl/10;
                geldps=geldps+1;
            }
            if(input2== 51)
            {
                if(geld<Bankzahl)
                {
                    system("cls");
                    printf("Not enough money(%d/%d$)\n",Bankzahl,geld);
                    system("pause");
                    continue;
                }
                geld=geld-Bankzahl;
                Bank++;
                Bankzahl=Bankzahl+Bankzahl/10;
                geldps=geldps+10;
            }
            if(input2== 52)
            {
                if(geld<oilzahl)
                {
                    system("cls");
                    printf("Not enough money(%d/%d$)\n",oilzahl,geld);
                    system("pause");
                    continue;
                }
                    geld=geld-oilzahl;
                    oil++;
                    oilzahl=oilzahl+oilzahl/10;
                    geldps=geldps+100;
                }
            }
            while(input2!=8);
        }
    }
    while(input!=27);
    return 0;
}

1 个答案:

答案 0 :(得分:0)

更新:我拖延并清理和改进了您的代码。在这个答案的最后。

如果您只需要根据时间一致地增加数字,请添加一个根据时间更新值的函数。

以下是一个示例,不仅展示了如何执行此操作,还展示了如何将代码划分为函数以及如何使用更好的代码格式和变量名称。

#include <stdio.h> // printf()
#include <time.h> // time()
#include <stdlib.h> // random()
#include <unistd.h> // sleep()


int updateValue(int lastValue, int amountPerSecond) {
  static time_t lastTime = -1;

  time_t currentTime = time(NULL);
  int newValue = lastValue;

  if (lastTime != -1) {
    newValue += amountPerSecond * (currentTime - lastTime);
  }
  lastTime = currentTime;

  return newValue;
}

void seedRandom() {
  // Don't use this in production code.
  srandom(time(NULL));
}

int sleepRandomly() {
  const int SLEEP_RANGE_IN_SECS = 5;
  // sleep( 0..5 seconds )
  int timeToSleep = random() % (SLEEP_RANGE_IN_SECS + 1);
  sleep(timeToSleep);
  return timeToSleep;
}

int main() {
  const int AMOUNT_PER_SECOND = 5;
  int value = 0;
  // How many times to run the loop
  int numCycles = 5;

  seedRandom();

  // Initialize the updateValue() start time
  value = updateValue(value, AMOUNT_PER_SECOND);

  while (numCycles--) {
    int amountSlept = sleepRandomly();
    int newValue = updateValue(value, AMOUNT_PER_SECOND);
    printf("Slept %d seconds.", amountSlept);
    printf("Value updated: %10d + (%d secs * %4d amount/secs) = %10d\n",
           value, amountSlept, AMOUNT_PER_SECOND, newValue);
    value = newValue;
  }

  return 0;
}

清理了您的代码版本,然后我不断改进它。

#include <stdio.h> // printf()
#include <string.h> // strlen()
#include <stdarg.h> // vsnprintf()
#include <unistd.h> // STDIN_FILENO
#include <sys/time.h> // gettimeofday()
#include <time.h>
#include <termios.h>
#include <errno.h>
#include <signal.h>

// TODO: convert the menus to tables:
//       key - desc   count   cost     effect
// TODO: add all income sources in a list so it's easy to add more
//       without changing code
// TODO: the current pricing is off
// TODO: convert to C++ so we can use classes
// TODO: only use one menu, it's nicer to use

// one global value so we can ensure that we restore
// stdin's terminal settings
struct termios g_oldStdinTermios;
int g_keepGoing = 1;

typedef struct {
  int count;
  int zahl;
  int zahlIncrement;
  int geldPerSecondIncrement;
} IncomeSource;

typedef struct {
  char lastMessage[100];

  // try to avoid global variables, pass them instead
  // one variable per line
  int geld;
  int geldPerSecond;
  int geldPerClick;

  IncomeSource werkzeug;
  IncomeSource stand;
  // Use consistent capitalization: sound be "mine"
  IncomeSource mine;
  IncomeSource bank;
  IncomeSource oil;
} Values;

void setLastMessage(Values *values, const char *fmt, ...) {
  va_list ap;
  va_start(ap, fmt);
  (void) vsnprintf(values->lastMessage, sizeof(values->lastMessage), fmt, ap);
  va_end(ap);
}

void clearLastMessage(Values *values) {
  // clear lastMessage after valid choice
  values->lastMessage[0] = '\0';
}

void initializeValues(Values *values) {
  clearLastMessage(values);

  // use spaces around assignment and operators
  values->geldPerSecond = 0;
  values->geld = 10000;
  // count, cost, cost increment (1/n), geldPerSecond increment
  values->werkzeug = (IncomeSource){0, 10, 10, 0};
  // BUG: number of stands doesn't increase geld per second
  //      or geld per click
  values->stand = (IncomeSource){0, 100, 10, 0};
  values->mine = (IncomeSource){0, 500, 10, 1};
  values->bank = (IncomeSource){0, 1000, 10, 10};
  values->oil = (IncomeSource){0, 10000, 10, 100};

  values->geldPerClick = 1 + values->werkzeug.count / 10;
}

void clearScreen() {
  // use ANSI escape sequences
  const char *ANSI_MOVE_TO_1_1 = "\x1B[1;1H";
  const char *ANSI_CLEAR_SCREEN = "\x1B[2J";
  printf("%s%s", ANSI_CLEAR_SCREEN, ANSI_MOVE_TO_1_1);
}

char upcase(char c) {
  if (c < 'a' || c > 'z') {
    return c;
  }
  return 'A' + (c - 'a');
}

void setNonBlockingBufferingStdinTermios() {
  struct termios new_;
  tcgetattr(STDIN_FILENO, &g_oldStdinTermios);
  new_ = g_oldStdinTermios;
  new_.c_lflag &= ~ICANON;
  tcsetattr(STDIN_FILENO, TCSANOW, &new_);
}

void restoreStdinTermios() {
  tcsetattr(STDIN_FILENO, TCSANOW, &g_oldStdinTermios);
}

long getElapsedTimeInMs(struct timeval *start) {
  struct timeval now;
  gettimeofday(&now, NULL);
  // in microseconds
  long elapsed = ((now.tv_sec - start->tv_sec) * 1000000
                  + now.tv_usec - start->tv_usec);
  return elapsed / 1000;
}

char getCharacter() {
  struct timeval start;
  gettimeofday(&start, NULL);

  char input = -1;
  while (read(STDIN_FILENO, &input, 1) == -1
         && errno == EAGAIN
         && getElapsedTimeInMs(&start) < 500) {
  }

  return upcase(input);
}

void updateGeld(Values *values) {
  static time_t lastTime = -1;

  time_t currentTime = time(NULL);
  if (lastTime != -1) {
    values->geld += values->geldPerSecond * (currentTime - lastTime);
  }
  lastTime = currentTime;
}

void printHeader(Values *values) {
  const char *UPPER_LEFT = "\u2554";
  const char *UPPER_RIGHT = "\u2557";
  const char *LOWER_LEFT = "\u255a";
  const char *LOWER_RIGHT = "\u255d";
  const char *HORIZONTAL = "\u2550";
  const char *VERTICAL = "\u2551";

  updateGeld(values);

  // Automatically expand the box as the size
  // of geld grows.
  const int BORDER_WIDTH = 3;
  char geldStr[20];
  snprintf(geldStr, sizeof(geldStr), "$ %d", values->geld);

  // Move code used more than once into its own function
  clearScreen();

  printf("%s", UPPER_LEFT);
  for (int i = 0; i < (2 * BORDER_WIDTH + strlen(geldStr)); i++) {
    printf("%s", HORIZONTAL);
  }
  printf("%s\n", UPPER_RIGHT);

  // use spaces around commas
  printf("%s   %s   %s   %s\n",
         VERTICAL, geldStr, VERTICAL, values->lastMessage);

  printf("%s", LOWER_LEFT);
  for (int i = 0; i < (2 * BORDER_WIDTH + strlen(geldStr)); i++) {
    printf("%s", HORIZONTAL);
  }
  printf("%s\n", LOWER_RIGHT);
}


void upgrade(Values *values, IncomeSource *source) {
  if (values->geld < source->zahl) {
    setLastMessage(values, "Not enough money(%d/%d$)",
                   source->zahl, values->geld);
    return;
  }
  clearLastMessage(values);
  values->geld -= source->zahl;
  source->count++;
  source->zahl += source->zahl / source->zahlIncrement;
  values->geldPerSecond += source->geldPerSecondIncrement;
}

char getUpgradeInput(Values *values) {
  clearScreen();
  printHeader(values);
  printf(" 0 - Tools(10 for 1 more Money)(%d)(%d$)\t\t+%d/click\n",
         values->werkzeug.count, values->werkzeug.zahl, values->geldPerClick);
  printf(" 1 - Lemon Stands(%d)(%d$)\t\t\t+%d/sec\n",
         values->stand.count, values->stand.zahl,
         values->stand.count * values->stand.geldPerSecondIncrement);
  printf(" 2 - Mines(%d)(%d$)\t\t\t\t+%d/sec\n",
         values->mine.count, values->mine.zahl,
         values->mine.count * values->mine.geldPerSecondIncrement);
  printf(" 3 - Banks(%d)(%d$)\t\t\t\t+%d/sec\n",
         values->bank.count, values->bank.zahl,
         values->bank.count * values->bank.geldPerSecondIncrement);
  printf(" 4 - Oil Refinerys(%d)(%d$)\t\t\t+%d/sec\n",
         values->oil.count, values->oil.zahl,
         values->oil.count * values->oil.geldPerSecondIncrement);
  printf(" Q - Back to main menu\n");
  printf("> ");
  fflush(stdout);
  return getCharacter();
}

void upgradeLoop(Values *values) {
  char input = ' ';
  while (input != 'Q' && g_keepGoing) {
    input = getUpgradeInput(values);
    switch (input) {
    case '0':
      upgrade(values, &values->werkzeug);
      values->geldPerClick = 1 + values->werkzeug.count / 10;
      break;
    case '1':
      upgrade(values, &values->stand);
      break;
    case '2':
      upgrade(values, &values->mine);
      break;
    case '3':
      upgrade(values, &values->bank);
      break;
    case '4':
      upgrade(values, &values->oil);
      break;
    case 'Q':
      break;
    default:
      break;
    }
  }
}

char getMainInput(Values *values) {
  printHeader(values);

  // make this easier to read in the code...
  printf(" _ - [Space] get money\n");
  printf(" U - Upgrades\n");
  printf(" Q - Quit\n");
  printf("> ");
  fflush(stdout);
  return getCharacter();
}

void mainLoop(Values *values) {
  char input = ' ';

  // while..do is easier to read and understand than do..while
  while (input != 'Q' && g_keepGoing) {
    // Encapsulate code in functions to make your program's logic
    // easier to follow
    input = getMainInput(values);
    // Use a switch statement here and use character values
    // rather than integers
    switch (input) {
    case ' ':
      values->geld += values->geldPerClick;
      clearLastMessage(values);
      break;
    case 'U':
      upgradeLoop(values);
      clearLastMessage(values);
    case 'Q':
      break;
    default:
      break;
    }
  };
}

void sigintHandler(int signal) {
  printf("SIGINT received, cleaning up.\n");
  restoreStdinTermios();
  g_keepGoing = 0;
}

int main() {
  Values values;

  initializeValues(&values);
  setNonBlockingBufferingStdinTermios();
  signal(SIGINT, sigintHandler);

  mainLoop(&values);

  restoreStdinTermios();
  return 0;
}