スロットゲームみたいなのをC言語で作る（コマンドプロンプト画面）

# プログラム

``` slot.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdbool.h>


#define Frame_no 2
#define FramevMax 9
#define pictMax 7 
#define overFlow 1000000000

int frame[FramevMax + 1][Frame_no + 1];
int count = 0;
int score = 0;
struct timespec startTime, goesTime;
long startnsec, goesnsec,overflow;
bool endflag,scoreflag;
char pictPattern[pictMax][1] = {\
"1"\
,"2"\
,"3"\
,"4"\
,"5"\
,"6"\
,"7"\
};


int kbhit(void)
{
    struct termios oldt, newt;
    int ch;
    int oldf;

    tcgetattr(STDIN_FILENO, &oldt);
    newt = oldt;
    newt.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
    fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

    ch = getchar();

    tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
    fcntl(STDIN_FILENO, F_SETFL, oldf);

    if (ch != EOF)
    {
        ungetc(ch, stdin);
        return 1;
    }

    return 0;
}

void initSlotFrame()
{
  frame[0][0] = 0;
  frame[1][0] = 0;
  frame[2][0] = 0;
  frame[3][0] = 1;
  frame[4][0] = 1;
  frame[5][0] = 2;
  frame[6][0] = 2;
  frame[7][0] = 3;
  frame[8][0] = 3;
  frame[9][0] = 4;

  frame[0][1] = 1;
  frame[1][1] = 0;
  frame[2][1] = 1;
  frame[3][1] = 0;
  frame[4][1] = 0;
  frame[5][1] = 2;
  frame[6][1] = 3;
  frame[7][1] = 2;
  frame[8][1] = 3;
  frame[9][1] = 4;

  frame[0][2] = 4;
  frame[1][2] = 0;
  frame[2][2] = 0;
  frame[3][2] = 2;
  frame[4][2] = 1;
  frame[5][2] = 1;
  frame[6][2] = 3;
  frame[7][2] = 2;
  frame[8][2] = 2;
  frame[9][2] = 0;

  clock_gettime(CLOCK_REALTIME,&startTime);
  startnsec = startTime.tv_nsec;
  goesnsec = goesTime.tv_nsec;
}

void updateSlotFrame()
{
  int w;
  int v;
  int bslot,aslot; 
  for(w = 0; w <= Frame_no; w++)
  {
    bslot = frame[FramevMax][w];
    for(v = 0; v <= FramevMax; v++)
    {
      if(w < count) break;
      aslot = frame[v][w];
      frame[v][w] = bslot;
      bslot = aslot;
    }
  }
}

void animator()
{
  int i;
  int m;

  system("clear");

  for(i = 0; i <= Frame_no; i++)
  {
    for(m = 0; m <= Frame_no; m++)
    {
      printf("  %c  ",pictPattern[frame[i][m]][0]);
    }
    printf("\n");
  }
}

int keyCheck()
{
    if(kbhit())
    {
      switch(getchar())
      {
        case('q'):
          endflag = true;
          break;
      
        case(' '):
          count = (count + 1) % (Frame_no + 2);
          scoreflag = true;
          break;

        default:
          break;
      }
    }
    

    return 0;
} 

int line_match_g = 0;

int lineCheck(int y, int x, int vec_y, int line_match)
{
  if((x + 1) > Frame_no || 0 > (y + vec_y) || (y + vec_y) > Frame_no) return line_match;
  if(frame[y][x] == frame[y + vec_y][x + 1]){ line_match++;}
  else {line_match = 0;}
  line_match = lineCheck(y + vec_y, x + 1, vec_y, line_match);
  return line_match;
}

int scoreCheck()
{
  int y;
  int score_local= 0;
  
  for(y = 0; y <= Frame_no; y++)
  {
    score_local += (((lineCheck(y, 0, 0,0)) / Frame_no) *  (frame[y][0] + 1))  * 100;
    if(y == 0) score_local += (((lineCheck(y, 0, 1,0)) / Frame_no) * (frame[y][0] + 1))  * 100;
    if(y == Frame_no) score_local += (((lineCheck(y, 0, -1,0)) / Frame_no) * (frame[y][0] + 1))  * 100;
  }
  return score_local;
}

int sceneCheck()
{
  if(endflag) exit(EXIT_SUCCESS);

  if(count >= 3 && scoreflag)
  {
    scoreflag = false;
    score += scoreCheck();
  }

  return 0;
}

void timekeeper()
{
  if(((goesnsec + overflow) - (startnsec)) > 200000000 )
    {
      updateSlotFrame();
      animator();
      printf("score %d\n",score);
      startnsec = goesnsec;
      overflow = 0;
    }

  clock_gettime(CLOCK_REALTIME,&goesTime);
  goesnsec = goesTime.tv_nsec;
  
  if((goesnsec - startnsec) <= 0)
  {
    overflow = overFlow - startnsec;
    startnsec = 0;
  }
}

void stopProgram()
{
  fputs("common INPUT",stderr);
  while(getchar()!='\n');
}

void scoreCalc()
{
}

int main()
{
  initSlotFrame();
  
  while(1)
  {
    keyCheck();
    timekeeper();
    sceneCheck();
  }
  
  return 0;
}

```
<dl>
  <dt>goesnsec</dt>
  <dd>常に時間を取得し、その結果を格納</dd>
  <dt>startnsec</dt>
  <dd>「goesnsec」との差分を取得し、「200000000」以上の差分があれば「goesnsec」の値を格納</dd>
</dl>

結果、200000000毎に処理が実施されています。

時間は
```
clock_gettime(CLOCK_REALTIME,&goesTime); 
```
この関数で取得していますが、数値はMAX999999999のため、差分を調べるために開始時間を入れる変数「startnsec」に「999999999」といった極端な数値がもし代入された場合、期待している「200000000」以上の差分が発生しなくなります。
そこで以下のように差分がマイナスになったら、開始時間に「0」を代入し、1000000000 - startnsecの結果をオーバーフロとして変数に格納します。
そうすることで、再び期待している差分が取得可能になります。
次回差分を確認する際に「goesnsec」にオーバーフロー分を足すことで「200000000」という周期が崩れることがなくなります。

```
  if((goesnsec - startnsec) <= 0)
  {
    overflow = overFlow - startnsec;
    startnsec = 0;
  }
```


# あとがき
こういうプログラムを作るときはスレッドとか使わないとダメみたいですね。
作り終わって正解を調べてたらそう思いました。

# 参考にしたURL
kbhit関数
※Linuxにはない

https://hotnews8.net/programming/tricky-code/c-code03


# 編集履歴
20220701　コンパイルエラー修正