# 小專題4 Tetris 烏克蘭方塊
## 開頭
5秒後開始

```c
printf(" .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. \n");
printf("| .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | \n");
printf("| | _________ | || | _________ | || | _________ | || | _______ | || | _____ | || | _______ | | \n");
printf("| | | _ _ | | || | |_ ___ | | || | | _ _ | | || | |_ __ \\ | || | |_ _| | || | / ___ | | | \n");
printf("| | |_/ | | \\_| | || | | |_ \\_| | || | |_/ | | \\_| | || | | |__) | | || | | | | || | | (__ \\_| | | \n");
printf("| | | | | || | | _| _ | || | | | | || | | __ / | || | | | | || | '.___`-. | | \n");
printf("| | _| |_ | || | _| |___/ | | || | _| |_ | || | _| | \\ \\_ | || | _| |_ | || | |`\\____) | | | \n");
printf("| | |_____| | || | |_________| | || | |_____| | || | |____| |___| | || | |_____| | || | |_______.' | | \n");
printf("| | | || | | || | | || | | || | | || | | | \n");
printf("| '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | \n");
printf(" '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' \n");
sleep(5);
```
## 增加功能
### 1.space
按空白鍵直接到底
```c
case 32:
while(isCollision(cur_x,cur_y+1)!=1)
{
eraseBlock(block_cur,cur_x,cur_y);
cur_y++;
printBlock(block_cur,cur_x,cur_y);
}
break;
```
### 2.整版變色
```c
case O:
system("color 01");
copy_block(blockO,block_cur);
break;
case J:
system("color 02");
copy_block(blockJ,block_cur);
break;
.
.
.
```
七種顏色
#### 1.O

#### 2.J

#### 3.L

#### 4.I

#### 5.Z

#### 6.S

#### 7.T

### 3.分數
削掉一條+10分
```c
clear_line++;
score += 10;
```

## 完整程式碼
```c
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <conio.h>
#define HEIGHT 14
#define WIDTH 18
#define block_h 4
#define block_w 4
HANDLE hand;
int cur_x,cur_y;
int block_cur[block_h][block_w]={0};
int screen[HEIGHT][WIDTH]={0};
int blockO[block_h][block_w]={
{0,0,0,0},
{0,1,1,0},
{0,1,1,0},
{0,0,0,0}
};
int blockL[block_h][block_w]={
{0,1,0,0},
{0,1,0,0},
{0,1,1,0},
{0,0,0,0}
};
int blockJ[block_h][block_w]={
{0,0,1,0},
{0,0,1,0},
{0,1,1,0},
{0,0,0,0}
};
int blockI[block_h][block_w]={
{0,1,0,0},
{0,1,0,0},
{0,1,0,0},
{0,1,0,0}
};
int blockZ[block_h][block_w]={
{0,0,0,0},
{1,1,0,0},
{0,1,1,0},
{0,0,0,0}
};
int blockS[block_h][block_w]={
{0,0,0,0},
{0,1,1,0},
{1,1,0,0},
{0,0,0,0}
};
int blockT[block_h][block_w]={
{0,0,0,0},
{1,1,1,0},
{0,1,0,0},
{0,0,0,0}
};
enum block_type{
O,J,L,I,Z,S,T
};
int block_type_num = 7;
int score=0;
int clear_line = 0;
int tm = 800;
UINT_PTR timerId;
void setCursorVisible(int v){
CONSOLE_CURSOR_INFO info={1, v};//size1-100 v bool
SetConsoleCursorInfo(hand, &info);
}
void gotoxy(int x, int y){
COORD pos={.X=x, .Y=y};
SetConsoleCursorPosition(hand, pos);
}
static void set_timer(int t){
KillTimer(NULL, timerId);
timerId = SetTimer(NULL,0,t,NULL);
}
static void close_timer(){
KillTimer(NULL, timerId);
}
void printxy(char c, int x, int y){
gotoxy(x, y);
printf("%c",c);
}
void printScreen(){
int i,j;
for(i=0;i<WIDTH;i++){
printxy('E',i+6,1);
printxy('E',i+6,2+HEIGHT);
}
for(j=-1;j<HEIGHT+1;j++){
printxy('E',5,j+2);
printxy('E',6+WIDTH,j+2);
}
for(i=0;i<WIDTH;i++){
for(j=0;j<HEIGHT;j++){
if(screen[j][i]==0){
printxy(' ',i+6,j+2);
}
else{
printxy('O',i+6,j+2);
}
}
}
gotoxy(30,12);
printf("shift left : <-");
gotoxy(30,14);
printf("shift right : ->");
gotoxy(30,16);
printf("rotate : up");
gotoxy(30,18);
printf("lower : down");
gotoxy(30,20);
printf("bace : space");
gotoxy(0,20);
printf("score:%d\n",score);
printf("clearn_line:%d\n",clear_line);
}
void printBlock(int block[][block_w],int x,int y){
int i,j;
for(i=0;i<block_h;i++){
for(j=0;j<block_w;j++){
if(block[i][j]==1){
printxy('O',x+6+j,y+2+i);
}
}
}
}
void eraseBlock(int block[][block_w],int x,int y){
int i,j;
for(i=0;i<block_w;i++){
for(j=0;j<block_h;j++){
if(block[i][j]==1){
printxy(' ',x+6+j,y+2+i);
}
}
}
}
int get_block_y_fill(int row){
int ans=0;
for(int col=0;col<block_w;col++){
if(block_cur[row][col]==1){
ans=1;
}
}
return ans;
}
int get_block_x_fill(int col){
int ans=0;
for(int row=0;row<block_w;row++){
if(block_cur[row][col]==1){
ans=1;
}
}
return ans;
}
void get_block_left_right_margin(int *left_margin ,int *right_margin){
for(int col=0;col<2;col++){
if(get_block_x_fill(col)==0){
*left_margin=*left_margin+1;
}
}
for(int col=2;col<4;col++){
if(get_block_x_fill(col)==0){
*right_margin=*right_margin+1;
}
}
return ;
}
void get_block_top_button_margin(int *top_margin ,int *button_margin){
for(int row=0;row<2;row++){
if(get_block_y_fill(row)==0){
*top_margin=*top_margin+1;
}
}
for(int row=2;row<4;row++){
if(get_block_y_fill(row)==0){
*button_margin=*button_margin+1;
}
}
}
int isCollision(int x , int y){
int top_margin=0,button_margin=0,left_margin=0,right_margin=0;
get_block_top_button_margin(&top_margin,&button_margin);
get_block_left_right_margin(&left_margin,&right_margin);
if(x<0-left_margin || y<0-top_margin || x>WIDTH-block_w+right_margin || y>HEIGHT-block_h+button_margin){
return 1;
}
int w,h;
for(w=0;w<block_w;w++){
for(h=0;h<block_h;h++){
if(block_cur[h][w]==1){
if(screen[y+h][x+w]==1){
return 1;
}
}
}
}
return 0;
}
int is_line_fill(int h){
int w;
for(w=0;w<WIDTH;w++){
if(screen[h][w]==0){
return 0;
}
}
return 1;
}
void clear_one_line(int h){
int w,row;
for(row = h;row>0;row--){
for(w=0;w<WIDTH;w++){
screen[row][w] = screen[row-1][w];
}
}
for(w=0;w<WIDTH;w++){
screen[0][w] = 0;
}
clear_line++;
score += 10;
}
void check_line(){
int total_line = 0;
int h;
for(h=cur_y;h<HEIGHT;h++)
{
if(is_line_fill(h)==1)
{
clear_one_line(h);
printScreen();
total_line++;
}
}
}
void land_block(){
int w,h;
for(w=0;w<block_w;w++){
for(h=0;h<block_h;h++){
if(block_cur[h][w]==1){
screen[cur_y+h][cur_x+w]=1;
}
}
}
}
void copy_block(int block_s[][block_w],int block_d[][block_w]){
int w,h;
for(w=0;w<block_w;w++){
for(h=0;h<block_h;h++){
block_d[h][w] = block_s[h][w];
}
}
}
void rotate_block(){
int temp[block_h][block_w] = {0};
copy_block(block_cur,temp);
int w,h;
for(w=0;w<block_w;w++){
for(h=0;h<block_h;h++){
block_cur[h][w] = temp[w][block_h-1-h];
}
}
}
void make_new_block(){
enum block_type type = (int)(rand() % block_type_num);
switch(type){
case O:
system("color 01");
copy_block(blockO,block_cur);
break;
case J:
system("color 02");
copy_block(blockJ,block_cur);
break;
case L:
system("color 03");
copy_block(blockL,block_cur);
break;
case I:
system("color 04");
copy_block(blockI,block_cur);
break;
case Z:
system("color 05");
copy_block(blockZ,block_cur);
break;
case S:
system("color 06");
copy_block(blockS,block_cur);
break;
case T:
system("color 07");
copy_block(blockT,block_cur);
break;
default:
break;
}
cur_x = (WIDTH-block_w)/2;
cur_y = 0;
printBlock(block_cur,cur_x,cur_y);
}
void move_block_down(){
if(isCollision(cur_x,cur_y+1)!=1){
eraseBlock(block_cur,cur_x,cur_y);
cur_y++;
printBlock(block_cur,cur_x,cur_y);
}
else{
land_block();
check_line();
make_new_block();
printBlock(block_cur,cur_x,cur_y);
if(isCollision(cur_x,cur_y)==1){
close_timer();
}
}
}
void key_control(){
MSG msg;
while(1){
if(PeekMessage(&msg,NULL,WM_TIMER,WM_TIMER,PM_REMOVE)!=0){//如果timer的倒數結束,會發訊息到這裡
move_block_down();
}
if(kbhit()!=0){
char ch=getch();
switch(ch){
case 72://up
eraseBlock(block_cur,cur_x,cur_y);
rotate_block();
if(isCollision(cur_x,cur_y)==1)
{
rotate_block();
rotate_block();
rotate_block();
}
printBlock(block_cur,cur_x,cur_y);
break;
case 80://down
if(isCollision(cur_x,cur_y+1)!=1){
eraseBlock(block_cur,cur_x,cur_y);
cur_y++;
printBlock(block_cur,cur_x,cur_y);
}
break;
case 75://left
if(isCollision(cur_x-1,cur_y)!=1){
eraseBlock(block_cur,cur_x,cur_y);
cur_x--;
printBlock(block_cur,cur_x,cur_y);
}
break;
case 77://right
if(isCollision(cur_x+1,cur_y)!=1){
eraseBlock(block_cur,cur_x,cur_y);
cur_x++;
printBlock(block_cur,cur_x,cur_y);
}
break;
case 32:
while(isCollision(cur_x,cur_y+1)!=1)
{
eraseBlock(block_cur,cur_x,cur_y);
cur_y++;
printBlock(block_cur,cur_x,cur_y);
}
break;
}
}
}
}
int main(){
printf(" .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. \n");
printf("| .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | \n");
printf("| | _________ | || | _________ | || | _________ | || | _______ | || | _____ | || | _______ | | \n");
printf("| | | _ _ | | || | |_ ___ | | || | | _ _ | | || | |_ __ \\ | || | |_ _| | || | / ___ | | | \n");
printf("| | |_/ | | \\_| | || | | |_ \\_| | || | |_/ | | \\_| | || | | |__) | | || | | | | || | | (__ \\_| | | \n");
printf("| | | | | || | | _| _ | || | | | | || | | __ / | || | | | | || | '.___`-. | | \n");
printf("| | _| |_ | || | _| |___/ | | || | _| |_ | || | _| | \\ \\_ | || | _| |_ | || | |`\\____) | | | \n");
printf("| | |_____| | || | |_________| | || | |_____| | || | |____| |___| | || | |_____| | || | |_______.' | | \n");
printf("| | | || | | || | | || | | || | | || | | | \n");
printf("| '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | \n");
printf(" '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' \n");
sleep(5);
system("cls");
hand=GetStdHandle(STD_OUTPUT_HANDLE);
srand(time(NULL));
setCursorVisible(0);
set_timer(tm);
int i,j;
for(i=0;i<WIDTH;i++){
for(j=0;j<HEIGHT;j++){
screen[j][i]=0;
}
}
printScreen();
make_new_block();
key_control();
return 0;
}
```