Lenny`s Dairy Notes

とある大学生のブログ

ビンゴーゲーム

去年の講義の課題でビンゴーゲームを作ったのですが、よくこんなものが書けたなと感心してしまいました。今の自分に同じようなものを作れと言われると、書ける自信がありません。

アルゴリズム自体というよりも、プレイヤーがプレイしやすいようにUIとかを色々考えているのがほんとに素晴らしいと思うし、昔の自分を褒めてあげたい。

ただ、今の自分が与えられるアドバイスとしては、入力を整数型(int)じゃなくて、文字列型(char)にした方が、入力エラーに対応できるんじゃないかとおもいますねぇ。

/* ビンゴゲーム */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 5
#define M 100

/* ビンゴのカードをを作る */
/* 111は閉じている、100は開いている */
void card(int s[][N], int n[][N])
{
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < N; j++) {
            s[i][j] = 111;
            n[i][j] = 0;
        }
    }
            s[N/2][N/2] = 100;
            n[N/2][N/2] = 1;
}

/* カードの状態を出力する */
/* 見やすくするため111はX、100はOにする */
void out(int s[][N])
{
    for(int i = 0; i < N; i++) {
        for(int j = 0; j < N; j++) {
            if(s[i][j] == 111)
                printf("  X ");
            else if(s[i][j] == 100)
                printf("  O ");
            else printf("%3d ", s[i][j]);
        }
        printf("\n");
    }
    printf("\n\n\n");
}

int main(void)
{
    int i, j, k, a[N][N], s[N][N], n[N][N], x[M], y[M], c, L, A, fa, fb, fc, fd, z;

/* ゲームのイントロ */
    printf("\n-----> BINGO GAME <-----\n\n");
    printf("何回挑戦する?(5 ~ 100): ");
    scanf("%d", &L);
    printf("\n\n[0 ~ 99 の数を入力してね]\n\n");

    card(s, n);     out(s);     //カードを出力

/* 数字の被り防止のため、0~99を配列に入れ真理値を1にする */
    for(i = 0; i < M; i++) {
        x[i] = 1;      y[i] = 1;
    }

/* 乱数でカードに数字を振り分ける */ 
/* 被る数があればやり直す */
    srand(time(NULL));
    for(i = 0; i < N; i++) {
        j =0;
        while(j < N) {
            k = rand() % M;
            if(x[k] == 1)    {
                a[i][j] = k;
                x[k] = 0;
            }
            else continue;
            j++;
        }
    }
    
    a[N/2][N/2] = 100;       //カードの中心は入力値の範囲外で常に真

    //out(a);          //デバッグ用、onにすると予めに答えがわかる

/* 入力値がカードの値に一致するかどうか、ビンゴの判定、カウント */
    c = L;
    while(c > 0) {                                            //挑戦回数のカウント
        printf("あと %d\n\n", c);
        printf("A = "); scanf("%d", &A);
        
        if(A < 0 || A > 99) {                             //入力値の範囲を制限
            printf("(0 ~ 99) の数を入力しろ\n\n\n");
            continue;
        }
        
        if(y[A] == 1) {                                      //入力値が被らなかった場合
            y[A] = 0;
            int flag = 0;
            for(i = 0; i < N; i++)
                for(j =0; j < N; j++) {
                    if(A == a[i][j]) {                        //数値の一致を判定
                        printf("GREAT!!\n\n");
                        s[i][j] = a[i][j];
                        n[i][j] = 1;
                        out(s); //out(n);
                        flag = 1;
                        break;
                    }
                    if(flag)  break;
                    if(i == N - 1 && j == N - 1)        printf("はずれ!\n\n\n");
                }
        }
        else if(y[A] == 0) {                               //入力値が被った場合
            printf("数字が被ってるよ!もう一度!\n\n\n");
            continue;
        }
        
        for(i = 0; i < N; i++) {                          //縦、横、斜めでのビンゴの判定
            fa = 1;    fb = 1;    fc = 1;    fd = 1;
            for(j = 0; j < N; j++) {
                if(n[i][j] != 1)     fa = 0;
                if(n[j][i] != 1) fb = 0;
                if(n[j][j] != 1) fc = 0;
                if(n[N - (j + 1)][j] != 1)  fd = 0;
            }
            if(fa || fb || fc || fd) {
                printf("BINGO!!!\tYOU WIN !!!\n\n");
                break;
            }
        }
        if(fa || fb || fc || fd)      break;
        c--;
    }
    if(c == 0) {                                         //挑戦回数が0になったらアウト
        printf("残り %d\n\nYOU LOSE !!!\n\n", c);
    }

/* カードの答え合わせが可能 */  
    while(1) {
        printf("答え合わせをしますか?\n(YES = 1 ; NO = 0):");
        scanf("%d", &z);
        printf("\n");
        
        if(z == 1) {
            printf("--->答え合わせ<---\n\n");
            out(a);     break;
        }
        else if(z == 0) break;
        else printf("\nちょと何いってるかわからない\n\n\n");
    }
    
    return 0;
}


/* 説明
変数
・i, j, k,  c, L, A, fa, fb, fc, fd, z;
   a[N][N], s[N][N], n[N][N], x[M], y[M],:int型 
   for文の引数i, j, k, カウントc, 挑戦回数L, 入力値A, ビンゴ判定fa, fb, fc, fd,
   答え合わせz, カードの値a[][], s[][], 真理値n[][], 全数値x[][], y[][], 
処理内容
・12〜22行:ビンゴのカードをを作る
・26〜39行:カードの状態を出力する
・66〜74行:乱数でカードに数字を振り分ける
・79〜109行:入力値がカードの値への一致を判定
・111〜129行:縦、横、斜めでのビンゴの判定
・132〜143行:カードの答え合わせ */

ターミナルで実行

/* 実行結果(中略あり)
-----> BINGO GAME <-----

何回挑戦する?(5 ~ 100): 40


[0 ~ 99 の数を入力してね]

  X   X   X   X   X 
  X   X   X   X   X 
  X   X   O   X   X 
  X   X   X   X   X 
  X   X   X   X   X 



あと 40 回

A = 10
はずれ!


あと 39 回

A = 11
GREAT!!

  X   X   X   X   X 
  X   X   X   X   X 
  X   X   O   X   X 
  X  11   X   X   X 
  X   X   X   X   X 



あと 38 回

A = 11
数字が被ってるよ!もう一度!


あと 38 回

A = 111
(0 ~ 99) の数を入力しろ


あと 38 回

A = 19
はずれ!


あと 37 回

A = 30
はずれ!
〜〜〜〜〜〜〜〜〜〜(中略)
あと 1 回

A = 79
GREAT!!

  9   X   2   X  79 
  X   X  94  78   X 
  X   X   O   X   X 
  X  11   X   X   X 
 83  87  80   X   X 



BINGO!!!   YOU WIN !!!

答え合わせをしますか?
(YES = 1 ; NO = 0):1

--->答え合わせ<---

  9   34   2   23  79 
 54  15  94  78  62 
 77   0   O   18  43 
 32  11  96   40  22 
 83  87  80   25   1               */