チーム1568

課題名

絶対音感ゲーム!!

研究者名

Eito Mitomi
Yuichi Watanabe

使用器具

・PSoC基盤 1個
・MiniProg 1本
・EIA-574(DSUB9)ストレート通信ケーブル 1本
・スピーカー 1個
・ジャンパー線 4本

ゲーム内容

①出題者がキーボードで音を鳴らします
 (a:ド s:レ d:ミ f:ファ g:ソ h:ラ j:シ k:ド l:無音 )
②回答者はその音をよく聴き、答えだと思うキーを押します
③正解、不正解、スコア、残りライフをLCD画面に表示します。そして不正解ならばヒントも表示します
 (ヒント:正解の音と回答者が答えた音を比較して、低いのか(lower)、高いのか(higher)を画面に表示する)
④5回正解したらゲームクリアですが、3回間違えるとゲームオーバーです

※以下のような仕様になっています
 LCD画面…回答者用
 PC画面 …出題者用

image_0078.jpg
正解の場合


image_0079.jpg image_0080.jpg
不正解の場合


image_0082.jpg
ゲームクリア!


image_0081.jpg
ゲームオーバー…


image_UART.png
PC画面(Tera Term)


ソースコード


#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules
#include <stdlib.h>
#include <stdio.h>

int PW=125;
int SILENT=0,D=229,L=204,M=182,F=172,S=153,R=136,C=121,DD=115;
int SCORE=0,LIFE=3,CLEAR=5;


void main(void)
{
  // M8C_EnableGInt ; // Uncomment this line to enable Global Interrupts
   // Insert your main routine code here.
   
   char *strPtr_1;
   char *strPtr_2;
   int answer;          // 正解の音
   int choice;          // 回答した音
   int score = SCORE;   // スコア
   char score_char[20]; // スコアの文字列化
   int life = LIFE;     // ライフ
   char life_char[20];  // ライフの文字列化
   
   UART_CmdReset();
   UART_IntCntl(UART_ENABLE_RX_INT);
   Counter8_WritePeriod(155);
   Counter8_WriteCompareValue(77);
   Counter8_Start();
   UART_Start(UART_PARITY_NONE);
   M8C_EnableGInt;
   LCD_Start();
   PWM16_1_Start();
   
   // ゲームスタートの初期画面
   // UART側に出題を要求する
   UART_CPutString("\r\nPSoC Synthesizer V1.1 \r\n");
   UART_CPutString("\r\nSet the Answer Tone.\r\n");
   // LCD
   LCD_PrCString("GAME START!");
   
   while(1){
     // 1つ目のループ 出題(鳴らす音を選ぶ)
     while(1){
       if(UART_bCmdCheck()){
         if(strPtr_1 = UART_szGetParam()){
         
           // コマンド入力と音の発生、正解をanswerに記憶
           if(*strPtr_1 == 'a'){
             PWM16_1_WritePeriod(D);
             answer = 1;
           }
           else if(*strPtr_1 == 's'){
             PWM16_1_WritePeriod(L);
             answer = 2;
           }
           else if(*strPtr_1 == 'd'){
             PWM16_1_WritePeriod(M);
             answer = 3;
           }
           else if(*strPtr_1 == 'f'){
             PWM16_1_WritePeriod(F);
             answer = 4;
           }
           else if(*strPtr_1 == 'g'){
             PWM16_1_WritePeriod(S);
             answer = 5;
           }
           else if(*strPtr_1 == 'h'){
             PWM16_1_WritePeriod(R);
             answer = 6;
           }
           else if(*strPtr_1 == 'j'){
             PWM16_1_WritePeriod(C);
             answer = 7;
           }
           else if(*strPtr_1 == 'k'){
             PWM16_1_WritePeriod(DD);
             answer = 8;
           }
           // 無音(SILENT)を選択した場合、ゲーム終了
           else if(*strPtr_1 == 'l'){
                PWM16_1_WritePeriod(SILENT);
             UART_CPutString("Bye!\r\n");
             break;
           }
           UART_CmdReset();
         
           // 回答を要求する表示
           // UART
           UART_CPutString("Inputed your Answer from [a, s, d, f, g, h, j, k] => ");
           // LCD
           LCD_Control(0x01);
           LCD_Position(0,0);
           LCD_PrCString("Input Answer");
           
           // 出題し、回答を要求したところで、1つ目のループを抜ける
           break;
         }
       }
     }
     
     // 2つ目のループ 回答(鳴っている音を選ぶ)
     while(1){
       if(strPtr_2 = UART_szGetParam()){
         UART_PutString(strPtr_2);
         PWM16_1_WritePeriod(SILENT);
         
         // コマンド入力、回答をchoiceに記憶
         if(*strPtr_2 == 'a'){
           choice = 1;
         }
         else if(*strPtr_2 == 's'){
           choice = 2;
         }
         else if(*strPtr_2 == 'd'){
           choice = 3;
         }
         else if(*strPtr_2 == 'f'){
           choice = 4;
         }
         else if(*strPtr_2 == 'g'){
           choice = 5;
         }
         else if(*strPtr_2 == 'h'){
           choice = 6;
         }
         else if(*strPtr_2 == 'j'){
           choice = 7;
         }
         else if(*strPtr_2 == 'k'){
           choice = 8;
         }
         
         //LCDの初期化
         LCD_Control(0x01);
         LCD_Position(0,0);
         
         // 正解の場合
         if(choice == answer){
           score++;
           
           // 正解の表示
           if(score != CLEAR) {
             // UART
             UART_CPutString("\r\nTrue!");
             // LCD
             LCD_PrCString("True!");
             // 出力のために、int型変数をchar型配列にコピー
             csprintf(score_char, "%d", score);
             csprintf(life_char, "%d", life);
           }
           
           // クリアした場合(スコアがCLEARに達した場合)
           else {
             csprintf(score_char, "%d", score);
             // UART
             UART_CPutString("\r\n\r\nGAME CLEAR!\r\nscore : ");
             UART_PutString(score_char);
             // LCD
             LCD_PrCString("GAME CLEAR!");
             LCD_Position(1,0);
             LCD_PrCString("Score : ");
             LCD_PrString(score_char);
             
             // 初期化してゲーム再開
             score = SCORE;
             life = LIFE;
             UART_CPutString("\r\n\r\nSet the Answer Tone.\r\n");
             break;
           }
         }
         
         // 不正解の場合
         else {
           life--;
           
           // 不正解の表示
           if(life != 0) {
             // UART
             UART_CPutString("\r\nFalse");
             // LCD
             LCD_PrCString("False");
             // 出力のために、int型変数をchar型配列にコピー
             csprintf(score_char, "%d", score);
             csprintf(life_char, "%d", life);
             
             LCD_Position(1,0);
             // 正解の音程は回答したものよりも高い
             if(choice > answer){
               UART_CPutString("\r\nhigher");
               LCD_PrCString("higher");
             }
             // 正解の音程は回答したものよりも低い
             else if(choice < answer){
               UART_CPutString("\r\nlower");
               LCD_PrCString("lower");
             }
           }
           
           // ゲームオーバーの場合(ライフが0になった場合)
           else {
             csprintf(score_char, "%d", score);
             // UART
             UART_CPutString("\r\n\r\nGAME OVER.\r\nscore : ");
             UART_PutString(score_char);
             // LCD
             LCD_Position(0,0);
             LCD_PrCString("GAME OVER.");
             LCD_Position(1,0);
             LCD_PrCString("Score : ");
             LCD_PrString(score_char);
             
             // 初期化してゲーム再開
             score = SCORE;
             life = LIFE;
             UART_CPutString("\r\n\r\nSet the Answer Tone.\r\n");
             break;
           }
         }
         
         // スコアの表示
         // UART
         UART_CmdReset();
         UART_CPutString("\r\nscore : ");
         UART_PutString(score_char);
         // LCD
         LCD_Position(0,7);
         LCD_PrCString("Score: ");
         LCD_PrString(score_char);
         
         // ライフの表示
         // UART
         UART_CPutString("\r\nlife : ");
         UART_PutString(life_char);
         // LCD
         LCD_Position(1,7);
         LCD_PrCString("Life : ");
         LCD_PrString(life_char);
         
         // 次の出題をUART側に要求して、2つ目のループを抜ける
         UART_CPutString("\r\n\r\nSet the Answer Tone.\r\n");
         break;
       }
     }
   }    
}

ブロック図

ブロック図3.png

考察

 作成した後に気づいたことだが、もしも回答者が間違った場合、
ヒントを表示したにも関わらず、出題者が次の問題(音)を自由に変えることができてしまう。
これだとヒントの価値がなくなってしまう。
せっかくヒントを表示したのだから、回答者が正解するまでずっと同じ音を鳴らすべきである。
つまり、出題者に「回答者が正解するまでは同じ音しか鳴らせない」
というような制限がついてあれば、より良いゲームが作れたであろう。

 無音(SILENT)を選択した場合、ゲーム終了としたいので
breakしてwhile文からループを抜けているが、
そのwhile文の上に更に大きなwhile文があるため
実は、完全にゲームを終了できていないことになっている。
この大きなwhile文からループを抜けることができれば
完全にゲームを終了することができるだろう。

  • 最終更新:2015-12-22 16:42:29

このWIKIを編集するにはパスワード入力が必要です

認証パスワード