チーム176A

課題名

15パズル

研究者名

Aozora Inagaki
Haruka Onodera

概要

4×4マトリックスキーパッドを用いて1から15までの数字を小さい順に以下のように並べるゲーム。
キャプチ.PNG
xは穴の位置を表し、xの上下左右のパネルはxの位置に移動させる事ができます。

操作方法
1:リセットボタンを押します
2:teratermにWelcomeが表示されたら難易度を選択します。キーボードでeasyなら'e',difficultなら'd'を入力してEnterを押します。
3:盤面が表示されたらゲームスタートです。xの文字の上下左右のボタンを押すとその位置のパネルがxの位置にずれます。
4:盤面がそろうまで頑張りましょう!

176a1.jpg
port0にマトリックスキーパッドをつなぎ、port1[3]とRX,port1[5]とTXをジャンパ線でつないだ。



使用機材

・PSoc基板
・ジャンパ線2本
・シリアル通信ケーブル
・PSocMiniProg
・4×4マトリックスキーパッド

ソースコード

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

/* These two variables are used to store the row number and the column number */

static const keypad_LUT[256] =
{/* 0 1 2 3 4 5 6 7
    8     9     A     B     C     D     E     F  */
/*0*/0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
/*1*/0x20, 'a', 'b', 0x20, 'c', 0x20, 0x20, 0x20,
   'd', 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
/*2*/0x20, 'e', 'f', 0x20, 'g', 0x20, 0x20, 0x20,
   'h', 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
/*3*/0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
/*4*/0x20, 'i', 'j', 0x20, 'k', 0x20, 0x20, 0x20,
   'l', 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
/*5*/0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
/*6*/0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
/*7*/0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
/*8*/0x20, 'm', 'n', 0x20, 'o', 0x20, 0x20, 0x20,
   'p', 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
/*9*/0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
/*A*/0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
/*B*/0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
/*C*/0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
/*D*/0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
/*E*/0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
/*F*/0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
};
BYTE rows,cols;

/* These two variables store the key number */
unsigned char key[2] = {0x20,0};
/*****************************************************/

int dif = 1;

/****************Functions****************************/

/* Handles keypad function- Checks the key pressed and debounces key */
void KeyPadHandler(void);

/* Keypad scanning routine */
unsigned char keypad_scan(void);

/* Initializes user modules used in the design */
void InitModules(void);

/* Interrupt handler for GPIO interrupt */
void GPIOInterrupt(void);
/****************************************************/


int master[6][6]= {{-1,-1,-1,-1,-1,-1},
                 {-1, 1, 2, 3, 4,-1},
                  {-1, 5, 6, 7, 8,-1},
                     {-1, 9,10,11,12,-1},
                  {-1,13,14,15, 0,-1},
                  {-1,-1,-1,-1,-1,-1}};

int que[6][6] = {{-1,-1,-1,-1,-1,-1},
                  {-1, 1, 2, 3, 4,-1},
                  {-1, 5, 6, 7, 8,-1},
                     {-1, 9,10,11,12,-1},
                  {-1,13,14,15, 0,-1},
                  {-1,-1,-1,-1,-1,-1}};

int xLoc[2]={4,4};

int make_board(){
  int i,ch=dif*2,t1,t2,tmp;
   char *d;
   for(i=0;i<ch;i++){
       t1=rand()%15+1;
       t2=t1;
       while(t1==t2)
           t2=rand()%15+1;
       tmp=que[((t1-1)/4)+1][(t1%4==0)? 4:t1%4];
       que[((t1-1)/4)+1][(t1%4==0)? 4:t1%4]=que[((t2-1)/4)+1][(t2%4==0)? 4:t2%4];
       que[((t2-1)/4)+1][(t2%4==0)? 4:t2%4]=tmp;
   }
   return ch/2;
}

void print_board(){
  int i,j,k;
   char buffer[3];
   for(i=0;i<6;i++){
       for(j=0;j<6;j++){
           if(que[i][j]==-1)
               UART_CPutString("   ");
           else if(que[i][j]==0)
               UART_CPutString("  x");
           else{
               itoa(buffer,que[i][j],10);
               if(que[i][j]<10)
                   UART_CPutString("  ");
               else
                   UART_CPutString(" ");
               UART_PutString(buffer);
           }
       }
       UART_CPutString("\r\n");
   }
}

void exchange(int n,int dif){
  int tmp;
   tmp=que[xLoc[0]][xLoc[1]];
   que[xLoc[0]][xLoc[1]]=(n==0)? que[xLoc[0]+dif][xLoc[1]]:que[xLoc[0]][xLoc[1]+dif];
   if(n==0)
       que[xLoc[0]+dif][xLoc[1]]=tmp;
   else
       que[xLoc[0]][xLoc[1]+dif]=tmp;
}

void operation(){
  int a,b,c,flag=0;
   while(1){
       if(key[0] != 0x20){
       c=key[0]-'a';
       switch(c){
           case 0: a=4;b=1;break;
           case 1: a=4;b=2;break;
           case 2: a=4;b=3;break;
           case 3: a=4;b=4;break;
           case 4: a=3;b=1;break;
           case 5: a=3;b=2;break;
           case 6: a=3;b=3;break;
           case 7: a=3;b=4;break;
           case 8: a=2;b=1;break;
           case 9: a=2;b=2;break;
           case 10: a=2;b=3;break;
           case 11: a=2;b=4;break;
           case 12: a=1;b=1;break;
           case 13: a=1;b=2;break;
           case 14: a=1;b=3;break;
           case 15: a=1;b=4;break;
           default: break; 
       }
           flag=0;
           if(xLoc[0]==a&&xLoc[1]!=b){
               if(b-xLoc[1]==1&&xLoc[1]+1<5){
                   exchange(1,1);
                   xLoc[1]+=1;
               }else if(b-xLoc[1]==-1&&xLoc[1]-1>0){
                   exchange(1,-1);
                   xLoc[1]-=1;
               }else
                   flag=2;
           }else if(xLoc[1]==b&&xLoc[0]!=a){
               if(a-xLoc[0]==1&&xLoc[0]+1<5){
                   exchange(0,1);
                   xLoc[0]+=1;
               }else if(a-xLoc[0]==-1&&xLoc[0]-1>0){
                   exchange(0,-1);
                   xLoc[0]-=1;
               }else
                   flag=2;
           }else{
               flag=2;
           }
           if(!flag){
               UART_CPutString("\r\nmove!\r\n");
               key[0] = 0x20;
               break;
           }
           else if(flag==2){
               UART_CPutString("\r\nerror : can't move!\r\n");
           }
           key[0] = 0x20;
       }
       
   }
}

int check_clear(){
  int i,j;
   for(i=1;i<5;i++){
       for(j=1;j<5;j++){
           if(que[i][j]!=master[i][j])
               return 1;
       }
   }
   return 0;
}

void result(int n,int d){
  char buffer[4];
   itoa(buffer,n,10);
   UART_CPutString("\r\n**********   clear!   **********\r\n\r\n");
   UART_CPutString("----------   result   ----------\r\n");
   UART_CPutString("                                \r\n");
   UART_CPutString("     difficulty : ");
   if(d==1)UART_CPutString("Easy\r\n");
   else if(d==2)UART_CPutString("Difficult\r\n");
   UART_CPutString("        count   : ");
   UART_PutString(buffer);
   UART_CPutString("\r\n                                \r\n");
   UART_CPutString("--------------------------------\r\n");
}


void main(void)
{
  int con=1,count=0,d,tc=0;
   char * strPtr; 
   /* Initialize variables and user modules */
   InitModules();
   UART_CmdReset();                      // Initialize receiver/cmd  
                                         // buffer  
   UART_IntCntl(UART_ENABLE_RX_INT);     // Enable RX interrupts
   Counter8_WritePeriod(155);            // Set up baud rate generator  
   Counter8_WriteCompareValue(77);
   Counter8_Start();                   // Turn on baud rate generator       
   UART_Start(UART_PARITY_NONE);         // Enable UART   
   
   /* Enable Global Interrupt */
   M8C_EnableGInt;
   
   UART_CPutString("\r\nWelcome to 15Puzzle!\r\n\r\nPlease input difficulty number\r\n\r\n(e:easy d:difficult)-> ");
   while(1) {
       tc++;
      if(UART_bCmdCheck()){   
         if(strPtr = UART_szGetParam()) {      
            UART_PutString(strPtr);
            if(*strPtr=='e'){
                dif=1;
               break;
            }else if(*strPtr=='d'){
                dif=2;
               break;
            }else{
                UART_CPutString("\r\n\r\nPlease input e or d-> \r\n\r\n");
            }
         }   
      UART_CmdReset();  
      }   
  }
  srand(tc*10);
  d = make_board();
   while(con){
       print_board();
       operation();
       count++;
       con=check_clear();
   }
   print_board();
   result(count,d);
   return;
}





/* This function initializes all the user modules used in the design */
void InitModules(void)
{
  /* Initilize timer- 10ms delay */
   Timer16_1_WritePeriod(320);
   Timer16_1_EnableInt();
       
   /* Enable GPIO interrupt */
   INT_MSK0|=0x20;
       
   /* Write 1's at column lines */
   PRT0DR|=0xF0;
}


/* This function scan the keypad and identifies the key pressed */
unsigned char keypad_scan(void)
{
  BYTE key_result;
       
   /* Drive rows */
   PRT0DR = 0x0F;
   
   /* Read columns */
   rows = PRT0DR;
   
   /* Drive columns */
   PRT0DR = 0xF0;
   
   /* Read rows */
   cols = PRT0DR;
   
   /* Combine results */
   key_result = rows & cols;
       
   /* Get the key number from LUT */
   return(keypad_LUT[key_result]);
}


/* This is the interrupt handler for the GPIO interrupt. Debounce timer is started on GPIO interrupt */
#pragma interrupt_handler GPIOInterrupt
void GPIOInterrupt(void)
{
  /* Disable GPIO interrupt */
   INT_MSK0&=~0x20;    
       
   /* Start Timer */
   Timer16_1_Start();
}


/* This is the interrupt handler for the timer. Scanning routine is called for key identification */
void TimerInterrupt(void)
{
  /* Stop the timer and update the flag */
   Timer16_1_Stop();
       
   /* Get the key */
   key[0] = keypad_scan();
   /* Clear GPIO posted interrupt */
   INT_CLR0&=~0x20;
       
   /* Enable GPIO interrupt */
   INT_MSK0|=0x20; 
}

回路図

zu.png

4*4マトリックスキーボードの入力を読み取るために割り込みを発生させるTimerモジュール
PCとの通信を行うUARTモジュールとクロック供給用のCounterモジュールを使用しています。
基本はmaster2014にあるMatrixkeypadをクローンしてuart_1の通信の仕組みを追加した。
Matrixkeypadの回路にcounter8,uartモジュールを追加して、上記の図のように配線する。
paramater、grobalresourcesはMatrixkeypadとuart_1に準ずる値にする。


考察

 今回は1から15までの数字をPC上に表示して15パズルを実現したが、数字ではなく画像で実現できるとより良いものになると考えた。だが、それを実現するためにはCUIの処理だけではなくGUIの処理を行う必要があるため時間的に難しく、この機能の実現には至らなかった。
この機能の実現のためには、Cにおいて画像処理を行う必要がありライブラリを使用しない場合はファイルに書き込む方式が考えられるがその方式ではリアルタイム表示ができないのでリアルタイムに画像が表示できるライブラリが存在すれば実現可能であると考えた。
 また、操作している途中に表示が途切れてしまうバグが散見された。このバグに関してはUART_PutString命令中に起こるため通信そのもののバグであると考えられる。

  • 最終更新:2017-12-19 17:06:24

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

認証パスワード