/* =============================================================================== LRPronQuiz.mc : 英語の L と R の発音の違いの聞き取りクイズ =============================================================================== Copyright (C) 2008-2013 Masahiko Watanabe Edition History: 2008.06.07 初版( GK Library: Rev.2008.02.29 使用 ) 2009.02.12 改版( GK Library: Rev.2009.02.03 使用 ) 2013.02.15 MikoScript3(ユニコード版)用に変更 -----------------------------------------------------------------------------*/ #include // スピーチエンジンの確認 switch( rv = ::Epsaly.Speak(0) ) // 現在読み上げ中なら中断する { case -1: ::Alert( "スピーチエンジンが機能していません!" ); case -2: return; default: if( rv >= 0 ) // 正常? break; ::Alert( "読み上げができません!" ); return; } /*****/ // GK Library のモジュールをロードする場合 #include #include if( ::Module.Include( "GkLibrary" ) > 0 ) Main( argc, argv ); return; /*****/ /***** // GK Library のソースをインクルードする場合 #include Main( argc, argv ); return; /*****/ //----------------------------------------------------------------------------- // デバッグプリント無効化(リリース時) #set pc #comment #set pv // デバッグプリント有効化(デバッグ時) //#set pc print //#set pv print #set p print //----------------------------------------------------------------------------- #set MAX_QUESTIONS 10 // 1区切りの出題数 #set SPEAK_TIMES 3 // 各問ごとの単語発音回数 #set Wnd_Xd 240 // ウィンドウ幅 #set Wnd_Yd 280 // ウィンドウ高 #set BtnBarYd 38 // ボタン表示領域の高さ #set BtnYd 24 // ボタン高 #set BtnYo ( .Yd - ( #BtnBarYd + #BtnYd ) / 2 ) // ボタン上端位置 #set BtnXd 80 // ボタン幅 #set BtnXs (( .Xd - 2 * #BtnXd ) / 3 ) // ボタン間の幅 #set BtnX1 #BtnXs // 第1ボタン左端位置 #set BtnX2 ( #BtnX1 + #BtnXd + #BtnXs ) // 第2ボタン左端位置 #set SPEAK_TIMER_ID 123 //----------------------------------------------------------------------------- function ^Main( argc, argv ) { #pc "開始"; ^DefValue = null; ^WidgetFont = ::GK.Font( "MS Pゴシック", 12, #SHIFTJIS_CHARSET, #VARIABLE_PITCH ); class ^QuizWindow : ::GK.Window {} #pv ^MainWnd = ^QuizWindow(); ^MainWnd.Open(); ^MainWnd.ShowTopMsg(); ::GK.WindowMsgLoop(); FIN: 'sleep( 500 ); delete ^MainWnd; delete ^WidgetFont; #pc "終了"; return; OnError: print ::ErrorMessage( $err_code, $err_info ); goto FIN; } //----------------------------------------------------------------------------- function ^QuizWindow.Construct() { Xd = #Wnd_Xd; Yd = #Wnd_Yd; Xo = ( ::GK.GetSystemMetrics( #SM_CXSCREEN ) - Xd ) / 2; Yo = ( ::GK.GetSystemMetrics( #SM_CYSCREEN ) - Yd ) / 2; .[ ::GK.Window.Construct ]( "L と R の発音聞き取りクイズ", Xo, Yo, Xd, Yd, #WS_POPUP | #WS_VISIBLE | #WS_CAPTION | #WS_DLGFRAME | #WS_SYSMENU ); } function ^QuizWindow.Destruct() { .[ ::GK.Window.Destruct ](); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^QuizWindow.OnCreate() { #pc "OnCreate"; .DefWidgetFont := ^WidgetFont; #pv ( .Xd, .Yd ) = .GetClientSize(); #pv .EditBox = .AddEditBox( #WS_VSCROLL | //#ES_READONLY | #ES_MULTILINE | #ES_AUTOVSCROLL | #ES_AUTOHSCROLL | #ES_WANTRETURN, ::GK.Rect( 0, 0, .Xd, .Yd - #BtnBarYd ) ); #pv .L_Button = .AddButton( "push", "スタート", ::GK.Rect( #BtnX1, #BtnYo, #BtnXd, #BtnYd ) ); .L_Button.OnCommand = function() { .owner.OnLButton(); }; #pv .R_Button = .AddButton( "push", "キャンセル", ::GK.Rect( #BtnX2, #BtnYo, #BtnXd, #BtnYd ) ); .R_Button.OnCommand = function() { .owner.OnRButton(); }; .IsStarted = #FALSE; .nRounds = 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^QuizWindow.OnClose() { #pc "OnClose"; .StopSpeak(); return 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^QuizWindow.OnMinMaxInfo( pMinMax ) { #pc "OnMinMaxInfo"; //MINMAXINFO ::= //{ // .Reserved = POINT; // .MaxSize = POINT; // .MaxPosition = POINT; // .MinTrackSize = POINT; // .MaxTrackSize = POINT; //} // ウィンドウサイズが変更できないように // .MinTrackSize と .MaxTrackSize を設定して返す P'LONG(4) = { #Wnd_Xd, #Wnd_Yd, #Wnd_Xd, #Wnd_Yd }; ( pMinMax + 3*4*2 )'memcpy( P'addr, 4*4 ); return #TRUE; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^QuizWindow.OnPaint() { #pc "OnPaint"; .GetHotRect( R'STRUCT ); .gc.DrawEdge( R, 0, #BF_MIDDLE ); } //----------------------------------------------------------------------------- function ^QuizWindow.OnLButton() { #pc "OnLButton"; if( ! .IsStarted ) { .L_Button.SetTitle( "L" ); .R_Button.SetTitle( "R" ); .IsStarted = #TRUE; .InitQuiz(); .GiveQuiz(); } else .CheckAnswer( 0 ); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - function ^QuizWindow.OnRButton() { #pc "OnRButton"; if( ! .IsStarted ) .Close(); else .CheckAnswer( 1 ); } //----------------------------------------------------------------------------- function ^QuizWindow.Print( cp ) // テキストボックスへ最終行へ文字列追加 { cn = .EditBox.GetTextCn(); .EditBox.Select( cn, cn ); .EditBox.Replace( cp ); } //----------------------------------------------------------------------------- function ^QuizWindow.ShowTopMsg() { .Print( ## これは、英語の L と R の発音の 違いを聞き取るクイズです。 問題は全部で #MAX_QUESTIONS 問あります。 各問では、同じ単語を #SPEAK_TIMES 回発音します。 その単語の中に、 L の発音があれば 「 L 」 のボタンを、 R の発音があれば 「 R 」 のボタンを、 押してください。 「スタート」 ボタンを押すと始まります。 ## ); } //----------------------------------------------------------------------------- function ^QuizWindow.InitQuiz() { if( .nRounds++ == 0 ) // 初回? { .WordList = { // L 音単語 R 音単語 "light", "right", "lay", "ray", "play", "pray", "lead", "read", "lice", "rice", "flesh", "fresh", "fly", "fry", "collect", "correct", "long", "wrong", }; .nWords = .WordList'count; ::Math.srand( 'ticks * 0xABCD ^ 0x12345678 ); } .QN = 0; // 問題番号 .nCorrectAns = 0; // 正解数 } //----------------------------------------------------------------------------- function ^QuizWindow.GiveQuiz() { // 乱数で今回の発声単語を決める( 同単語の再出を抑制 ) DefValue = 0; M = ( #MAX_QUESTIONS - 1 ) / .nWords + 1; for( N = 0 ; N < .nWords ; N++ ) { i = ( ::Math.rand() & 0xFFFF ) * .nWords / 0x10000; if( .Use[i] < M ) break; } .Use[i] = .Use[i] + 1; // 今回の単語の使用回数+1 .CurWord = .WordList[ i ]; // 今回の発声単語 .CurAns = i & 01; // 今回の正解( =0:L, =1:R ) .Print( ## 第 ${ ++.QN } 問:  ${ .WordList[ i & ~01 ] } or ${ .WordList[ i | 01 ] } ## ); .StopSpeak(); .StartSpeak(); // 単語の発声開始 } //----------------------------------------------------------------------------- function ^QuizWindow.CheckAnswer( ans ) { .StopSpeak(); .Print( ## ${ ans == .CurAns ? "○" : "×" } ( 正解: ${ .CurWord } ) ## ); if( ans == .CurAns ) .nCorrectAns++; if( .QN < #MAX_QUESTIONS ) { .GiveQuiz(); // 次の出題 } else // 全問の出題が終った時 { .Print( ## ${ .QN } 問中、${ .nCorrectAns } 問 正解でした! ## ); .IsStarted = #FALSE; .L_Button.SetTitle( "スタート" ); .R_Button.SetTitle( "キャンセル" ); delete .Use; } } //----------------------------------------------------------------------------- function ^QuizWindow.StartSpeak() { ::Epsaly.Speak( .CurWord ); .SpeakCount = 1; .StartTimer( #SPEAK_TIMER_ID, 50 ); } function ^QuizWindow.OnTimer( id ) { if( id != #SPEAK_TIMER_ID ) return; if( ::Epsaly.TraceSpeaking() != -2 ) // 未だ発声中? return; if( .SpeakCount < #SPEAK_TIMES ) { ::Epsaly.Speak( .CurWord ); .SpeakCount++; } else .StopTimer( #SPEAK_TIMER_ID ); } function ^QuizWindow.StopSpeak() { ::Epsaly.Speak( 0 ); .StopTimer( #SPEAK_TIMER_ID ); } //-----------------------------------------------------------------------------