# Tetris第二週進度
## 課前
先將上禮拜製作的 Code 從 GitHub 上 Pull 下
可參考先前的講義內容
## 第二周功能
上個禮拜的進度到讓同學們能輸出不同俄羅斯方塊出來,以下是今天的內容
- define 長寬
長20 寬10的板子
```c=
#define CANVAS_WIDTH 10
#define CANVAS_HEIGHT 20
```
- Block
- 遊戲板
這是每一個格子的結構,我們會將其用於二維陣列
```c=
typedef struct {
Color color;
ShapeId shape;
bool current;
}Block;
```
- 兩個Block函式
- 為此位置設置block的屬性
```c
void setBlock(Block* block, Color color, ShapeId shape, bool current)
```
- 重設block的屬性
```c
void resetBlock(Block* block)
```
- State
遊戲的狀態(分數、座標位置、旋轉模式、掉落時間、QUEUE裡的方塊是?)
```c=
typedef struct {
int x;
int y;
int score;
int rotate;
int fallTime;
ShapeId queue[4];
}State;
```
- 將BLOCK輸出看看
先不輸出空白,使大家能更看出這個空間感

## 課堂練習
想像遊戲即將開始那方塊要出現在哪
請完成如圖,利用雙for迴圈、State達到,放入一個 J

## 參考
[\u3000](https://blog.csdn.net/lilongsy/article/details/78288697)
## 課堂CODE
```c=
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#define CANVAS_WIDTH 10
#define CANVAS_HEIGHT 20
typedef enum {
RED = 41,
GREEN,
YELLOW,
BLUE,
PURPLE,
CYAN,
WHITE,
BLACK = 0,
}Color;
typedef enum {
EMPTY = -1,
I,
J,
L,
O,
S,
T,
Z
}ShapeId;
typedef struct {
ShapeId shape;
Color color;
int size;
char rotates[4][4][4];
}Shape;
typedef struct
{
int x;
int y;
int score;
int rotate;
int fallTime;
ShapeId queue[4];
}State;
typedef struct {
Color color;
ShapeId shape;
bool current;
}Block;
Shape shapes[7] = {
{
.shape = I,
.color = CYAN,
.size = 4,
.rotates =
{
{
{0, 0, 0, 0},
{1, 1, 1, 1},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{0, 0, 1, 0},
{0, 0, 1, 0},
{0, 0, 1, 0},
{0, 0, 1, 0}
},
{
{0, 0, 0, 0},
{0, 0, 0, 0},
{1, 1, 1, 1},
{0, 0, 0, 0}
},
{
{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 0, 0}
}
}
},
{
.shape = J,
.color = BLUE,
.size = 3,
.rotates =
{
{
{1, 0, 0},
{1, 1, 1},
{0, 0, 0}
},
{
{0, 1, 1},
{0, 1, 0},
{0, 1, 0}
},
{
{0, 0, 0},
{1, 1, 1},
{0, 0, 1}
},
{
{0, 1, 0},
{0, 1, 0},
{1, 1, 0}
}
}
},
{
.shape = L,
.color = YELLOW,
.size = 3,
.rotates =
{
{
{0, 0, 1},
{1, 1, 1},
{0, 0, 0}
},
{
{0, 1, 0},
{0, 1, 0},
{0, 1, 1}
},
{
{0, 0, 0},
{1, 1, 1},
{1, 0, 0}
},
{
{1, 1, 0},
{0, 1, 0},
{0, 1, 0}
}
}
},
{
.shape = O,
.color = WHITE,
.size = 2,
.rotates =
{
{
{1, 1},
{1, 1}
},
{
{1, 1},
{1, 1}
},
{
{1, 1},
{1, 1}
},
{
{1, 1},
{1, 1}
}
}
},
{
.shape = S,
.color = GREEN,
.size = 3,
.rotates =
{
{
{0, 1, 1},
{1, 1, 0},
{0, 0, 0}
},
{
{0, 1, 0},
{0, 1, 1},
{0, 0, 1}
},
{
{0, 0, 0},
{0, 1, 1},
{1, 1, 0}
},
{
{1, 0, 0},
{1, 1, 0},
{0, 1, 0}
}
}
},
{
.shape = T,
.color = PURPLE,
.size = 3,
.rotates =
{
{
{0, 1, 0},
{1, 1, 1},
{0, 0, 0}
},
{{0, 1, 0},
{0, 1, 1},
{0, 1, 0}
},
{
{0, 0, 0},
{1, 1, 1},
{0, 1, 0}
},
{
{0, 1, 0},
{1, 1, 0},
{0, 1, 0}
}
}
},
{
.shape = Z,
.color = RED,
.size = 3,
.rotates =
{
{
{1, 1, 0},
{0, 1, 1},
{0, 0, 0}
},
{
{0, 0, 1},
{0, 1, 1},
{0, 1, 0}
},
{
{0, 0, 0},
{1, 1, 0},
{0, 1, 1}
},
{
{0, 1, 0},
{1, 1, 0},
{1, 0, 0}
}
}
},
};
void setBlock(Block* block, Color color, ShapeId shape, bool current)
{
block->color = color;
block->shape = shape;
block->current = current;
}
void resetBlock(Block* block)
{
block->color = BLACK;
block->shape = EMPTY;
block->current = false;
}
int main() {
srand(time(NULL));
State state = {
.x = CANVAS_WIDTH / 2,
.y = 0,
.score = 0,
.rotate = 0,
.fallTime = 0
};
Block canvas[CANVAS_HEIGHT][CANVAS_WIDTH];
for (int i = 0; i < CANVAS_HEIGHT; i++) {
for (int j = 0; j < CANVAS_WIDTH; j++) {
resetBlock(&canvas[i][j]);
}
}
Shape shapeData = shapes[1];
for (int i = 0; i < shapeData.size; i++) {
for (int j = 0; j < shapeData.size; j++) {
if (shapeData.rotates[0][i][j]) {
setBlock(&canvas[state.y + i][state.x + j], shapeData.color, J, true);
}
}
}
//將光標移動到第一行第一列
printf("\033[0;0H\n");
for (int i = 0; i < CANVAS_HEIGHT; i++) {
printf("|");
for (int j = 0; j < CANVAS_WIDTH; j++) {
printf("\033[%dm\u3000", canvas[i][j].color);
}
printf("\033[0m");
printf("|\n");
}
//printf("\e[?25l"); // hide cursor
return 0;
}
```