素人プログラマーの日常

効率の良いコード、美しいコードなんて書けません。

「いち!にの!さんすう」完成!

完成しました。


こちらのページからダウンロード出来ます。

http://tenkomorituuhan2.com/products/sansuu/top.html


内容についてそんなに複雑なことは何もないので、実際にやってみればすぐ理解出来ると思います。早速私も少しレベルを上げたところまで進めています。果たしてこのソフトでどれだけ計算力が上がるのか?まだ未知数ですが、息子にも毎日やらせてみて様子を見ます。

でも、こういうのって「やらされてる感」があると、上達の仕方も鈍くなってくる気がします。私は自分のためでもあるので積極的に取組みますが、息子は苦手な計算を強いられるわけですから、考え方も違ってやらされてる感が強く出てきそうです。なのでダウンロードページにも書きましたが、そこを補う意味でエサをちらつかせます。Ψ(`∀´)Ψケケケ

まあエサというと言葉が悪いかもしれませんが、ちゃんとやったことに対価を与えることは大事かなと考えています。逆にいえば、何もやらなければ何も得られないということですから。そういう基本的な思考は子どもの頃から身に付けていてほしいものです。これを口で説明しても、息子はまだ実感するのは難しいかもしれないので、それなら機会があるごとに実践すれば良いだけのことです。

計算だけではなく、今までもいろいろ実戦形式で試していますが、ことごとく中途半端に終わっています。だからこそ今回は長期目線で続けられるようにと、こなす量を少な目に見積もっています。1日に四則演算各10問、合計40問です。1問10秒に設定していますから、どんなに時間がかかっても400秒程度です。

これで少しは計算に対して苦手意識がなくなれば、作った甲斐もあるというものです。



では、いつものようにソースコードを掲載します。

※ただ漠然とコピペして使用すると、PCが宇宙と交信を始めて宇宙人が攻めてくる原因となりかねません。きちんと理解出来る人が確認した上で使用してください。
細かい処理にはコメントを添えていないことも多いので、何をしているのか分かりづらいかもしれませんが、それも楽しみのひとつということで…(笑)。

#include "DxLib.h"

const int wX = 640;        //ウインドウサイズ
const int wY = 480;

const int BSname = 33;        //DATA.nameの文字数
const int numPlayer = 5;    //プレーヤ数
const int numQ = 10;        //問題数

const int absX = 120;        //描画基準X
const int absY = 130;        //描画基準Y
const int addY = 56;        //描画加算

const int BGcolor = 0x00aaee;        //背景色

//プレーヤ情報
struct tagDATA{
    char name[ BSname ];         //名前
    int lvl[ 4 ];        //レベル [0]:足算 [1]:引算 [2]:掛算 [3]:割算
    int exp[ 4 ];    //経験値 [0]:足算...
    int play[ 4 ];    //挑戦回数 [0]:足算...
    int correct[ 4 ];    //正解数 [0]:足算...
} DATA[ numPlayer ];

int player;        //プレーヤ
int cs;            //カーソル位置
int csh;        //カーソル位置横

int mondaiNo;        //現在の問題数
int mondaiKind;    //問題種類
int time;            //制限時間

//キー割当て
int key[ ] = { KEY_INPUT_NUMPAD0 , KEY_INPUT_NUMPAD1,
            KEY_INPUT_NUMPAD2 , KEY_INPUT_NUMPAD3,
            KEY_INPUT_NUMPAD4 , KEY_INPUT_NUMPAD5,
            KEY_INPUT_NUMPAD6 , KEY_INPUT_NUMPAD7,
            KEY_INPUT_NUMPAD8 , KEY_INPUT_NUMPAD9,
            KEY_INPUT_NUMPADENTER , KEY_INPUT_RETURN,
            KEY_INPUT_UP , KEY_INPUT_DOWN,
            KEY_INPUT_LEFT , KEY_INPUT_RIGHT };
int keyinput[ 16 ];        //キー入力状態

//グラフィックハンドル
int GHtitle;        //タイトル
int GHnum[ 15 ];        //数字・記号
int GHwaku;    //枠
int GHwaku2;

int GHstart[ 5 ];        //問題開始
int GHeffect[ 5 ];        //エフェクト
int GHfade;        //画面キャプチャ用

//サウンドハンドル
int SHselect;            //選択
int SHdecision;        //決定
int SHcorrect;        //正解
int SHmiss;            //間違い
int SHtimeout;        //時間切れ
int SHlvlup;            //レベルアップ
int SHlvldown;        //レベルダウン

DATEDATA date;    //日時取得用構造体 Year Mon Day Hour Min Sec

//詳細テキスト出力用
int num1st[ numQ ];    //1つ目の数字
int num2nd[ numQ ];    //2つ目の数字
int numans[ numQ ];    //答え
int ans[ numQ ];        //回答
int kindans[ numQ ];    //回答種別 =0:時間切 1:間違 2:正解 3:5秒以内正解
int kindclc;            //計算の種別
char markans[ 4 ][ 3 ] = { "T" , "▲" , "〇" , "◎" };    //回答種別記号
char markclc[ 4 ][ 2 ] = { "+" , "-" , "*" , "/" };        //計算種別記号
int ansketa;        //回答桁数

int totalflag;        //全体のフラグ

//プロトタイプ宣言
void Title();        //タイトル
void DrawTitle( int flag );

void Menu();        //メニュー
void DrawMenu();

void Seiseki();        //成績

void InputCs( int csMax );        //カーソル入力

void FadeIn();            //フェードイン・アウト
void FadeOut();

void PrePlay();        //プレイ準備
void Play();            //プレイ
void DrawPlay();        //プレイ画面描画
void NumInput();        //テンキー入力
void Effect( int flag );        //エフェクト描画

void Tasu();        //四則演算準備
void Hiku();
void Kakeru();
void Waru();

void Save();        //読み書き
void Load();
void Log();
void Error( int flag );    //ファイルエラー処理


//WinMain
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        LPSTR lpCmdLine, int nCmdShow )
{
    SetOutApplicationLogValidFlag( FALSE );    //ログ出力しない
    SetMainWindowText( "さんすう" );        //ウインドウタイトル指定
    SetGraphMode( wX , wY , 32 );            //ウインドウの大きさとカラービット数指定
    ChangeWindowMode( TRUE );                //ウインドウで表示
    SetDrawScreen( DX_SCREEN_BACK );    //ちらつき防止設定
    SetWaitVSyncFlag( TRUE );                    //フレーム同期
    SetMouseDispFlag( TRUE );                    //マウスカーソル表示
    SetWindowUserCloseEnableFlag( FALSE );    //×ボタンで終了しない
    SetAlwaysRunFlag( TRUE );                    //ウインドウ非アクティブ時動作

    if( DxLib_Init() == -1 ) return -1;

    //フォント設定
    SetFontSize( 32 );
    SetFontThickness( 1 );
    ChangeFontType( DX_FONTTYPE_ANTIALIASING );
    ChangeFont( "メイリオ" );

    //グラフィック
    LoadDivGraph( "img/num.png" , 15 , 15 , 1 , 48 , 48 , GHnum );
    LoadDivGraph( "img/start.png" , 5 , 1 , 5 , 200 , 64 , GHstart );
    LoadDivGraph( "img/effect.png" , 5 , 5 , 1, 128 , 128 , GHeffect );
    GHtitle = LoadGraph( "img/title.png" );
    GHwaku = LoadGraph( "img/waku01.png" );
    GHwaku2 = LoadGraph( "img/waku02.png" );

    //サウンド
    SHselect = LoadSoundMem( "img/select.wav" );
    SHdecision = LoadSoundMem( "img/decision.wav" );
    SHcorrect = LoadSoundMem( "img/correct.wav" );
    SHmiss =LoadSoundMem( "img/miss.wav" );
    SHtimeout = LoadSoundMem( "img/timeout.wav" );
    SHlvlup = LoadSoundMem( "img/lvlup.wav" );
    SHlvldown = LoadSoundMem( "img/lvldown.wav" );

    //プレーヤ情報読込み
    Load();

    //メインループ
    while( totalflag >-1 ){

        switch( totalflag ){
        case 0:                //タイトル
            Title();    break;
        case 1:                //メニュー
            Menu();    break;
        case 2:                //プレイ
            PrePlay();    break;
        case 3:                //成績
            Seiseki();    break;
        }
        FadeOut();

    }

    Save();

    DxLib_End() ;                // DXライブラリ使用の終了処理

    return 0 ;                // ソフトの終了
}



void Title(){        //タイトル画面///////////////////////////////

    cs = 0;
    DrawTitle( 0 );
    FadeIn();

    while( 1 ){

        InputCs( 6 );    //カーソル操作

        //終了
        if( ( cs == 5 )&&( ( keyinput[10] == 1 )||( keyinput[11] == 1 ) ) ){
            totalflag = -1;
            break;
        }

        DrawTitle( 0 );
        ScreenFlip();

        //enterキー押下
        if( ( keyinput[10] == 1 )||( keyinput[11] == 1 ) ){
            PlaySoundMem( SHdecision , DX_PLAYTYPE_BACK );

            //メニューへ
            if( DATA[cs].name[0] != '\0' ){
                player = cs;
                totalflag = 1;
                break;
            } else {
                //名前入力
                DrawTitle( 1 );
                ScreenFlip();
                ZeroMemory( &DATA[ cs ] , sizeof( tagDATA ) );
                KeyInputString( absX+15 , absY+cs*addY+8 , BSname -1 , DATA[ cs ].name , FALSE );
                DrawTitle( 0 );
                ScreenFlip();
            }
        }
    }

}


void DrawTitle( int flag ){        //タイトル画面描画/////////////////////

    DrawBox( 0 , 0 , wX , wY , BGcolor , TRUE );
    DrawGraph( absX , 10 , GHtitle , TRUE );

    //プレーヤ名描画
    for( int i=0 ; i<6 ; i++ ){
        DrawGraph( absX , absY+i*addY , GHwaku , TRUE );
        if( i == 5 ){
            DrawString( absX+15 , absY+i*addY+8 , "終了" , 0xffffff );
        } else if( ( flag == 1 )&&( cs == i ) ){
            continue;
        } else if( DATA[i].name[0] == '\0' ){
            DrawString( absX+15 , absY+i*addY+8 , "新しく作成" , 0xffff00 );
        } else {
            DrawString( absX+15 , absY+i*addY+8 , DATA[i].name , 0xffffff );
        }
    }

    //カーソル描画
    if( flag != 1 ){
        SetDrawBlendMode( DX_BLENDMODE_ALPHA , 70 );
        DrawBox( 0 , absY+cs*addY , wX , absY+cs*addY+48 , 0xffffff , TRUE );
        SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 );
    }

}


void Menu(){        //メニュー画面////////////////////////////////

    cs = 0;
    csh = 0;
    DrawMenu();
    FadeIn();

    while( 1 ){

        InputCs( 4 );    //カーソル操作

        //enterキー押下
        if( ( keyinput[10] == 1 )||( keyinput[11] == 1 ) ){
            PlaySoundMem( SHdecision , DX_PLAYTYPE_BACK );
            switch( cs+csh*4 ){
            case 0:        //足し算
                mondaiKind = 0;
                totalflag = 2;
                break;
            case 1:        //引き算
                mondaiKind = 1;
                totalflag = 2;
                break;
            case 2:        //掛け算
                mondaiKind = 2;
                totalflag = 2;
                break;
            case 3:        //割り算
                mondaiKind = 3;
                totalflag = 2;
                break;
            case 4:        //四則演算
                mondaiKind = 4;
                totalflag = 2;
                break;
            case 5:        //成績
                totalflag = 3;
                break;
            case 6:        //消す
                SetDrawBlendMode( DX_BLENDMODE_ALPHA , 180 );
                DrawBox( 0 , 0 , wX , wY , 0x000000 , TRUE );
                DrawFormatString( 100 , 180 , 0xffffff , "%sさんの記録がすべて消えます" , DATA[ player ].name );
                DrawString( 100 , 240 , "よろしいですか? はい[Y] いいえ[N]" , 0xffffff );
                ScreenFlip();
                while( 1 ){
                    WaitVSync( 1 );
                    if( CheckHitKey( KEY_INPUT_Y ) == 1 ){
                        PlaySoundMem( SHdecision , DX_PLAYTYPE_BACK );
                        ZeroMemory( &DATA[ player ] , sizeof( tagDATA ) );
                        totalflag = 0;
                        break;
                    } else if( CheckHitKey( KEY_INPUT_N ) == 1 ){
                        break;
                    }
                }
                break;
            case 7:        //戻る
                totalflag = 0;
            }
            break;
        }
        DrawMenu();
        ScreenFlip();
    }

}


void DrawMenu(){        //メニュー画面描画/////////////////////

    DrawBox( 0 , 0 , wX , wY , BGcolor , TRUE );

    DrawFormatString( absX , 50 , 0xffffff , "%sさん" , DATA[ player ].name );
    DrawFormatString( absX , 100 , 0x00ff00 , "LV(+)%d LV(-)%d" , DATA[ player ].lvl[ 0 ] , DATA[ player ].lvl[ 1 ] );
    DrawFormatString( absX , 140 , 0x00ff00 , "LV(×)%d LV(÷)%d" , DATA[ player ].lvl[ 2 ] , DATA[ player ].lvl[ 3 ] );

    char strdraw[ 8 ][ 15 ] = { "足し算10問" , "引き算10問" , "掛け算10問" , "割り算10問" , "四則演算40問" , "成績" , "消す" , "戻る" };
    for( int x=0 ; x<2 ; x++ ){
        for( int y=0 ; y<4 ; y++ ){
            DrawGraph( absX+x*200 , absY+y*addY+90 , GHwaku2 , TRUE );
            DrawString( absX+x*200+15 , absY+y*addY+98 , strdraw[ y+x*4 ] , 0xffffff );
        }
    }

    //カーソル描画
    SetDrawBlendMode( DX_BLENDMODE_ALPHA , 70 );
    DrawBox( absX+csh*200 , absY+cs*addY+90 , absX+csh*200+190 , absY+cs*addY+138 , 0xffffff , TRUE );
    SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 );

}


void Seiseki(){        //成績/////////////////////////////////////

    DrawBox( 0 , 0 , wX , wY , BGcolor , TRUE );

    char str[ 4 ][ 7 ] = { "足し算" , "引き算" , "掛け算" , "割り算" };

    DrawFormatString( absX , 50 , 0xffffff , "%sさんの成績" , DATA[ player ].name );
    for( int i = 0 ; i < 4 ; i++ ){
        DrawString( absX , 100+i*80 , &str[ i ][ 0 ] , 0xffffff );
        int cr = DATA[ player ].correct[ i ];
        int pl = DATA[ player ].play[ i ];
        int per;
        if( pl == 0 ){
            per = 0;
        } else {
            per = cr * 100 / pl;
        }
        DrawFormatString( absX , 140+i*80 , 0x00ff00 , "LV %d 正解 %d/%d 正解率 %d%" , DATA[ player ].lvl[ i ] , cr , pl , per );
    }

    FadeIn();
    WaitKey();

    totalflag = 1;
}


void InputCs( int csMax ){        //カーソル操作////////////////////////////

    int flag = 0;

    while( flag == 0 ){        //入力があるまで待機

        WaitVSync( 1 );
        for( int i=10 ; i<16 ; i++ ){
            if( CheckHitKey( key[i] ) == 1 ){
                keyinput[i]++;
                if( keyinput[i] == 1 ){
                    flag = 1;
                    switch ( i ){
                    case 12:
                        PlaySoundMem( SHselect , DX_PLAYTYPE_BACK );
                        cs--;
                        if( cs < 0 ) cs = csMax-1;
                        break;
                    case 13:
                        PlaySoundMem( SHselect , DX_PLAYTYPE_BACK );
                        cs = ( cs+1 )%csMax;
                        break;
                    case 14:
                        PlaySoundMem( SHselect , DX_PLAYTYPE_BACK );
                        csh--;
                        if( csh < 0 ) csh = 1;
                        break;
                    case 15:
                        PlaySoundMem( SHselect , DX_PLAYTYPE_BACK );
                        csh = ( csh+1 )%2;
                        break;
                    }

                }
            } else {
                keyinput[i] = 0;
            }
        }

    }

}


void FadeIn(){        //フェードイン//////////////////////////////

    GHfade = MakeGraph( wX , wY );
    GetDrawScreenGraph( 0 , 0 , wX-1 , wY-1 , GHfade );
    for( int i=0 ; i<256 ; i = i+10 ){
        DrawBox( 0 , 0 , wX , wY , 0xffffff , TRUE );
        SetDrawBlendMode( DX_BLENDMODE_ALPHA , i );
        DrawGraph( 0 , 0 , GHfade , TRUE );
        SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 );
        ScreenFlip();
    }
    DeleteGraph( GHfade );

}


void FadeOut(){        //フェードアウト/////////////////////////

    GHfade = MakeGraph( wX , wY );
    GetDrawScreenGraph( 0 , 0 , wX-1 , wY-1 , GHfade );
    for( int i=255 ; i>0 ; i = i-10 ){
        DrawBox( 0 , 0 , wX , wY , 0xffffff , TRUE );
        SetDrawBlendMode( DX_BLENDMODE_ALPHA , i );
        DrawGraph( 0 , 0 , GHfade , TRUE );
        SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 );
        ScreenFlip();
    }
    DeleteGraph( GHfade );

}


void PrePlay(){            //プレイ準備////////////////////////////

    mondaiNo = 0;
    DrawBox( 0 , 0 , wX , wY , BGcolor , TRUE );
    FadeIn();

    int roop = 1;
    if( mondaiKind == 4 ) roop = 4;

    for( int i = 0 ; i < roop ; i++ ){
        kindclc = mondaiKind;
        if( kindclc == 4 ) kindclc = mondaiNo / numQ;
        Play();
    }

}


void Play(){        //プレイ///////////////////////////////////////

    switch( kindclc ){        //計算種別
    case 0:
        Tasu();
        break;
    case 1:
        Hiku();
        break;
    case 2:
        Kakeru();
        break;
    case 3:
        Waru();
        break;
    }

    // "スタート!" 描画
    for( int i = 3 ; i > 0 ; i-- ){
        for( int t = 0 ; t < 60 ; t++ ){
            DrawBox( 0 , 0 , wX , wY , BGcolor , TRUE );
            DrawGraph( 110 , 100 , GHstart[ kindclc ] , TRUE );
            DrawGraph( 310 , 100 , GHstart[ 4 ] , TRUE );
            DrawExtendGraph( 256 , 200 , 384 , 328 , GHnum[ i ] , TRUE );
            ScreenFlip();
        }
    }

    for( int i=0 ; i < numQ ; i++ ){        //10問

        int flagQ = 0;
        time = 600;
        ans[ i ] = 0;
        ansketa = 0;

        while( time > -1 ){        //タイムがなくなるまで
            NumInput();            //キー入力
            for( int j = 0 ; j<16 ; j++ ){    
                if( keyinput[ j ] == 1 ){
                    switch( j ){
                    case 0:
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                    case 8:
                    case 9:
                        if( ansketa < 9 ){
                            ans[ i ] = ans[ i ]*10;        //回答数字追加
                            ans[ i ] = ans[ i ] + j;
                            ansketa++;
                        }
                        break;
                    case 10:
                    case 11:            //回答決定
                        flagQ = 1;
                        break;
                    case 14:            //回答全取消し
                        ans[ i ] = 0;
                        ansketa = 0;
                        break;
                    case 15:            //回答1桁取消し
                        ans[ i ] = ans[ i ]/10;
                        ansketa = ( ansketa < 1 ) ? 0 : ansketa-1;
                        break;
                    }
                }
            }

            //画面描画
            DrawBox( 0 , 0 , wX , wY , BGcolor , TRUE );
            DrawPlay();
            ScreenFlip();

            //正否判定
            if( flagQ == 1 ){
                if( ans[ i ] == numans[ i ] ){
                    PlaySoundMem( SHcorrect , DX_PLAYTYPE_BACK );
                    Effect( 0 );
                    DATA[ player ].correct[ kindclc ]++;
                    if( time < 300 ){
                        kindans[ i ] = 2;
                        DATA[ player ].exp[ kindclc ]++;
                    } else {
                        kindans[ i ] = 3;
                        DATA[ player ].exp[ kindclc ] += 2;
                    }
                } else {
                    PlaySoundMem( SHmiss , DX_PLAYTYPE_BACK );
                    Effect( 1 );
                    kindans[ i ] = 1;
                    DATA[ player ].exp[ kindclc ]--;
                }
                break;
            }
            time--;
        }

        //時間切れ
        if( flagQ == 0 ){
            PlaySoundMem( SHtimeout , DX_PLAYTYPE_BACK );
            Effect( 2 );
            kindans[ i ] = 0;
            DATA[ player ].exp[ kindclc ] -= 2;
        }

        mondaiNo++;
        DATA[ player ].play[ kindclc ]++;

        //レベルアップ
        int lv = kindclc+2;
        if( DATA[ player ].exp[ kindclc ] >= 5*lv ){
            PlaySoundMem( SHlvlup , DX_PLAYTYPE_BACK );
            Effect( 3 );
            DATA[ player ].exp[ kindclc ] -= 5*lv;
            DATA[ player ].lvl[ kindclc ]++;
        }

        //レベルダウン
        if( DATA[ player ].exp[ kindclc ] < -4 ){
            if( DATA[ player ].lvl[ kindclc ] > 0 ){
                PlaySoundMem( SHlvldown , DX_PLAYTYPE_BACK );
                Effect( 4 );
                DATA[ player ].lvl[ kindclc ]--;
            }
            DATA[ player ].exp[ kindclc ] += 5;
        }

    }

    //ログ書込み
    Log();

    totalflag = 1;
}


void DrawPlay(){        //プレイ画面描画/////////////////////

    int tempmondaiNo = mondaiNo % 10;

    DrawFormatString( 100 , 20 , 0xffff00 , "%d問目" , mondaiNo + 1 );
    DrawBox( 98 , 198 , 502 , 242 , 0x666666 , TRUE );
    DrawBox( 100 , 200 , 100+400*time/600 , 240 , GetColor( 255*(600-time)/600 , 255*time/600 , 0 ) , TRUE );

    //問題描画
    int numGraph[ 8 ];    //数字
    int numtemp = num1st[ tempmondaiNo ];
    int keta = 1;        //桁数
    int dspX = 0;        //描画位置

    while( 1 ){        //数値1描画
        numGraph[ keta ] = numtemp%10;
        if( numtemp/10 == 0 ){
            break;
        } else {
            numtemp = numtemp/10;
            keta++;
        }
    }
    for( int i = keta ; i > 0 ; i-- ){
        DrawGraph( 50+dspX , 100 , GHnum[ numGraph[ i ] ] , TRUE );
        dspX = dspX+40;
    }

    DrawGraph( 50+dspX , 100 , GHnum[ 10+kindclc ] , TRUE );        //記号描画
    dspX = dspX+40;

    numtemp = num2nd[ tempmondaiNo ];        //数値2描画
    keta = 1;

    while( 1 ){
        numGraph[ keta ] = numtemp%10;
        if( numtemp/10 == 0 ){
            break;
        } else {
            numtemp = numtemp/10;
            keta++;
        }
    }
    for( int i = keta ; i > 0 ; i-- ){
        DrawGraph( 50+dspX , 100 , GHnum[ numGraph[ i ] ] , TRUE );
        dspX = dspX+40;
    }

    DrawGraph( 50+dspX , 100 , GHnum[ 14 ] , TRUE );        //「=」描画

    int tempans = ans[ mondaiNo%numQ ];            //回答描画
    for( int i = 0 ; i < ansketa ; i++ ){
        DrawGraph( 400-i*40 , 300 , GHnum[ tempans%10 ] , TRUE );
        tempans = tempans/10;
    }

    DrawString( 50 , 380 , "テンキーで入力 [enter]で決定" , 0xffffff );
    DrawString( 50 , 430 , "[←]:全取消し [→]:1桁取消し" , 0xffffff );

}


void NumInput(){        //テンキー入力/////////////////////////////

    for( int i = 0 ; i < 16 ; i++ ){
        if( CheckHitKey( key[ i ] ) == 1 ){
            keyinput[ i ]++;
        } else {
            keyinput[ i ] = 0;
        }
    }

}


void Effect( int flag ){        //エフェクト描画//////////////////////////

    GHfade = MakeGraph( wX , wY );
    GetDrawScreenGraph( 0 , 0 , wX-1 , wY-1 , GHfade );

    int GHtemp;

    switch( flag ){
    case 0:
    case 1:
        if( flag == 0 ){
            GHtemp = GHeffect[ 0 ];    //正解
        } else {
            GHtemp = GHeffect[ 1 ];    //ミス
        }
        for( int i = 64 ; i < 160 ; i += 8 ){
            DrawGraph( 0 , 0 , GHfade , TRUE );
            DrawExtendGraph( 320-i , 240-i , 320+i , 240+i , GHtemp , TRUE );
            ScreenFlip();
        }
        WaitVSync( 10 );
        break;
    case 2:
    case 3:
        if( flag == 2 ){    
            GHtemp = GHeffect[ 2 ];    //時間切れ
        } else {
            GHtemp = GHeffect[ 3 ];    //レベルアップ
        }
        for( int i = 16 ; i < 400 ; i += 20 ){
            DrawGraph( 0 , 0 , GHfade , TRUE );
            DrawExtendGraph( 160 , wY-i , 480 , wY-i+320 , GHtemp , TRUE );
            ScreenFlip();
        }
        WaitVSync( 10 );
        break;
    case 4:        //レベルダウン
        for( int i = 16 ; i < 400 ; i += 20 ){
            DrawGraph( 0 , 0 , GHfade , TRUE );
            DrawExtendGraph( 160 , i-320 , 480 , i , GHeffect[ 4 ] , TRUE );
            ScreenFlip();
        }
        WaitVSync( 10 );
        break;
    }

    DeleteGraph( GHfade );
}


void Tasu(){        //足し算準備////////////////////////////////

    int num = DATA[ player ].lvl[ 0 ] + 4;    //レベルによる調整
    for( int i=0 ; i<10 ; i++ ){        //10問
        int r = GetRand( 9 );
        if( r < 7 ){        //70%は数値が高くなるように設定
            num1st[ i ] = num/2 + GetRand( num/2 );
        } else {
            num1st[ i ] = GetRand( num );
        }
        r = GetRand( 9 );
        if( r < 7 ){
            num2nd[ i ] = num/2 + GetRand( num/2 );
        } else {
            num2nd[ i ] = GetRand( num );
        }
        numans[ i ] = num1st[ i ] + num2nd[ i ];
    }

}


void Hiku(){        //引き算準備///////////////////////////////

    int num = DATA[ player ].lvl[ 1 ] + 4;    //レベルによる調整
    for( int i=0 ; i<10 ; i++ ){        //10問
        int r = GetRand( 9 );
        if( r < 7 ){        //70%は数値が高くなるように設定
            num1st[ i ] = num/2 + GetRand( num/2 );
        } else {
            num1st[ i ] = GetRand( num );
        }
        r = GetRand( 9 );
        if( r < 4 ){        //40%
            num2nd[ i ] = num/2 + GetRand( num/2 );
        } else {
            num2nd[ i ] = GetRand( num );
        }
        if( num2nd[ i ] > num1st[ i ] ){        //2番目の数値が大きければ入換え
            int temp = num1st[ i ];
            num1st[ i ] = num2nd[ i ];
            num2nd[ i ] = temp;
        }
        numans[ i ] = num1st[ i ] - num2nd[ i ];
    }

}


void Kakeru(){        //掛け算準備////////////////////////////

        int num = DATA[ player ].lvl[ 2 ] + 4;    //レベルによる調整
    for( int i=0 ; i<10 ; i++ ){        //10問
        int r = GetRand( 9 );
        if( r < 7 ){        //70%は数値が高くなるように設定
            num1st[ i ] = num/2 + GetRand( num/2 );
        } else {
            num1st[ i ] = GetRand( num );
        }
        r = GetRand( 9 );
        if( r < 7 ){
            num2nd[ i ] = num/2 + GetRand( num/2 );
        } else {
            num2nd[ i ] = GetRand( num );
        }
        numans[ i ] = num1st[ i ] * num2nd[ i ];
    }

}

void Waru(){        //割り算準備//////////////////////////////

    int num = DATA[ player ].lvl[ 3 ] + 4;    //レベルによる調整
    for( int i=0 ; i<10 ; i++ ){        //10問
        int r = GetRand( 9 );
        if( r < 7 ){        //70%は数値が高くなるように設定
            numans[ i ] = num/2 + GetRand( num/2 );
        } else {
            numans[ i ] = GetRand( num );
        }
        r = GetRand( 9 );
        if( r < 5 ){        //50%
            num2nd[ i ] = num/2 + GetRand( num/2 );
        } else {
            num2nd[ i ] = GetRand( num );
        }
        if( num2nd[ i ] == 0 ) num2nd[ i ] = num;        //2番目の数値が0なら入換え
        num1st[ i ] = numans[ i ] * num2nd[ i ];
    }

}


void Save(){        //書込み/////////////////////////////////////

    FILE *fp;
    errno_t error;
    if( (error = fopen_s( &fp , "data.sv" , "w" )) !=0 ){
        Error( 0 );
    } else {
        fwrite( DATA , sizeof( tagDATA ) , numPlayer , fp );
        fclose( fp );
    }

}


void Load(){        //読込み////////////////////////////////////

    FILE *fp;
    errno_t error;
    if( ( error = fopen_s( &fp , "data.sv" , "r" )) != 0 ){
        Error( 1 );
    } else {
        fread( DATA , sizeof( tagDATA ) , numPlayer , fp );
        fclose( fp );
    }

}


void Log(){        //詳細ログ書込み////////////////

    //登録名に".txt"を追加
    char fn[50];            //ファイル名
    char fntxt[5] = ".txt";        //ファイル拡張子
    int index;
    for( index = 0 ; DATA[ player ].name[ index ] != '\0' ; index++ ){
        fn[ index ] = DATA[ player ].name[ index ];
    }
    for( int i=0 ; i<5 ; i++ ){
        fn[ index+i ] = fntxt[ i ];
    }

    GetDateTime( &date );    //日付を取得

    //ログ書込み
    FILE *fp;
    errno_t error;
    if( ( error = fopen_s( &fp , fn , "a" )) != 0 ){
        Error( 2 );
    } else {
        fprintf( fp , "%d/%d/%d/%d:%d\n" , date.Year , date.Mon , date.Day , date.Hour , date.Min );
        for( int i=0 ; i<numQ ; i++ ){
            fprintf( fp , "%s %d%s%d=%d %d\n" , &markans[ kindans[ i ] ][ 0 ] , num1st[ i ] , &markclc[ kindclc ][ 0 ] , num2nd[ i ] , ans[ i ] , numans[ i ]);
        }
        fprintf( fp , "\n" );
        fclose( fp );
    }

}


void Error( int flag ){        //ファイルエラー処理

    SetDrawBlendMode( DX_BLENDMODE_ALPHA , 180 );
    DrawBox( 0 , 0 , wX , wY , 0x000000 , TRUE );
    SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 );

    switch( flag ){
    case 0:
        DrawString( 100 , 180 , "ファイルの書込みに失敗しました" , 0xffffff );
        break;
    case 1:
        DrawString( 100 , 140 , "ファイルの読込みに失敗しました" , 0xffffff );
        DrawString( 100 , 180 , "初回起動時はこのメッセージが表示されます" , 0xffffff );
        break;
    case 2:
        DrawString( 100 , 180 , "ログの書込みに失敗しました" , 0xffffff );
        break;
    }
    DrawString( 100 , 220 , "何かキーを押してください" , 0xffffff );

    ScreenFlip();
    WaitKey();

}