/* ---------------------------------------- 'tetris.c' for softe2 by K.Egami (いつかどこかで見たようなプログラム) ---------------------------------------- */
#include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <signal.h>
struct itimerval timer_val; struct sigaction act;
void timer() { setitimer(ITIMER_REAL,&timer_val,(struct itimerval *)0); }
int screen[12*23] = {0,}; /* ゲーム画面の表示保存用配列 1次元配列で保存*/ int old_screen[12*23]; /* 1つ前の画面を保存する */
int pos = 17; /* 落ちてくるテトリスの場所 */ int pos_y; /* */
/* ***** テトリスの形状等の構造体定義 ***** */ struct STONE_PATTERN { int next ; /* 回転させたときの次のパターン */ int stone1; /* 1個目の石の場所 */ int stone2; /* 2個目の石の相対場所 */ int stone3; /* 3個目の石の相対場所 */ int stone4; /* 4個目の石の相対場所 */ } pattern[19] = { { 7, 0, -13, -12, 1}, /* 0 -> 7 -> 0 */ { 8, 0, -11, -12, -1}, /* 1 -> 8 -> 1 */ { 9, 0, -1, 1, 12}, /* 2 -> 9 -> 10 -> 11 -> 2 */ { 3, 0, -13, -12, -1}, /* 3 -> 3 */ { 12, 0, -1, 11, 1}, /* 4 -> 12 -> 13 -> 14 -> 4 */ { 15, 0, -1, 13, 1}, /* 5 -> 15 -> 16 -> 17 -> 5 */ { 18, 0, -1, 1, 2}, /* 6 -> 18 -> 6 */ { 0, 0, -12, -1, 11}, /* 7 */ { 1, 0, -12, 1, 13}, /* 8 */ { 10, 0, -12, 1, 12}, /* 9 */ { 11, 0, -12, -1, 1}, /* 10 */ { 2, 0, -12, -1, 12}, /* 11 */ { 13, 0, -12, 12, 13}, /* 12 */ { 14, 0, -11, -1, 1}, /* 13 */ { 4, 0, -13, -12, 12}, /* 14 */ { 16, 0, -11, -12, 12}, /* 15 */ { 17, 0, -13, 1, -1}, /* 16 */ { 5, 0, -12, 12, 11}, /* 17 */ { 6, 0, -12, 12, 24} /* 18 */ };
/* ***** 画面の描画する為の関数 ***** */ void update_screen(void) { int i;
for (i = 12;i < 12*22;i++) if (screen[i] != old_screen[i]) { printf("\033[%d;%dH", i / 12, i % 12 * 2 + 10); if (screen[i] > old_screen[i]) { printf("##"); /* 石・壁を書く */ } else { printf(" "); /* 石を消す */ } old_screen[i] = screen[i]; } }
/* ***** 回転・落下させたときに空間があるのか?のチェックを行う関数 ***** */ int is_empty(int value, int n) { if ( screen[ value + pattern[n].stone1 ] + screen[ value + pattern[n].stone2 ] + screen[ value + pattern[n].stone3 ] + screen[ value + pattern[n].stone4 ] == 0) { return 1; /* すきまあり */ } else { return 0; /* すきまなし */ } }
/* ***** テトリスのブロックをセット・リセットする関数 ***** */ set_block(int value, int n) { screen[ pos + pattern[n].stone1 ] = value; screen[ pos + pattern[n].stone2 ] = value; screen[ pos + pattern[n].stone3 ] = value; screen[ pos + pattern[n].stone4 ] = value; }
/* ********************** */ /* ***** メイン関数 ***** */ /* ********************** */ int main(void) { int i,j,k; int c; /* キーボードからの入力用 */ int n; /* 落下するテトリスのパターン番号 */
srand(time(0)); /* ゲーム・落下速度・・・数を大きくするとユックリになる */ timer_val.it_value.tv_usec = 300*1000; timer_val.it_value.tv_sec = 0;
system("stty cbreak -echo stop u"); act.sa_handler = timer; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGALRM, &act, 0); timer();
/* ゲームの枠データを設定 */ for (i = 0;i < 12*23; i++) { if ((i % 12 == 0) || (i % 12 == 11) || (i > 12*21)) screen[i] = 1; }
/* 画面の消去(クリア) */ printf("\033[H\033[J");
n = rand() % 7;
/* メインループ */ while (1) { set_block(1,n); update_screen(); /* 画面の更新 */ set_block(0,n);
c = getchar();
switch (c) {
case '4': /* '4' で左へ動かす */ if (is_empty(pos-1,n)) pos--; break; case '5': /* '5' で回転 */ if (is_empty(pos,pattern[n].next) ) n = pattern[n].next; break; case '6': /* '6' で右へ動かす */ if (is_empty(pos+1,n)) pos++; break; case ' ': /* ' ' で落とす */ while ( is_empty(pos + 12,n) ) { pos += 12; pos_y ++; } break;
default: /* それ以外のキー or 押さなかった */
if (is_empty(pos + 12,n)) { pos += 12; } else { /* 下まで落ちた場合 */ set_block(1,n); pos ++;
for (j = 0; j < 12*21; j += 12) { int k = 0; for (i = 1;i <= 10; i++) { k += screen[j + i]; } if (k == 10) { /* 石が1段そろっていたら・・・ */ for (i = 1;i <= 10; i++) screen[j + i] = 0; /* 1段全て消去 */ update_screen(); for (i = j;i > 0;i--) screen[i + 12] = screen[i]; /* パターンを1段下げる */ update_screen(); } } n = rand() % 7; pos = 17;
if (! is_empty(17,n)) { system("stty sane"); exit(0); /* ゲームオーバー */ } } /* end of if */ } /* end of switch */ } /* end of while */ }
|