# 烏克蘭方塊 (Ukraine Tetris)
首先一進入遊戲
會出現熱情奔放的歡迎頁面

再來選擇**是否按F進入遊戲**(只有內部測試人員才知道按G可以開啟beta版的測試功能)
下載正常版即享有專業代碼**破解高清畫面** 隨附**方塊代管系統 足跡保存系統 時空粒子加速功能**
## 破解高清畫面

※本商品建議在光線暗的地方使用,效果更佳、更明顯出色
請不要在背光、反光的環境下使用(因光線充足會產生折射,造成光線混亂,使畫面模糊不清,甚至會感到頭昏眼花哦)
## 隨附方塊代管系統

提供客製化台藉管家全天服務,
針對每一種方塊類型的需求,安排適合的管家,並且提供飯店式管家服務水準,讓您每一次操作都像在享受五星級飯店的專人管家服務。
## 足跡保存系統

是個人足跡地圖,可根據定位記錄呈現您消除的行數、路線和行程。您可以在遊戲結束後查看足跡,也可以在遊戲後刪除時間軸中的分數記錄。
※本功能假如開啟了網路和應用程式活動等設定,即使已關閉定位記錄功能或將位置資料從定位記錄中刪除,系統仍「**可能**」會在您使用其他 Google 協作平台、應用程式和服務時,將位置資料儲存至雲端帳戶中。
## 時空粒子加速功能

超時空粒子加速功能為同盟國聯軍通用的支援技能,由超時空傳送儀解鎖。
使用後,能通過特定條件(消除特定行數),觸發重力場變化,改變時間的流速,從而讓一定範圍內的使用使用的四方形、長條狀、閃電型方塊移動速度提高,且從理論而言速度可無止盡上升。
# beta版
可以體驗開發團隊正在測試的**自旋姿態落點精準判定系統** **外搖桿操縱物體質變系統**
## 自旋姿態落點精準判定系統
## 
本系統涉及以等傾角姿態控制的自旋穩定方塊姿態方式,此方法以自旋穩定方塊在參考坐標系下的初始狀態、目標姿態和姿控量為輸入,
對方塊姿態進行預測,計算麥卡托座標圖,並對X軸0度角水平線和Y軸垂直鉛直線進行預測,根據已經計算出的姿態控制參數(姿控量)和給定的控制方式計算出方塊姿態因受控而發生垂直翻轉、水平翻轉之姿態變化。
## 外搖桿操縱物體質變系統

又稱為外搖桿操縱物體質變系統(External Joystick Manipulation System),此技術為我們帶來了前所未有的物體操作體驗。本系統乃基於普遍應用的單面物理觸點技術運作,使我們能夠以鍵盤為媒介,打破物理守則,消除不需要的方塊,遠端一鍵操控引起方塊的質變。
以下為程式碼
```
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <windows.h>
#define DELETE_KEY 0x44
#define DELETE_FUNC() GetAsyncKeyState(DELETE_KEY) & 0x8000
#define LEFT_KEY 0x25 // The key to move left, default = 0x25 (left arrow)
#define RIGHT_KEY 0x27 // The key to move right, default = 0x27 (right arrow)
#define ROTATE_KEY 0x26 // The key to rotate, default = 0x26 (up arrow)
#define DOWN_KEY 0x28 // The key to move down, default = 0x28 (down arrow)
#define FALL_KEY 0x20 // The key to fall, default = 0x20 (spacebar)
#define FALL_DELAY 500 // The delay between each fall, default = 500
#define RENDER_DELAY 100 // The delay between each frame, default = 100
#define LEFT_FUNC() GetAsyncKeyState(LEFT_KEY) & 0x8000
#define RIGHT_FUNC() GetAsyncKeyState(RIGHT_KEY) & 0x8000
#define ROTATE_FUNC() GetAsyncKeyState(ROTATE_KEY) & 0x8000
#define DOWN_FUNC() GetAsyncKeyState(DOWN_KEY) & 0x8000
#define FALL_FUNC() GetAsyncKeyState(FALL_KEY) & 0x8000
#define HOLD_FUNC() GetAsyncKeyState(HOLD_KEY) & 0x8000
#define QUIT_FUNC() GetAsyncKeyState(QUIT_KEY) & 0x8000
#define HOLD_KEY 0x43
#define QUIT_KEY 0x51
#define CANVAS_WIDTH 10
#define CANVAS_HEIGHT 20
int tmp = 0;
int tmpscore = 0;
int flag = 0;
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}
}
}
},
};
Shape Hold = {.size = 0};
bool isHold = false;
int scoremode = 0;
bool programContinue = true;
bool drop_predict(Block canvas[CANVAS_HEIGHT][CANVAS_WIDTH], int X_position, int Y_position, int newRotate, ShapeId shapeId)
{
Shape shapeData = shapes[shapeId];
for (int i = 0; i < shapeData.size; i++)
{
for (int j = 0; j < shapeData.size; j++)
{
if (shapeData.rotates[newRotate][i][j])
{
if (X_position + j < 0 || X_position + j >= CANVAS_WIDTH || Y_position + i < 0 || Y_position + i >= CANVAS_HEIGHT)
{
return false;
}
if (!canvas[Y_position + i][X_position + j].current && canvas[Y_position + i][X_position + j].shape != EMPTY)
{
return false;
}
}
}
}
return true;
}
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;
}
void cleanShape(Block canvas[CANVAS_HEIGHT][CANVAS_WIDTH], int originalX, int originalY, int originalRotate, ShapeId shapeId) {
Shape shapeData = shapes[shapeId];
int size = shapeData.size;
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (shapeData.rotates[originalRotate][i][j]) {
resetBlock(&canvas[originalY + i][originalX + j]);
}
}
}
}
bool move(Block canvas[CANVAS_HEIGHT][CANVAS_WIDTH], int originalX, int originalY, int originalRotate, int newX, int newY, int newRotate, ShapeId shapeId) {
Shape shapeData = shapes[shapeId];
int size = shapeData.size;
// check if the new position is valid to place the block
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (shapeData.rotates[newRotate][i][j]) {
if (newX + j < 0 || newX + j >= CANVAS_WIDTH || newY + i < 0 || newY + i >= CANVAS_HEIGHT) {
return false;
}
if (!canvas[newY + i][newX + j].current && canvas[newY + i][newX + j].shape != EMPTY) {
return false;
}
}
}
}
// remove the old position
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (shapeData.rotates[originalRotate][i][j]) {
resetBlock(&canvas[originalY + i][originalX + j]);
}
}
}
// move the block
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (shapeData.rotates[newRotate][i][j]) {
setBlock(&canvas[newY + i][newX + j], shapeData.color, shapeId, true);
}
}
}
return true;
}
void printCanvas(Block canvas[CANVAS_HEIGHT][CANVAS_WIDTH], State* state, char tmp)
{
int y_position = state->y + 1;
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 ", canvas[i][j].color);
}
printf("\033[0m|\n");
}
Shape shapeData = shapes[state->queue[1]];
printf("\033[%d;%dHNext:", 3, CANVAS_WIDTH * 2 + 5);
for (int i = 1; i <= 3; i++)
{
shapeData = shapes[state->queue[i]];
for (int j = 0; j < 4; j++) {
printf("\033[%d;%dH", i * 4 + j, CANVAS_WIDTH * 2 + 15);
for (int k = 0; k < 4; k++) {
if (j < shapeData.size && k < shapeData.size && shapeData.rotates[0][j][k]) {
printf("\x1b[%dm ", shapeData.color);
}
else {
printf("\x1b[0m ");
}
}
}
}
if(tmp=='g'){
// 計算掉落方塊的最終位置
while (drop_predict(canvas, state->x, y_position, state->rotate, state->queue[0]))
{
y_position++;
}
// 顯示正在掉落的方塊
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (i < shapeData.size && j < shapeData.size && shapeData.rotates[state->rotate][i][j])
{
printf("\033[%d;%dH\033[%dmo\033[0m", y_position + i + 1, 2 * (state->x + j)+2 , 37);
}
}
}
}
printf("\033[%d;%dHHold:", 3, CANVAS_WIDTH * 2 + 25);
if (!isHold) {
for (int j = 0; j < 4; j++) {
printf("\033[%d;%dH", 1 * 4 + j, CANVAS_WIDTH * 2 + 35);
for (int k = 0; k < 4; k++) {
if (j < Hold.size && k < Hold.size && Hold.rotates[0][j][k]) {
printf("\x1b[%dm ", Hold.color);
}
else {
printf("\x1b[0m ");
}
}
}
}
printf("\033[%d;%dHScore: %d", 20, CANVAS_WIDTH * 2 + 5, (state->score));
return;
}
int clearLine(Block canvas[CANVAS_HEIGHT][CANVAS_WIDTH]) {
for (int i = 0; i < CANVAS_HEIGHT; i++) {
for (int j = 0; j < CANVAS_WIDTH; j++) {
if (canvas[i][j].current) {
canvas[i][j].current = false;
}
}
}
int linesCleared = 0;
for (int i = CANVAS_HEIGHT - 1; i >= 0; i--)
{
bool isFull = true;
for (int j = 0; j < CANVAS_WIDTH; j++)
{
if (canvas[i][j].shape == EMPTY) {
isFull = false;
break;
}
}
if (isFull) {
linesCleared += 1;
for (int j = i; j > 0; j--)
{
for (int k = 0; k < CANVAS_WIDTH; k++)
{
setBlock(&canvas[j][k], canvas[j - 1][k].color, canvas[j - 1][k].shape, false);
resetBlock(&canvas[j - 1][k]);
}
}
i++;
}
}
return linesCleared;
}
void logic(Block canvas[CANVAS_HEIGHT][CANVAS_WIDTH], State* state, char tmp)
{
if (ROTATE_FUNC()) {
int newRotate = (state->rotate + 1) % 4;
if (move(canvas, state->x, state->y, state->rotate, state->x, state->y, newRotate, state->queue[0]))
{
state->rotate = newRotate;
}
}
else if (LEFT_FUNC()) {
if (move(canvas, state->x, state->y, state->rotate, state->x - 1, state->y, state->rotate, state->queue[0]))
{
state->x -= 1;
}
}
else if (RIGHT_FUNC()) {
if (move(canvas, state->x, state->y, state->rotate, state->x + 1, state->y, state->rotate, state->queue[0]))
{
state->x += 1;
}
}
else if (DOWN_FUNC()) {
state->fallTime = FALL_DELAY;
}
else if (FALL_FUNC()) {
state->fallTime += FALL_DELAY * CANVAS_HEIGHT;
}
else if (HOLD_FUNC() && !isHold) {
isHold = false;
cleanShape(canvas, state->x, state->y, state->rotate, state->queue[0]);//clean original shape
if (Hold.size == 0) {
Hold = shapes[state->queue[0]];
state->queue[0] = state->queue[1];
state->queue[1] = state->queue[2];
state->queue[2] = state->queue[3];
state->queue[3] = rand() % 7;
}//hold have nothing
else {
ShapeId temp = state->queue[0];
state->queue[0] = Hold.shape;
Hold = shapes[temp];
}//when hold exist
state->rotate = 0;
}
else if (DELETE_FUNC()) {
// Check if the current block can be deleted
bool canDelete = true;
Shape shapeData = shapes[state->queue[0]];
int size = shapeData.size;
if(tmp=='g'){
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (shapeData.rotates[state->rotate][i][j]) {
int deleteX = state->x + j;
int deleteY = state->y + i;
if (deleteY >= 0 && deleteY < CANVAS_HEIGHT && deleteX >= 0 && deleteX < CANVAS_WIDTH) {
if (!canvas[deleteY][deleteX].current) {
canDelete = false;
break;
}
}
}
}
if (!canDelete) {
break;
}
}
// Delete the current block
if (canDelete) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
if (shapeData.rotates[state->rotate][i][j]) {
int deleteX = state->x + j;
int deleteY = state->y + i;
if (deleteY >= 0 && deleteY < CANVAS_HEIGHT && deleteX >= 0 && deleteX < CANVAS_WIDTH) {
resetBlock(&canvas[deleteY][deleteX]);
}
}
}
}
}
}
}
state->fallTime += RENDER_DELAY;
if (state->score > tmpscore) {
flag = 0;
}
else {
flag = 1;
}
if ((state->score) % 2 == 0 && state->score != 0 && flag == 0) {
tmp += 15;
flag = 1;
}
state->fallTime += tmp;
while (state->fallTime >= FALL_DELAY) {
state->fallTime -= FALL_DELAY;
if (move(canvas, state->x, state->y, state->rotate, state->x, state->y + 1, state->rotate, state->queue[0])) {
state->y++;
tmpscore = state->score;
}
else {
tmpscore = state->score;
state->score += 5*clearLine(canvas);
state->x = CANVAS_WIDTH / 2;
state->y = 0;
state->rotate = 0;
state->fallTime = 0;
state->queue[0] = state->queue[1];
state->queue[1] = state->queue[2];
state->queue[2] = state->queue[3];
state->queue[3] = rand() % 7;
if (!move(canvas, state->x, state->y, state->rotate, state->x, state->y, state->rotate, state->queue[0]))
{
system("cls");
printf("\033[%d;%dH\x1b[41m GAME OVER \x1b[0m\033[%d;%dH\n", CANVAS_HEIGHT - 15, CANVAS_WIDTH * 2-10, CANVAS_HEIGHT + 10, -10);
printf(" Your scores is : %d !!!!\n\n\n\n",state->score);
exit(0);
}
}
}
return;
}
void playIntroAnimation() {
// 開頭動畫程式碼
printf("<<<<<<<<<<<<<<<<<<<__>>>>>>>>>>>>>>>>>>>>>\n");
printf("========~~~~~~Ukraine TETRIS!~~~~~~=======\n");
printf("<<<<<<<<<<<<<<<<<<<-->>>>>>>>>>>>>>>>>>>>>\n");
Sleep(2000);
}
int main()
{
char tmp;
srand(time(NULL));
playIntroAnimation();
State state = {
.x = CANVAS_WIDTH / 2,
.y = 0,
.score = 0,
.rotate = 0,
.fallTime = 0
};
for (int i = 0; i < 4; i++)
{
state.queue[i] = rand() % 7;
}
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]);
}
}
system("cls");
printf("\nPress\nF\nto\nenter\nthe\ntetris: ");
scanf("%c", &tmp);
if (tmp != 'f' && tmp!= 'g') return 0;
// printf("\e[?25l"); // hide cursor
move(canvas, state.x, state.y, state.rotate, state.x, state.y, state.rotate, state.queue[0]);
while (1)
{
logic(canvas, &state, tmp);
printCanvas(canvas, &state, tmp);
Sleep(100);
}
}//pray for ukraine
```