Skip to content

Instantly share code, notes, and snippets.

@HaruhiroTakahashi
Last active August 29, 2015 14:23
Show Gist options
  • Save HaruhiroTakahashi/8b8b1fa815cf8c7db3ba to your computer and use it in GitHub Desktop.
Save HaruhiroTakahashi/8b8b1fa815cf8c7db3ba to your computer and use it in GitHub Desktop.
/* 【メモ】
・自作の変数は先頭にmy_~を付けて作成。
・変数「x,y」は小さいループ。変数「i,j」は大きいループで使用。
*/
#include<stdio.h>
#include<stdlib.h> //「system("cls")」と「rand()」を使うためのヘッダファイル
#include<conio.h> //「_getch()」などを使うためのヘッダファイル
#include<time.h> //「time()」を使うためのヘッダファイル
/*定数*/
/*ブロック幅縦・横*/
#define BLOCK_HEIGHT 4
#define BLOCK_WIDTH 4
/*フィールド幅縦・横*/
#define FIELD_HEIGHT 23
#define FIELD_WIDTH 21
/*消去ブロック探索開始点*/
#define SEARCH_START_Y 19
#define SERACH_START_X 3
/*関数プロトタイプ宣言*/
void my_init_var();
void my_init_var2();
void my_op_scene();
void my_make_block();
void my_gameover();
void my_get_key();
void my_make_field();
void my_make_collision_field();
void my_init_field();
void my_save_field();
void my_freeze_block();
void my_search_line();
void my_draw_field();
void my_turn_right();
void my_turn_left();
void my_clear_field();
void my_timer();
/*グローバル変数*/
int first_block[BLOCK_HEIGHT][BLOCK_WIDTH];
int block[BLOCK_HEIGHT][BLOCK_WIDTH];
int stage[FIELD_HEIGHT][FIELD_WIDTH];
int field[FIELD_HEIGHT][FIELD_WIDTH];
int collision_field[FIELD_HEIGHT][FIELD_WIDTH];
/*ブロック7種類×4パターン*/
int blocks[28][16] = {
/* □ */ /*右図*/ /*対称図*/ /*左図*/
{ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0, },
{ 0, 1, 1, 0,/**/ 0, 1, 1, 0,/**/ 0, 1, 1, 0,/**/ 0, 1, 1, 0, },
{ 0, 1, 1, 0,/**/ 0, 1, 1, 0,/**/ 0, 1, 1, 0,/**/ 0, 1, 1, 0, },
{ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0, },
/* L */
{ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 1, 0, 0,/**/ 0, 0, 0, 0, },
{ 0, 1, 1, 0,/**/ 0, 0, 1, 0,/**/ 0, 1, 0, 0,/**/ 0, 1, 1, 1, },
{ 0, 0, 1, 0,/**/ 1, 1, 1, 0,/**/ 0, 1, 1, 0,/**/ 0, 1, 0, 0, },
{ 0, 0, 1, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0, },
/* 逆L */
{ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 1, 0,/**/ 0, 0, 0, 0, },
{ 0, 1, 1, 0,/**/ 1, 1, 1, 0,/**/ 0, 0, 1, 0,/**/ 0, 1, 0, 0, },
{ 0, 1, 0, 0,/**/ 0, 0, 1, 0,/**/ 0, 1, 1, 0,/**/ 0, 1, 1, 1, },
{ 0, 1, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0, },
/* N */
{ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0, },
{ 0, 0, 1, 0,/**/ 0, 1, 1, 0,/**/ 0, 0, 1, 0,/**/ 0, 1, 1, 0, },
{ 0, 1, 1, 0,/**/ 0, 0, 1, 1,/**/ 0, 1, 1, 0,/**/ 0, 0, 1, 1, },
{ 0, 1, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 1, 0, 0,/**/ 0, 0, 0, 0, },
/* 逆N */
{ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0, },
{ 0, 1, 0, 0,/**/ 0, 0, 1, 1,/**/ 0, 1, 0, 0,/**/ 0, 0, 1, 1, },
{ 0, 1, 1, 0,/**/ 0, 1, 1, 0,/**/ 0, 1, 1, 0,/**/ 0, 1, 1, 0, },
{ 0, 0, 1, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 1, 0,/**/ 0, 0, 0, 0, },
/* T */
{ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 0, 0, 0, },
{ 0, 1, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 1, 0, 0,/**/ 0, 1, 0, 0, },
{ 0, 1, 1, 0,/**/ 1, 1, 1, 0,/**/ 1, 1, 0, 0,/**/ 1, 1, 1, 0, },
{ 0, 1, 0, 0,/**/ 0, 1, 0, 0,/**/ 0, 1, 0, 0,/**/ 0, 0, 0, 0, },
/* I */
{ 0, 1, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 1, 0, 0,/**/ 0, 0, 0, 0, },
{ 0, 1, 0, 0,/**/ 1, 1, 1, 1,/**/ 0, 1, 0, 0,/**/ 1, 1, 1, 1, },
{ 0, 1, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 1, 0, 0,/**/ 0, 0, 0, 0, },
{ 0, 1, 0, 0,/**/ 0, 0, 0, 0,/**/ 0, 1, 0, 0,/**/ 0, 0, 0, 0, },
};
int block_index_x[4] = { 0, 4, 8, 12 };
int block_index_y[7] = { 0, 4, 8, 12, 16, 20, 24 };
int fall;
int side;
int gameover_flag;
int block_flag;
int block_flag2;
int freeze_flag;
int fall_point;
int ran;
int ran2;
int turn_point;
int score;
int lv;
/*メイン*/
int main(){
my_init_var();
my_init_field();
my_draw_field();
my_op_scene();
while (1){
if (gameover_flag == 0){
my_make_block();//ブロック生成
my_gameover();//ゲームオーバー判定
my_get_key();//キー入力判定
my_make_field();//フィールド生成
my_init_field();//フィールド初期化
my_freeze_block();//残るブロックの判定
my_draw_field();//数字情報を絵柄に置き換える
my_clear_field();//フィールドの情報をクリア
my_timer();//時間稼ぎ処理
}
else{
printf("Gmae Over\n");
break;
}
fall++;
}
return 0;
}
/*グローバル変数初期化・開始時のみ*/
void my_init_var(){
fall = 0;
side = 6;
gameover_flag = 0;
block_flag = 0;
block_flag2 = 0;
freeze_flag = 0;
fall_point = 0;
ran = 0;
ran2 = 0;
turn_point = 400;
score = 0;
lv = 1;
}
/*グローバル変数初期化・ブロック再生成時*/
void my_init_var2(){
fall = 0;
side = 6;
block_flag2 = 0;
freeze_flag = 0;
fall_point = 0;
turn_point = 400;
}
/*オープニング*/
void my_op_scene(){
int any_key;
printf("\n====TETRIS====\n");
printf("Press any key to start");
any_key = _getch();
if (any_key == 0 || any_key == 224) any_key = _getch();
}
/*ブロック生成*/
/*
2段階にブロックを生成
最初に作ったブロックを「first_block[4][4]」に保存して
そのまま「block[4][4]」に「first_block[4][4]」を移し替える
そのあと続けてブロックを作って「first_block[4][4]」に保存する
次からは「first_block[4][4]」→「block[4][4]」
ブロック生成→「first_block[4][[4]」の流れを繰り返す
*/
void my_make_block(){
int x, y;
if (block_flag == 0){
srand((unsigned)time(NULL));
ran = (rand() % 7);
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
first_block[y][x] = blocks[block_index_y[ran] + y]
[block_index_x[0] + x];
}
}
block_flag = 1;
}
if (block_flag2 == 0){
srand((unsigned)time(NULL));
ran2 = ran;
ran = (rand() % 7);
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
block[y][x] = first_block[y][x];
first_block[y][x] = blocks[block_index_y[ran] + y]
[block_index_x[0] + x];
}
}
block_flag2 = 1;
}
}
/*ゲームオーバー判定*/
void my_gameover(){
int x, y;
my_make_collision_field();
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
if (block[y][x] != 0){
if (collision_field[fall + y][side + x] != 0){
gameover_flag++;
}
}
}
}
}
/*キー入力*/
void my_get_key(){
int x, y;
int key = 0;
int side_flag = 0;
int fall_flag = 0;
my_make_collision_field();
if (_kbhit()){
key = _getch();
if (key == 0 || key == 224) key = _getch();
switch (key){
case 0x4b://左
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
if (block[y][x] != 0){
if (collision_field[fall + y][side + (x - 1)] != 0){
side_flag++;
}
}
}
}
if (side_flag == 0){
side--;
}
break;
case 0x4d://右
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
if (block[y][x] != 0){
if (collision_field[fall + y][side + (x + 1)] != 0){
side_flag++;
}
}
}
}
if (side_flag == 0){
side++;
}
break;
case 0x50://下
while (fall_flag == 0){
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
if (block[y][x] != 0){
if (collision_field[fall + (y + 1)][side + x] != 0){
fall_flag++;
}
}
}
}
if (fall_flag == 0){
fall++;
}
}
break;
case 0x48://上
my_turn_right();
break;
case 'z':
my_turn_left();
break;
default:
break;
}
}
}
/*「field」に「block」と「stage」を登録*/
void my_make_field(){
int i, j, x, y;
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
field[y + fall][x + side] = block[y][x];
}
}
for (i = 0; i < FIELD_HEIGHT; i++){
for (j = 0; j < FIELD_WIDTH; j++){
field[i][j] = field[i][j] + stage[i][j];
}
}
}
/*当たり判定用フィールド作成*/
void my_make_collision_field(){
int i, j;
for (i = 0; i<FIELD_HEIGHT; i++){
for (j = 0; j<FIELD_WIDTH; j++){
collision_field[i][j] = stage[i][j];
collision_field[i][0] = 9;
collision_field[i][1] = 9;
collision_field[i][2] = 9;
collision_field[20][j] = 9;
collision_field[21][j] = 9;
collision_field[22][j] = 9;
collision_field[i][13] = 9;
collision_field[i][14] = 9;
collision_field[i][15] = 9;
collision_field[i][16] = 9;
collision_field[i][17] = 9;
collision_field[i][18] = 9;
collision_field[i][19] = 9;
collision_field[i][20] = 9;
}
}
}
/*フィールドの端に「9」を登録*/
/*スコアボード等を作成*/
/*スコアボードに使う文字表記を文字コードで書く*/
void my_init_field(){
int i, j, x, y;
int dispsc[4] = { 0 };
for (i = 0; i < FIELD_HEIGHT; i++){
for (j = 0; j < FIELD_WIDTH; j++){
field[i][2] = 9;
field[20][j] = 9;
field[i][13] = 9;
}
}
/*スコアボード等を作成*/
for (i = 0; i < FIELD_HEIGHT; i++){
for (j = 16; j < FIELD_WIDTH; j++){
field[i][j] = 19;
}
}
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
field[y + 2][x + 16] = first_block[y][x] + 10;
//↑16,y-2)の位置
}
}
if (score < 10){
dispsc[0] = 10;
dispsc[1] = 10;
dispsc[2] = 10;
dispsc[3] = score;
}
else if (score < 100){
dispsc[0] = 10;
dispsc[1] = 10;
dispsc[2] = score / 10;
dispsc[3] = score - ((score / 10) * 10);
}
else{
dispsc[0] = 10;
dispsc[1] = 10;
dispsc[2] = 9;
dispsc[3] = 9;
}
/*NEXT*/
field[1][16] = 78;
field[1][17] = 69;
field[1][18] = 88;
field[1][19] = 84;
/*SC*/
field[8][16] = 10;
field[8][17] = 10;
field[8][18] = 83;
field[8][19] = 67;
field[9][16] = dispsc[0];
field[9][17] = dispsc[1];
field[9][18] = dispsc[2];
field[9][19] = dispsc[3];
/*LV*/
field[11][16] = 10;
field[11][17] = 10;
field[11][18] = 76;
field[11][19] = 86;
field[12][16] = 10;
field[12][17] = 10;
field[12][18] = 10;
field[12][19] = lv;
}
/*ブロック固定判定*/
/*後半ブロック固定を2段階に*/
/*一回目は固定せずにその落下地点だけ保存して「fall」を戻す*/
/*次も同じ落下地点だったら固定*/
void my_freeze_block(){
int x, y;
my_make_collision_field();
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
if (block[y][x] != 0){
if (collision_field[fall + (y + 1)][side + x] != 0){
freeze_flag++;
}
}
}
}
if (freeze_flag != 0){
if (fall_point == fall){
my_search_line();
my_save_field();
my_init_var2();
}
else{
freeze_flag = 0;
fall_point = fall;
fall--;
}
}
}
/*ブロック消去判定*/
void my_search_line(){
int i, j;
int zero_count = 0;
int clear_flag = 0;
int clear_lines_point[4] = { 0 };
int clear_line_index = 0;
int remain_lines_point[20] = { 0 };
int remain_line_index = 0;
for (i = SEARCH_START_Y; i >= SEARCH_START_Y - 19; i--){
for (j = SERACH_START_X; j < SERACH_START_X + 10; j++){
if (field[i][j] == 0){
zero_count++;
}
}
if (zero_count == 0){
clear_flag++;
clear_lines_point[clear_line_index] = i;
clear_line_index++;
score++;
}
else{
remain_lines_point[remain_line_index] = i;
remain_line_index++;
zero_count = 0;
}
}
if (clear_flag != 0){
for (clear_line_index = 0; clear_line_index < 4; clear_line_index++){
if (clear_lines_point[clear_line_index] != 0){
for (j = SERACH_START_X; j < SERACH_START_X + 10; j++){
field[clear_lines_point[clear_line_index] != 0][j] = 0;
}
}
}
my_draw_field();
my_timer();
remain_line_index = 0;
for (i = SEARCH_START_Y; i >= SEARCH_START_Y - 19; i--){
for (j = SERACH_START_X; j < SERACH_START_X + 10; j++){
field[i][j] = field[remain_lines_point[remain_line_index]][j];
}
remain_line_index++;
}
}
}
/*ブロック固定時にフィールドをステージに保存*/
void my_save_field(){
int i, j;
for (i = 0; i<FIELD_HEIGHT; i++){
for (j = 0; j<FIELD_WIDTH; j++){
stage[i][j] = field[i][j];
}
}
}
/*画面をクリアしてから完成した「field」を表示*/
/*後半部分スコアボード表示*/
/*文字コード65(A)以上が来たら文字コードとして「%c」で表示*/
void my_draw_field(){
int i, j;
system("cls");
for (i = 0; i<FIELD_HEIGHT - 2; i++){
for (j = 2; j<14; j++){
if (field[i][j] == 9)printf("■");
else if (field[i][j] == 1)printf("□");
else if (field[i][j] == 2)printf("■");
else printf(" ");
}
for (j = 16; j<21; j++){
if (field[i][j] >= 65)printf(" %c", field[i][j]);
else if (field[i][j] < 10)printf(" %d", field[i][j]);
else if (field[i][j] == 19)printf("■");
else if (field[i][j] == 11)printf("□");
else printf(" ");
}
printf("\n");
}
}
/*右回転*/
void my_turn_right(){
int x, y;
int turn_flag = 0;
int turn_block[4][4] = { 0 };
turn_point++;
my_make_collision_field();
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
turn_block[y][x] = blocks[block_index_y[ran2] + y]
[block_index_x[turn_point % 4] + x];
}
}
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
if (turn_block[y][x] != 0){
if (collision_field[fall + y][side + x] != 0){
turn_flag++;
}
}
}
}
if (turn_flag == 0){
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
block[y][x] = turn_block[y][x];
}
}
}
else{
turn_point--;
}
}
/*左回転*/
void my_turn_left(){
int x, y;
int turn_flag = 0;
int turn_block[4][4] = { 0 };
turn_point--;
my_make_collision_field();
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
turn_block[y][x] = blocks[block_index_y[ran2] + y]
[block_index_x[turn_point % 4] + x];
}
}
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
if (turn_block[y][x] != 0){
if (collision_field[fall + y][side + x] != 0){
turn_flag++;
}
}
}
}
if (turn_flag == 0){
for (y = 0; y < BLOCK_HEIGHT; y++){
for (x = 0; x < BLOCK_WIDTH; x++){
block[y][x] = turn_block[y][x];
}
}
}
else{
turn_point++;
}
}
/*フィールドクリア*/
void my_clear_field(){
int i, j;
for (i = 0; i < FIELD_HEIGHT; i++){
for (j = 0; j < FIELD_WIDTH; j++){
field[i][j] = 0;
}
}
}
/*時間稼ぎ*/
/*消去ライン数に応じてレベル・スピード変化*/
void my_timer(){
int x, y;
int max;
if (score < 90){
lv = (score / 10) + 1;
max = 10000 - (score * 100);
}
else{
lv = 9;
max = 1000;
}
for (y = 0; y < max; y++){
for (x = 0; x < max; x++){
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment