//回路制作/プログラムH306015 犬飼 浩一 //使用部品 //PIC16F873A //セラミック発信素子20MHz //8×8LEDマトリックス(BU5004) //LEDマトリックスの電流増幅ドライバー(TD62083) //抵抗少々(120Ω、5.6kΩ、3.3kΩ) //ピン接続 //  ボタン関係 //PIN_C5(16pin) → 右移動 //PIN_C7(17pin) → 左移動 //PIN_A5(7pin) → 上移動(使ってない) //PIN_C6(17pin) → 下移動 //PIN_C4(15pin) → ローテーション //  LEDマトリックス関係 //   横列の接続 //PIN_B0(21pin) → C1 //PIN_B1(22pin) → C2 //PIN_B2(23pin) → C3 //PIN_B3(24pin) → C4 //PIN_B4(25pin) → C5 //PIN_B5(26pin) → C6 //PIN_B6(27pin) → C7 //PIN_B7(28pin) → C8 // 縦列の接続,ドライバ TD62083を経由する //PIN_A0(2pin) → R1 //PIN_A1(3pin) → R2 //PIN_A2(4pin) → R3 //PIN_A3(5pin) → R4 //PIN_C0(11pin) → R5 //PIN_C1(12pin) → R6 //PIN_C2(13pin) → R7 //PIN_C3(14pin) → R8 //表示が8×8と小さいので、通常のテトリスブロックを使うと //かなり窮屈なゲームになってしまうので、 //     ■ //■■ と ■ と ■ //■■   ■  ■■ //という3種類のブロックで構成されている //プログラムメモリ73% //データメモリ 46% #include <16F876A.h> #include #fuses HS,NOWDT,NOLVP,NOPROTECT,NOBROWNOUT #use delay(clock = 20000000) #use RS232(BAUD=9600,xmit=PIN_C6,rcv=PIN_C7) int matrix[8][11];//ブロックの状態保存用配列 int number[10][3];//数字表示用データ保存用配列 int st[2];//得点表示用 int i,l,j;//forループ用変数 int create_number=0;//ブロック総生成数 int delete_number=0;//ブロック削除回数(得点) int block_number; int rotation; int row; int line; long count=0; int time=0; int s1=0; int s2=0; int s3=0; int s4=0; int mode=0; int ti=0; int speed=0; void b_set(int block_number);//ブロック情報挿入関数 void b_end();//ゲームオーバー判定関数 void b_create();//生成 void b_delete();//削除 void b_down();//下移動 void b_move_r();//右移動 void b_move_l();//左移動 void b_rotate();//ブロック回転 void b_show();//LEDマトリックス表示 //----------------------------------ブロック情報挿入関数------------------------------------ //表にブロックの情報を挿入 void b_set(int block_number) { //表にブロックを代入 if(block_number==0) { row=3; line=8; matrix[row][line]=1; matrix[row+1][line]=1; matrix[row][line+1]=1; matrix[row+1][line+1]=1; } else if(block_number==1) { row=4; line=9; matrix[row][line-1]=1; matrix[row][line]=1; matrix[row][line+1]=1; rotation=1; } else if(block_number==2) { row=3; line=8; matrix[row][line+1]=1; matrix[row][line]=1; matrix[row+1][line]=1; rotation=3; } } //----------------------------------ゲームオーバー判定関数------------------------------------ //ブロックが見えない部分に残ったまま、この関数が呼び出されるとゲームオーバー void b_end() { if(line>7 && block_number==1 && rotation==0) { mode=2; } else if(line>6) { mode=2; } } //----------------------------------ブロックの生成関数------------------------------------ void b_create() { create_number++; block_number=rand()%3;//次に出すブロック決定 b_set(block_number);//ブロックを表示用配列上に挿入 } //----------------------------------そろったブロックの削除関数------------------------------------ //横8列そろったらその列を削除して、それよりも上の段のブロックを1段降ろす void b_delete() { int temp=0; int l2; for(l=0;l<8;l++) { temp=0; for(i=0;i<8;i++) { temp=temp+matrix[i][l]; } if(temp==8) { for(l2=l;l2<8;l2++) { for(i=0;i<8;i++) { matrix[i][l2]=matrix[i][l2+1]; } } delete_number++; } } } //----------------------------------ブロックの下移動関数------------------------------------ //countの値によってブロックの落ちてくる速度を決定 void b_down() { count=count+1; //スピード変更 //speedが大きいほど遅くなる //ブロックがcreate_numberで設定した数生成されると早くなる if(create_number>=20) { speed=30; } else if(create_number>=15) { speed=50; } else if(create_number>=10) { speed=75; } if(create_number<5) { speed=100; } if(count>speed) { count=0; if(block_number==0 && line>0 && matrix[row][line-1]==0 && matrix[row+1][line-1]==0) { matrix[row][line+1]=0; matrix[row+1][line+1]=0; line--; matrix[row][line]=1; matrix[row+1][line]=1; } else if(block_number==1 && rotation==0 && line>0 && matrix[row-1][line-1]==0 && matrix[row][line-1]==0 && matrix[row+1][line-1]==0) { matrix[row-1][line]=0; matrix[row][line]=0; matrix[row+1][line]=0; line--; matrix[row-1][line]=1; matrix[row][line]=1; matrix[row+1][line]=1; } else if(block_number==1 && rotation==1 && line>1 && matrix[row][line-2]==0) { matrix[row][line+1]=0; line--; matrix[row][line-1]=1; } else if(block_number==2 && line>0 && rotation==0 && matrix[row][line-1]==0 && matrix[row+1][line-1]==0) { matrix[row+1][line+1]=0; matrix[row][line]=0; line--; matrix[row][line]=1; matrix[row+1][line]=1; } else if(block_number==2 && line>0 && rotation==1 && matrix[row][line]==0 && matrix[row+1][line-1]==0) { matrix[row+1][line+1]=0; matrix[row][line+1]=0; line--; matrix[row+1][line]=1; matrix[row][line+1]=1; } else if(block_number==2 && line>0 && rotation==2 && matrix[row+1][line]==0 && matrix[row][line-1]==0) { matrix[row+1][line+1]=0; matrix[row][line+1]=0; line--; matrix[row+1][line+1]=1; matrix[row][line]=1; } else if(block_number==2 && line>0 && rotation==3 && matrix[row][line-1]==0 && matrix[row+1][line-1]==0) { matrix[row+1][line]=0; matrix[row][line+1]=0; line--; matrix[row][line]=1; matrix[row+1][line]=1; } else//ブロックが下について移動できなくなった場合 { b_delete();//b_delete()が3回続くのは1回では1列しか消すことができず、 b_delete();//最大3段まで消えることがあるので、3回b_delete()を呼び出している b_delete(); b_end();//新しいブロックを作る前にゲームオーバー判定 b_create(); } } } //----------------------------------ブロックの右移動関数------------------------------------ //ブロックの種類と状態から、移動先が空かどうかの判定をしてから移動 void b_move_r() { if(block_number==0 && row<6 && matrix[row+2][line]==0 && matrix[row+2][line+1]==0) { matrix[row][line]=0; matrix[row][line+1]=0; row++; matrix[row+1][line]=1; matrix[row+1][line+1]=1; } else if(block_number==1) { if(rotation==0 && row<6 && matrix[row+2][line]==0) { matrix[row-1][line]=0; row++; matrix[row+1][line]=1; } else if(rotation==1 && row<7 && matrix[row+1][line+1]==0 && matrix[row+1][line]==0 && matrix[row+1][line-1]==0) { matrix[row][line+1]=0; matrix[row][line]=0; matrix[row][line-1]=0; row++; matrix[row][line+1]=1; matrix[row][line]=1; matrix[row][line-1]=1; } } else if(block_number==2) { if(rotation==0 && row<6 && matrix[row+2][line]==0 && matrix[row+2][line+1]==0) { matrix[row][line]=0; matrix[row+1][line+1]=0; row++; matrix[row+1][line]=1; matrix[row+1][line+1]=1; } else if(rotation==1 && row<6 && matrix[row+2][line]==0 && matrix[row+2][line+1]==0) { matrix[row][line+1]=0; matrix[row+1][line]=0; row++; matrix[row+1][line]=1; matrix[row+1][line+1]=1; } else if(rotation==2 && row<6 && matrix[row+2][line+1]==0 && matrix[row+1][line]==0) { matrix[row][line]=0; matrix[row][line+1]=0; row++; matrix[row][line]=1; matrix[row+1][line+1]=1; } else if(rotation==3 && row<6 && matrix[row+2][line]==0 && matrix[row+1][line+1]==0) { matrix[row][line]=0; matrix[row][line+1]=0; row++; matrix[row+1][line]=1; matrix[row][line+1]=1; } } } //----------------------------------ブロックの左移動関数------------------------------------ //ブロックの種類と状態から、移動先が空かどうかの判定をしてから移動 void b_move_l() { if(block_number==0 && row>0 && matrix[row-1][line]==0 && matrix[row-1][line+1]==0) { matrix[row+1][line]=0; matrix[row+1][line+1]=0; row--; matrix[row][line]=1; matrix[row][line+1]=1; } else if(block_number==1) { if(rotation==0 && row>1 && matrix[row-2][line]==0) { matrix[row+1][line]=0; row--; matrix[row-1][line]=1; } else if(rotation==1 && row>0 && matrix[row-1][line+1]==0 && matrix[row-1][line]==0 && matrix[row-1][line-1]==0) { matrix[row][line+1]=0; matrix[row][line]=0; matrix[row][line-1]=0; row--; matrix[row][line+1]=1; matrix[row][line]=1; matrix[row][line-1]=1; } } else if(block_number==2) { if(rotation==0 && matrix[row-1][line]==0 && matrix[row][line+1]==0) { matrix[row+1][line]=0; matrix[row+1][line+1]=0; row--; matrix[row][line]=1; matrix[row+1][line+1]=1; } else if(rotation==1 && row>0 && matrix[row-1][line+1]==0 && matrix[row][line]==0) { matrix[row+1][line]=0; matrix[row+1][line+1]=0; row--; matrix[row][line+1]=1; matrix[row+1][line]=1; } else if(rotation==2 && row>0 && matrix[row-1][line]==0 && matrix[row-1][line+1]==0) { matrix[row][line]=0; matrix[row+1][line+1]=0; row--; matrix[row][line]=1; matrix[row][line+1]=1; } else if(rotation==3 && row>0 && matrix[row-1][line]==0 && matrix[row-1][line+1]==0) { matrix[row][line+1]=0; matrix[row+1][line]=0; row--; matrix[row][line]=1; matrix[row][line+1]=1; } } } //----------------------------------ブロック回転関数------------------------------------ //ブロックの種類と状態から、回転先が空かどうかの判定をしてから回転 void b_rotate() { if(block_number==1) { if(rotation==1 && row>0 && matrix[row-1][line]==0 && matrix[row+1][line]==0) { matrix[row][line-1]=0; matrix[row][line+1]=0; matrix[row-1][line]=1; matrix[row+1][line]=1; rotation=0; } else if(rotation==0 && line>0 && matrix[row][line-1]==0 && matrix[row][line+1]==0) { matrix[row-1][line]=0; matrix[row+1][line]=0; matrix[row][line-1]=1; matrix[row][line+1]=1; rotation=1; } } else if(block_number==2) { if(rotation==3 && matrix[row+1][line+1]==0) { matrix[row][line+1]=0; matrix[row+1][line+1]=1; rotation=0; } else if(rotation==0 && matrix[row][line+1]==0) { matrix[row][line]=0; matrix[row][line+1]=1; rotation=1; } else if(rotation==1 && matrix[row][line]==0) { matrix[row+1][line]=0; matrix[row][line]=1; rotation=2; } else if(rotation==2 && matrix[row+1][line]==0) { matrix[row+1][line+1]=0; matrix[row+1][line]=1; rotation=3; } } } //----------------------------------ブロック表示------------------------------------ //この表示関数を使えばmatrix[][]に保存されたデータを表示することができる //0=消灯 1=点灯 void b_show() { //表示部分(横スクロール) for(i=0;i<8;i++)//8ループで1回の表示 { //縦列の点灯情報の設定 output_bit(PIN_B0,matrix[i][0]); output_bit(PIN_B1,matrix[i][1]); output_bit(PIN_B2,matrix[i][2]); output_bit(PIN_B3,matrix[i][3]); output_bit(PIN_B4,matrix[i][4]); output_bit(PIN_B5,matrix[i][5]); output_bit(PIN_B6,matrix[i][6]); output_bit(PIN_B7,matrix[i][7]); //横の表示 if(i==0)//1列目 { output_bit(PIN_A0,1); delay_ms(1); output_bit(PIN_A0,0); } else if(i==1)//2列目 { output_bit(PIN_A1,1); delay_ms(1); output_bit(PIN_A1,0); } else if(i==2)//3列目 { output_bit(PIN_A2,1); delay_ms(1); output_bit(PIN_A2,0); } else if(i==3)//4列目 { output_bit(PIN_A3,1); delay_ms(1); output_bit(PIN_A3,0); } else if(i==4)//5列目 { output_bit(PIN_C0,1); delay_ms(1); output_bit(PIN_C0,0); } else if(i==5)//6列目 { output_bit(PIN_C1,1); delay_ms(1); output_bit(PIN_C1,0); } else if(i==6)//7列目 { output_bit(PIN_C2,1); delay_ms(1); output_bit(PIN_C2,0); } else if(i==7)//8列目 { output_bit(PIN_C3,1); delay_ms(1); output_bit(PIN_C3,0); } } } //----------------------------------メイン関数------------------------------------ void main() { //マトリックス用数字表示用データ //縦向きに見て、8ビット3列として保存してある //number[数字][何列目] //0=消灯 1=点灯 for(i=0;i<10;i++) { for(l=0;l<3;l++) { number[i][l]=0; } } //■■■ //■ ■ //■ ■ //■ ■ //■■■ number[0][0]=0b11111000; number[0][1]=0b10001000; number[0][2]=0b11111000; // ■ //■■ // ■ // ■ //■■■ number[1][0]=0b01001000; number[1][1]=0b11111000; number[1][2]=0b00001000; //■■■ //  ■ //■■■ //■ //■■■ number[2][0]=0b10111000; number[2][1]=0b10101000; number[2][2]=0b11101000; //■■■ //  ■ //■■■ //  ■ //■■■ number[3][0]=0b10101000; number[3][1]=0b10101000; number[3][2]=0b11111000; //  ■ // ■■ //■ ■ //■■■ //  ■ number[4][0]=0b00110000; number[4][1]=0b01010000; number[4][2]=0b11111000; //■■■ //■ //■■■ //  ■ //■■■ number[5][0]=0b11101000; number[5][1]=0b10101000; number[5][2]=0b10111000; //■■■ //■ //■■■ //■ ■ //■■■ number[6][0]=0b11111000; number[6][1]=0b10101000; number[6][2]=0b10111000; //■■■ //  ■ // ■ //□■ //□■ number[7][0]=0b10000000; number[7][1]=0b10111000; number[7][2]=0b11000000; //■■■ //■ ■ //■■■ //■ ■ //■■■ number[8][0]=0b11111000; number[8][1]=0b10101000; number[8][2]=0b11111000; //■■■ //■ ■ //■■■ //  ■ //■■■ number[9][0]=0b11101000; number[9][1]=0b10101000; number[9][2]=0b11111000; //----------------------------------メインループ------------------------------------ while(1) { //----------------------------------開始待機モード------------------------------------ if(mode==0) { //表示列初期化 output_bit(PIN_A0,0); output_bit(PIN_A1,0); output_bit(PIN_A2,0); output_bit(PIN_A3,0); output_bit(PIN_C0,0); output_bit(PIN_C1,0); output_bit(PIN_C2,0); output_bit(PIN_C3,0); //表示用配列初期化 for(i=0;i<8;i++) { for(l=0;l<11;l++) { matrix[i][l]=0; } } l=0; create_number=0; delete_number=0; while(mode==0)//----------------------------------開始待機モード用ループ------------------------------------ { if(input(PIN_C4)==0)//ゲームスタート { if(s3==0) { delay_us(50); mode=1; s3=1; } } else { s3=0; } l++; if(l==50000)//待機モードのときの点滅している部分 { matrix[3][3]=1; matrix[3][4]=1; matrix[4][3]=1; matrix[4][4]=1; } else if(l==100000) { matrix[3][3]=0; matrix[3][4]=0; matrix[4][3]=0; matrix[4][4]=0; l=0; } b_show();//ブロック表示 } } //----------------------------------ゲームモード------------------------------------ else if(mode==1) { //表示列初期化 output_bit(PIN_A0,0); output_bit(PIN_A1,0); output_bit(PIN_A2,0); output_bit(PIN_A3,0); output_bit(PIN_C0,0); output_bit(PIN_C1,0); output_bit(PIN_C2,0); output_bit(PIN_C3,0); //表示用配列初期化 for(i=0;i<8;i++) { for(l=0;l<11;l++) { matrix[i][l]=0; } } b_create();//最初のブロックを生成 while(mode==1)//----------------------------------ゲームモード用ループ------------------------------------ { b_down(); if(input(PIN_C5)==0)//右移動 { if(s1==0) { delay_us(50); b_move_r(); s1=1; } } else { s1=0; } if(input(PIN_C7)==0)//左移動 { if(s2==0) { delay_us(50); b_move_l(); s2=1; } } else { s2=0; } if(input(PIN_C4)==0)//ブロックローテーション { if(s3==0) { delay_us(50); b_rotate(); s3=1; } } else { s3=0; } if(input(PIN_C6)==0)//ブロックダウン { if(s4==0) { delay_us(50); count=999; s4=1; } } else { s4=0; } b_show();//ブロック表示 } } //----------------------------------終了モード------------------------------------ else if(mode==2) { //得点表示する前に、表示用配列のデータをすべて削除 for(i=0;i<8;i++) { for(l=0;l<8;l++) { matrix[i][l]=0; } } //st[1]に十の位の値を、st[0]に一の位の値を代入 st[1]=delete_number/10; st[0]=delete_number-st[1]*10; //数字データを表示用配列に代入 l=4; for(i=0;i<5;i++) { matrix[0][l]=bit_test(number[st[1]][0],l+3); matrix[1][l]=bit_test(number[st[1]][1],l+3); matrix[2][l]=bit_test(number[st[1]][2],l+3); matrix[4][l]=bit_test(number[st[0]][0],l+3); matrix[5][l]=bit_test(number[st[0]][1],l+3); matrix[6][l]=bit_test(number[st[0]][2],l+3); l--; } while(mode==2)//----------------------------------終了モード用ループ------------------------------------ { if(input(PIN_C4)==0)//ゲームスタート待機モードへ { if(s3==0) { delay_us(50); mode=0; s3=1; } } else { s3=0; } b_show();//ブロック表示 } } } }