java大作业 俄罗斯方块_大作业之俄罗斯方块样例

#include

#include

#include

#define CELL 20

#define ROWS 25

#define COLS 15

//升级所需分数值

#define SCORE_LEVEL_INC 80

#define ID_TIMER 1

/全局变量/

HWND hwnd; //保存窗口句柄

int score = 0; //分数

int level = 0; //级数

int interval_unit = 25; //随级数递增的时间间隔增量

int interval_base = 300; //时间间隔基量

int old_interval; //保存当前的时间间隔,用于加速操作

int cur_left, cur_top; //记录方块当前的位置

int width_block, height_block; //方块的宽带和高度

bool isPause = false; //暂停标识

UINT timer_id = 0; //保存计时器ID

static byte* block = NULL; //方块,方块为随机大小,采用动态分配内存方式,所以这里是指针变量

byte g_panel[ROWS][COLS] = { 0 };

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

void DrawPanel(HDC hdc); //绘制表格

void RefreshPanel(HDC hdc); //刷新面板

void DoDownShift(HDC hdc); //下移

void DoLeftShift(HDC hdc); //左移

void DoRightShift(HDC hdc); //右移

void DoAccelerate(HDC hdc); //加速

void DoRedirection(HDC hdc); //改变方向

void ClearRow(HDC hdc); //消行

bool ExportBlock(); //输出方块,

//该函数会直接修改全局变量block,width_block,height_block,

//cur_left和cur_top

bool IsTouchBottom(HDC hdc); //判断是否到达底部

int main()

{

HINSTANCE hInstance = GetModuleHandle(NULL);

TCHAR szAppName[] = TEXT("teris");

MSG msg;

WNDCLASS wc;

wc.style = CS_HREDRAW | CS_VREDRAW;

wc.lpfnWndProc = WndProc;

wc.cbClsExtra = 0;

wc.cbWndExtra = 0;

wc.hInstance = hInstance;

wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);

wc.hCursor = LoadCursor(NULL, IDC_ARROW);

wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);

wc.lpszMenuName = NULL;

wc.lpszClassName = szAppName;

if (!RegisterClass(&wc))

{

printf("RegisterClass occur errors!");

return 0;

}

hwnd = CreateWindow(szAppName, TEXT("Teris Demo"),

WS_OVERLAPPEDWINDOW,

0, 0, 0, 0,

NULL,

NULL,

hInstance,

NULL);

ShowWindow(hwnd, SW_SHOW);

UpdateWindow(hwnd);

while (GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return msg.wParam;

}

void DrawPanel(HDC hdc) //绘制游戏面板

{

int x, y;

RECT rect;

for (y = 0; y < ROWS; y++)

{

for (x = 0; x < COLS; x++)

{

//计算方块的边框范围

rect.top = y * CELL + 1;

rect.bottom = (y + 1) * CELL - 1;

rect.left = x * CELL + 1;

rect.right = (x + 1) * CELL - 1;

FrameRect(hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));

}

}

}

void DoDownShift(HDC hdc) //下移

{

if (NULL == block) return;

//判断是否到达底部

if (IsTouchBottom(hdc)) //到底部

{

//消行处理

ClearRow(hdc);

ExportBlock(); //输出下一个方块

}

cur_top++;

RefreshPanel(hdc);

}

void DoLeftShift(HDC hdc) //左移

{

int x, y;

if (NULL == block) return;

if (0 == cur_left) return;

if (cur_top < 0) return; //方块没有完整显示前,不能左移

for (y = 0; y < height_block; y++)

{

for (x = 0; x < width_block; x++) //从左边开始扫描,获取该行最左边的实心方格块

{

if (*(block + y * width_block + x))

{

//判断当前方格在面板上面左边一个方格是否为实心,是就代表不能再左移

if (g_panel[cur_top + y][cur_left + x - 1]) return;

break; //只判断最左边的一个实心方格,之后直接扫描下一行

}

}

}

cur_left--;

RefreshPanel(hdc);

}

void DoRightShift(HDC hdc) //右移

{

int x, y;

if (NULL == block) return;

if (COLS - width_block == cur_left) return;

if (cur_top < 0) return; //方块完整显示前不能右移

for (y = 0; y < height_block; y++)

{

for (x = width_block - 1; x >= 0; x--) //从右边开始扫描,获取该行最右边的实心方格块

{

if (*(block + y * width_block + x))

{

//判断当前方格在面板上右边一个方格是否为实心,是就代表不能再右移

if (g_panel[cur_top + y][cur_left + x + 1]) return;

break; //只判断最右边的一个实心方格

}

}

}

cur_left++;

RefreshPanel(hdc);

}

void DoRedirection(HDC hdc) //改变方向

{

int i, j;

byte* temp = NULL;

if (NULL == block) return;

if (cur_top < 0) return; //方块完整显示前不能转向

temp = (byte*)malloc(sizeof(byte) * width_block * height_block);

for (i = 0; i < width_block; i++)

{

for (j = 0; j < height_block; j++)

{

//temp[i][j]=block[height_block-j-1][i];

*(temp + i * height_block + j) = *(block + (height_block - j - 1) * width_block + i);

}

}

//给方块重新定位

int incHeight = width_block - height_block;

int incWidth = height_block - width_block;

int temp_cur_top = cur_top - incHeight / 2;

int temp_cur_left = cur_left - incWidth / 2;

//system("cls");

//printf("temp_top=%d, temp_left=%d",temp_cur_top,temp_cur_left);

//判断当前空间是否足够让方块改变方向

int max_len = max(width_block, height_block);

//防止下标访问越界

if (temp_cur_top + max_len - 1 >= ROWS || temp_cur_left < 0 || temp_cur_left + max_len - 1 >= COLS)

{

free(temp); //退出前必须先释放内存

return;

}

for (i = 0; i < max_len; i++)

{

for (j = 0; j < max_len; j++)

{

//转向所需的空间内有已被占用的实心方格存在,即转向失败

if (g_panel[temp_cur_top + i][temp_cur_left + j])

{

free(temp); //退出前必须先释放内存

return;

}

}

}

//把临时变量的值赋给block,只能赋值,而不能赋指针值

for (i = 0; i < height_block; i++)

{

for (j = 0; j < width_block; j++)

{

//block[i][j]=temp[i][j];

*(block + i * width_block + j) = *(temp + i * width_block + j);

}

}

//全局变量重新被赋值

cur_top = temp_cur_top;

cur_left = temp_cur_left;

//交换

i = width_block;

width_block = height_block;

height_block = i;

free(temp); //释放为临时变量分配的内存

RefreshPanel(hdc);

}

void DoAccelerate(HDC hdc) //加速

{

if (NULL == block) return;

if (IsTouchBottom(hdc))

{

//消行处理

ClearRow(hdc);

ExportBlock();

}

cur_top++;

RefreshPanel(hdc);

}

bool IsTouchBottom(HDC hdc)

{

int x, y;

int i, j;

if (NULL == block) return false;

if (ROWS == cur_top + height_block)

{

//固定方块

for (i = 0; i < height_block; i++)

{

for (j = 0; j < width_block; j++)

{

if (*(block + i * width_block + j)) g_panel[cur_top + i][cur_left + j] = 1;

}

}

return true;

}

for (y = height_block - 1; y >= 0; y--) //从底行开始扫描

{

//判断第一个实心方块在面板上邻接的下方方格是否为实心,是就代表已经到达底部

for (x = 0; x < width_block; x++)

{

if (*(block + y * width_block + x))

{

if (cur_top + y + 1 < 0) return false;

if (g_panel[cur_top + y + 1][cur_left + x])

{

//判断是否gameover

if (cur_top <= 0)

{

if (timer_id)

{

KillTimer(hwnd, ID_TIMER);

timer_id = 0;

}

MessageBox(hwnd, TEXT("游戏结束"), TEXT("MSG"), MB_OK | MB_ICONEXCLAMATION);

SendMessage(hwnd, WM_CLOSE, 0, 0);

}

//

//固定方块

for (i = 0; i < height_block; i++)

{

for (j = 0; j < width_block; j++)

{

if (*(block + i * width_block + j)) g_panel[cur_top + i][cur_left + j] = 1;

}

}

return true;

}

}

}

}

return false;

}

void ClearRow(HDC hdc) //消行

{

int i, j, k;

int count = 0; //消行次数

bool isFilled;

//消行处理

for (i = ROWS - 1; i >= 0; i--)

{

isFilled = true;

for (j = 0; j < COLS; j++)

{

if (!g_panel[i][j])

{

isFilled = false;

break;

}

}

if (isFilled)

{

for (j = 0; j < COLS; j++)

{

g_panel[i][j] = 0;

}

//所有方块往下移

for (k = i - 1; k >= 0; k--)

{

for (j = 0; j < COLS; j++)

{

g_panel[k + 1][j] = g_panel[k][j];

}

}

i = i + 1;

count++;

}

}

//最高级别为9级,所以分数极限为(9+1)*SCORE_LEVEL_INC-1

if (score >= 10 * SCORE_LEVEL_INC - 1) return;

//加分规则:消除行数,1行加10分,2行加15分,3行加20分,4行加30分

switch (count)

{

case 1:

score += 10;

break;

case 2:

score += 15;

break;

case 3:

score += 20;

break;

case 4:

score += 30;

break;

}

int temp_level = score / SCORE_LEVEL_INC;

if (temp_level > level)

{

level = temp_level;

//撤销当前计时器,然后重设

if (timer_id) KillTimer(hwnd, ID_TIMER);

timer_id = SetTimer(hwnd, ID_TIMER, interval_base - level * interval_unit, NULL);

}

system("cls");

printf("score: %d, level: %d ", score, level);

}

void RefreshPanel(HDC hdc) //刷新面板

{

int x, y;

RECT rect;

HBRUSH h_bSolid = (HBRUSH)GetStockObject(GRAY_BRUSH),

h_bEmpty = (HBRUSH)GetStockObject(WHITE_BRUSH);

if (NULL == block) return;

//先刷屏

for (y = 0; y < ROWS; y++)

{

for (x = 0; x < COLS; x++)

{

//为避免刷掉方块的边框,rect范围必须比边框范围小1

rect.top = y * CELL + 2;

rect.bottom = (y + 1) * CELL - 2;

rect.left = x * CELL + 2;

rect.right = (x + 1) * CELL - 2;

if (g_panel[y][x])

FillRect(hdc, &rect, h_bSolid);

else

FillRect(hdc, &rect, h_bEmpty);

}

}

//再定位方块

for (y = 0; y < height_block; y++)

{

for (x = 0; x < width_block; x++)

{

if (*(block + y * width_block + x)) //实心

{

rect.top = (y + cur_top) * CELL + 2;

rect.bottom = (y + cur_top + 1) * CELL - 2;

rect.left = (x + cur_left) * CELL + 2;

rect.right = (x + cur_left + 1) * CELL - 2;

FillRect(hdc, &rect, h_bSolid);

}

}

}

}

bool ExportBlock() //输出方块

{

int sel;

if (block)

{

free(block); //释放之前分配的内存

block = NULL;

}

sel = rand() % 7;

switch (sel)

{

case 0: //水平条

width_block = 4;

height_block = 1;

block = (byte*)malloc(sizeof(byte) * width_block * height_block);

*(block + 0) = 1; //可以理解为*(block+0*width_block+0)=1,即第一行的第一个方格,下面同理

*(block + 1) = 1; //*(block+0*width_block+1)=1

*(block + 2) = 1; //*(block+0*width_block+2)=1

*(block + 3) = 1; //*(block+0*width_block+3)=1

cur_top = 0 - height_block;

cur_left = (COLS - width_block) / 2;

break;

case 1: //三角

width_block = 3;

height_block = 2;

block = (byte*)malloc(sizeof(byte) * width_block * height_block);

*(block + 0) = 0; //可以理解为*(block+0*width_block+0)=0,即第一行的第一个方格,下面同理

*(block + 1) = 1; //*(block+0*width_block+1)=1

*(block + 2) = 0; //*(block+0*width_block+2)=0

*(block + 3) = 1; //*(block+1*width_block+0)=1,第二行开始

*(block + 4) = 1; //*(block+1*width_block+1)=1

*(block + 5) = 1; //*(block+1*width_block+2)=1

cur_top = 0 - height_block;

cur_left = (COLS - width_block) / 2;

break;

case 2: //左横折

width_block = 3;

height_block = 2;

block = (byte*)malloc(sizeof(byte) * width_block * height_block);

*(block + 0) = 1; //可以理解为*(block+0*width_block+0)=1,下面同理

*(block + 1) = 0; //*(block+0*width_block+1)=0

*(block + 2) = 0; //*(block+0*width_block+2)=0

*(block + 3) = 1; //*(block+1*width_block+0)=1

*(block + 4) = 1; //*(block+1*width_block+1)=1

*(block + 5) = 1; //*(block+1*width_block+2)=1

cur_top = 0 - height_block;

cur_left = (COLS - width_block) / 2;

break;

case 3: //右横折

width_block = 3;

height_block = 2;

block = (byte*)malloc(sizeof(byte) * width_block * height_block);

*(block + 0) = 0; //可以理解为*(block+0*width_block+0)=0,下面同理

*(block + 1) = 0; //*(block+0*width_block+1)=0

*(block + 2) = 1; //*(block+0*width_block+2)=1

*(block + 3) = 1; //*(block+1*width_block+0)=1

*(block + 4) = 1; //*(block+1*width_block+1)=1

*(block + 5) = 1; //*(block+1*width_block+2)=1

cur_top = 0 - height_block;

cur_left = (COLS - width_block) / 2;

break;

case 4: //左闪电

width_block = 3;

height_block = 2;

block = (byte*)malloc(sizeof(byte) * width_block * height_block);

*(block + 0) = 1; //可以理解为*(block+0*width_block+0)=1,下面同理

*(block + 1) = 1; //*(block+0*width_block+1)=1

*(block + 2) = 0; //*(block+0*width_block+2)=0

*(block + 3) = 0; //*(block+1*width_block+0)=0

*(block + 4) = 1; //*(block+1*width_block+1)=1

*(block + 5) = 1; //*(block+1*width_block+2)=1

cur_top = 0 - height_block;

cur_left = (COLS - width_block) / 2;

break;

case 5: //右闪电

width_block = 3;

height_block = 2;

block = (byte*)malloc(sizeof(byte) * width_block * height_block);

*(block + 0) = 0; //可以理解为*(block+0*width_block+0)=0,下面同理

*(block + 1) = 1; //*(block+0*width_block+1)=1

*(block + 2) = 1; //*(block+0*width_block+2)=1

*(block + 3) = 1; //*(block+1*width_block+0)=1

*(block + 4) = 1; //*(block+1*width_block+1)=1

*(block + 5) = 0; //*(block+1*width_block+2)=0

cur_top = 0 - height_block;

cur_left = (COLS - width_block) / 2;

break;

case 6: //石头

width_block = 2;

height_block = 2;

block = (byte*)malloc(sizeof(byte) * width_block * height_block);

*(block + 0) = 1; //可以理解为*(block+0*width_block+0)=1,下面同理

*(block + 1) = 1; //*(block+0*width_block+1)=1

*(block + 2) = 1; //*(block+1*width_block+0)=1

*(block + 3) = 1; //*(block+1*width_block+1)=1

cur_top = 0 - height_block;

cur_left = (COLS - width_block) / 2;

break;

}

return block != NULL;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)

{

HDC hdc;

PAINTSTRUCT ps;

//TCHAR szBuffer[1024];

switch (message)

{

case WM_CREATE:

MoveWindow(hwnd, 400, 10, CELL * COLS + 8, CELL * ROWS + 32, FALSE); //补齐宽度和高度

srand(time(NULL));

ExportBlock();

timer_id = SetTimer(hwnd, ID_TIMER, interval_base - level * interval_unit, NULL);

return 0;

case WM_TIMER:

hdc = GetDC(hwnd);

DoDownShift(hdc);

ReleaseDC(hwnd, hdc);

return 0;

case WM_KEYDOWN:

hdc = GetDC(hwnd);

switch (wParam)

{

case VK_LEFT: //左移

if (!isPause) DoLeftShift(hdc);

break;

case VK_RIGHT: //右移

if (!isPause) DoRightShift(hdc);

break;

case VK_UP: //转向

if (!isPause) DoRedirection(hdc);

break;

case VK_DOWN: //加速

if (!isPause) DoAccelerate(hdc);

break;

case VK_SPACE: //暂停

isPause = !isPause;

if (isPause)

{

if (timer_id) KillTimer(hwnd, ID_TIMER);

timer_id = 0;

}

else

{

timer_id = SetTimer(hwnd, ID_TIMER, interval_base - level * interval_unit, FALSE);

}

break;

}

ReleaseDC(hwnd, hdc);

return 0;

case WM_PAINT:

hdc = BeginPaint(hwnd, &ps);

DrawPanel(hdc); //绘制面板

RefreshPanel(hdc); //刷新

EndPaint(hwnd, &ps);

return 0;

case WM_DESTROY:

if (block) free(block);

if (timer_id) KillTimer(hwnd, ID_TIMER);

PostQuitMessage(0);

return 0;

}

return DefWindowProc(hwnd, message, wParam, lParam);

}

低配版(代码行数较少)

注意:C语言实现(放.c文件里)

#include

#include

#include

#include

#define WIDTH 10//x j

#define HIGTH 25//y i

//[y][x] [HIGTH][WIDTH] [i][j] [20][10]

#define TICK 1000

#define COOLDOWN 200

typedef enum ELEMENT

{

AIR, BLOCK, MOVING

}ELEMENT;

typedef enum FUNCTION_RESULT

{

FUNCTION_SUSSESS, FUNCTION_FAIL

}FUNCTION_RESULT;

typedef enum SHAPE_TYPE

{

O_SHAPE, J_SHAPE, L_SHAPE, T_SHAPE, I_SHAPE, S_SHAPE, Z_SHAPE

}SHAPE_TYPE;

char map[HIGTH][WIDTH];//显示区域为0,5到10,25 0为空 1为已下落的方块 2为正在移动的方块

COORD faller[4];

COORD next_faller[4];

ULONGLONG last;

ULONGLONG now;

int key;

SHAPE_TYPE now_shape;

int keyboard_flag;

HANDLE hdl;

//形状的初始位置,分别表示xy坐标,顺序是ojltisz

short o_shape[8] = { 4,3,5,3,4,4,5,4 };

short j_shape[8] = { 4,4,5,4,6,4,4,3 };

short l_shape[8] = { 5,4,4,4,3,4,5,3 };

short t_shape[8] = { 5,4,4,4,6,4,5,3 };

short i_shape[8] = { 4,4,5,4,3,4,6,4 };

short s_shape[8] = { 4,3,5,3,4,2,5,4 };

short z_shape[8] = { 4,3,5,3,5,2,4,4 };

short shape[7][8] =

{

{ 4,3,5,3,4,4,5,4 },

{ 4,4,5,4,6,4,4,3 },

{ 5,4,4,4,3,4,5,3 },

{ 5,4,4,4,6,4,5,3 },

{ 4,4,5,4,3,4,6,4 },

{ 4,3,5,3,4,2,5,4 },

{ 4,3,5,3,5,2,4,4 },

};

int is_legal(COORD test[4])//1为合法 0为不合法

{

for (int i = 0; i < 4; i++)

{

if (test[i].X < 0 || test[i].X >= WIDTH)return 0;

if (test[i].Y >= HIGTH)return 0;

}

for (int i = 0; i < 4; i++)

{

if (map[test[i].Y][test[i].X] == BLOCK)return 0;

}

return 1;

}

void update_screen()

{

//system("CLS");

COORD pos_start = { 0,0 };

SetConsoleCursorPosition(hdl, pos_start);

for (int i = 5; i < HIGTH; i++)

{

printf("

for (int j = 0; j < WIDTH; j++)

{

if (map[i][j] == AIR) printf(". ");

else printf("■");

}

printf("|>\n");

}

printf("");

}

void generate()

{

now_shape = rand() % 7;

memcpy(&faller, shape[now_shape], 4 * sizeof(COORD));

for (int i = 0; i < 4; i++) map[faller[i].Y][faller[i].X] = MOVING;

}

FUNCTION_RESULT try_move_down()

{

memcpy(next_faller, faller, sizeof(faller));

for (int i = 0; i < 4; i++)

{

next_faller[i].Y++;

if (next_faller[i].Y >= HIGTH)return FUNCTION_FAIL;

if (map[next_faller[i].Y][next_faller[i].X] == BLOCK)return FUNCTION_FAIL;

}

for (int i = 0; i < 4; i++) map[faller[i].Y][faller[i].X] = AIR;

memcpy(faller, next_faller, sizeof(faller));

for (int i = 0; i < 4; i++) map[faller[i].Y][faller[i].X] = MOVING;

return FUNCTION_SUSSESS;

}

void clear_row()

{

COORD temp_map[HIGTH][WIDTH];

int flag;

for (int i = HIGTH - 1; i >= 5; i--)

{

flag = 1;

for (int j = 0; j < WIDTH; j++)

{

if (map[i][j] != BLOCK)

{

flag = 0;

break;

}

}

if (flag)

{

memcpy(temp_map, map, i * sizeof(map[0]));

memcpy(map + 1, temp_map, i * sizeof(map[0]));

continue;

}

}

}

//向右输入1,向左输入-1

FUNCTION_RESULT try_move_horizontal(int direction)

{

memcpy(next_faller, faller, sizeof(faller));

for (int i = 0; i < 4; i++)

{

next_faller[i].X += direction;

if (next_faller[i].X >= WIDTH || next_faller[i].X < 0) return FUNCTION_FAIL;

if (map[next_faller[i].Y][next_faller[i].X] == BLOCK)return FUNCTION_FAIL;

}

keyboard_flag = 1;

for (int i = 0; i < 4; i++) map[faller[i].Y][faller[i].X] = AIR;

memcpy(faller, next_faller, sizeof(faller));

for (int i = 0; i < 4; i++) map[faller[i].Y][faller[i].X] = MOVING;

return FUNCTION_SUSSESS;

}

FUNCTION_RESULT try_fall()

{

FUNCTION_RESULT result = FUNCTION_FAIL;

while (try_move_down() == FUNCTION_SUSSESS)result = FUNCTION_SUSSESS;

return result;

}

//以中心点旋转

//以所有点旋转后向下

//以其他点旋转

FUNCTION_RESULT t_spin(int direction)

{

for (int j = 0; j < 4; j++)

{

next_faller[j].X = faller[0].X + direction * (faller[0].Y - faller[j].Y);

next_faller[j].Y = faller[0].Y + direction * (faller[j].X - faller[0].X);

}

if (is_legal(next_faller))

{

for (int i = 0; i < 4; i++) map[faller[i].Y][faller[i].X] = AIR;

memcpy(faller, next_faller, sizeof(faller));

for (int i = 0; i < 4; i++) map[faller[i].Y][faller[i].X] = MOVING;

return FUNCTION_SUSSESS;

}

for (int round = 1; round >= 0; round--)

{

for (int i = 0; i < 4; i++)

{

for (int j = 0; j < 4; j++)

{

next_faller[j].X = faller[i].X + direction * (faller[i].Y - faller[j].Y);

next_faller[j].Y = faller[i].Y + direction * (faller[j].X - faller[i].X) + round;

}

if (is_legal(next_faller))

{

for (int i = 0; i < 4; i++) map[faller[i].Y][faller[i].X] = AIR;

memcpy(faller, next_faller, sizeof(faller));

for (int i = 0; i < 4; i++) map[faller[i].Y][faller[i].X] = MOVING;

return FUNCTION_SUSSESS;

}

}

}

return FUNCTION_FAIL;

}

//以中心点旋转

//以其他点旋转

//检查以中心点旋转后能否向下移动一格

//检查以其他点旋转后能否向下移动一格

FUNCTION_RESULT try_rotate(int direction)

{

if (now_shape == O_SHAPE)return FUNCTION_FAIL;

if (now_shape == T_SHAPE)return t_spin(direction);

for (int round = 0; round <= 1; round++)

{

for (int i = 0; i < 4; i++)

{

for (int j = 0; j < 4; j++)

{

next_faller[j].X = faller[i].X + direction * (faller[i].Y - faller[j].Y);

next_faller[j].Y = faller[i].Y + direction * (faller[j].X - faller[i].X) + round;

}

if (is_legal(next_faller))

{

for (int i = 0; i < 4; i++) map[faller[i].Y][faller[i].X] = AIR;

memcpy(faller, next_faller, sizeof(faller));

for (int i = 0; i < 4; i++) map[faller[i].Y][faller[i].X] = MOVING;

return FUNCTION_SUSSESS;

}

}

}

return FUNCTION_FAIL;

}

int main()

{

//清除光标

hdl = GetStdHandle(STD_OUTPUT_HANDLE);

CONSOLE_CURSOR_INFO cci = { 1,0 };

SetConsoleCursorInfo(hdl, &cci);

SetConsoleTitle("TETRIS!!!");

//随机数种子

srand((unsigned)time(NULL));

//地图初始化

memset(map, 0, WIDTH * HIGTH * sizeof(char));

//计时开始

last = GetTickCount64();

keyboard_flag = 0;

//生成第一个方块

generate();

update_screen();

while (1)//主循环

{

now = GetTickCount64();

//说明该向下移动了

if (keyboard_flag)

{

keyboard_flag = 0;

last = GetTickCount64() + COOLDOWN;

update_screen();

}

if (now > last)

{

last += TICK;

if (try_move_down() == FUNCTION_FAIL)//向下移动失败,创建一个新的形状

{

for (int i = 0; i < 4; i++) map[faller[i].Y][faller[i].X] = BLOCK;

clear_row();

generate();

}

update_screen();

}

while (_kbhit())

{

key = _getch();

switch (key)

{

case 'E':case 'e':

if (try_rotate(1) == FUNCTION_SUSSESS)keyboard_flag = 1;

break;

case 'Q':case 'q':

if (try_rotate(-1) == FUNCTION_SUSSESS)keyboard_flag = 1;

break;

case 'S':case 's':

if (try_move_down() == FUNCTION_SUSSESS)keyboard_flag = 1;

break;

case 'W':case 'w':

if (try_fall() == FUNCTION_SUSSESS)keyboard_flag = 1;

break;

case 'D':case 'd':

if (try_move_horizontal(1) == FUNCTION_SUSSESS)keyboard_flag = 1;

break;

case 'A':case 'a':

if (try_move_horizontal(-1) == FUNCTION_SUSSESS)keyboard_flag = 1;

break;

}

}

}

return 0;

}

#include

#include

#include

#include

#include

#define A1 0//A代表长条型,B为方块,C为L型,D为闪电型

#define A2 1

#define B 2

#define C11 3

#define C12 4

#define C13 5

#define C14 6

#define C21 7

#define C22 8

#define C23 9

#define C24 10

#define D11 11

#define D12 12

#define D21 13

#define D22 14

using namespace std;

class Box

{

private:

int map[23][12];//画面坐标,记录有方块的点,也是游戏界面

int hotpoint[2];//当前活动的点,所有图形都是以此为基准绘制的

int top;//当前最高位置

int point;//分数

int level;//等级

int ID;//当前活动图形的ID号

int colorID;//图形的颜色ID。

public:

Box()//初始化

{

int i,j;

for(i=0;i<23;i++)

for(j=0;j<12;j++)

map[i][j]=0;

hotpoint[0]=0;

hotpoint[1]=5;

point=0;

level=1;

top=99;

ID=0;

}

void SetColor(int color);//颜色

void DrawMap();//画游戏的大界面

bool Judge(int x,int y);//判断当前位置能否绘制图形

void Welcome();//欢迎界面

void DrawBox(int x,int y,int num);//绘制图形

void Redraw(int x,int y,int num);//擦除图形

void Run();//运行

void Turn();//转动方块

void UpdataMap();//更新画面

void Pause();//暂停

};

void SetPos(int i,int j)//设定光标位置

{

COORD pos={i,j};

SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);

}

const int sharp[15][8]=

{

{0,0,1,0,2,0,3,0},{0,0,0,1,0,2,0,3},

{0,0,1,0,0,1,1,1},

{0,0,1,0,1,1,1,2},{0,1,1,1,2,0,2,1},{0,0,0,1,0,2,1,2},{0,0,0,1,1,0,2,0},

{1,0,1,1,1,2,0,2},{0,0,0,1,1,1,2,1},{0,0,0,1,0,2,1,0},{0,0,1,0,2,0,2,1},

{0,0,0,1,1,1,1,2},{0,1,1,0,1,1,2,0},

{0,1,0,2,1,0,1,1},{0,0,1,0,1,1,2,1}

};//形状点的各个坐标,先纵后横

const int high[15]={4,1,2,2,3,2,3,2,3,2,3,2,3,2,3};//这个数组是用来保存各个形状高度的,以上面的坐标相对应

void Box::SetColor(int colorID)

{

int n_color;

switch(colorID)

{

case 0: n_color = 0x08;break;

case 1: n_color = 0x0C;break;

case 2: n_color = 0x0D;break;

case 3: n_color = 0x0E;break;

case 4: n_color = 0x0A;break;

}

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), n_color);

}

void Box::DrawMap()//画界面

{

int i;

SetColor(0);//界面颜色

for(i=0;i<14;i++)

{

SetPos(i*2,0);

cout<

}

for(i=1;i<=24;i++)

{

SetPos(0,i);

cout<

SetPos(13*2,i);

cout<

}

for(i=0;i<14;i++)

{

SetPos(i*2,24);

cout<

}

i=15;

for(i=15;i<=25;i++)

{

SetPos(i*2,0);

cout<

}

for(i=1;i<=8;i++)

{

SetPos(15*2,i);

cout<

SetPos(25*2,i);

cout<

}

for(i=15;i<=25;i++)

{

SetPos(i*2,9);

cout<

}

SetPos(16*2,16);

cout<

SetPos(16*2,17);

cout<

SetPos(16*2,18);

cout<

}

void Box::DrawBox(int x,int y,int num)//绘制图形

{

int i;

int nx,ny;

if (num<2)SetColor(1);//0、1是长条

else if(num<3) SetColor(2);//2 方块

else if(num<11) SetColor(3);//3、4、5、6、7、8、9、10

else SetColor(4);

for(i=0;i<4;i++)

{

nx=x+sharp[num][i*2];

ny=y+sharp[num][i*2+1];

SetPos((ny+1)*2,nx+1);//利用sharp数组相对于点x,y绘制形状

//SetColor(i+1);

cout<

}

}

void Box::Redraw(int x,int y,int num)//擦除图形,原理同上

{

int i;

int nx,ny;

for(i=0;i<4;i++)

{

nx=x+sharp[num][i*2];

ny=y+sharp[num][i*2+1];

SetPos((ny+1)*2,nx+1);

cout<

}

}

void Box::Turn()//转动图形,单纯的该ID而已

{

switch(ID)

{

case A1: ID=A2; break;

case A2: ID=A1; break;

case B: ID=B; break;

case C11: ID=C12; break;

case C12: ID=C13; break;

case C13: ID=C14; break;

case C14: ID=C11; break;

case C21: ID=C22; break;

case C22: ID=C23; break;

case C23: ID=C24; break;

case C24: ID=C21; break;

case D11: ID=D12; break;

case D12: ID=D11; break;

case D21: ID=D22; break;

case D22: ID=D21; break;

}

}

void Box::Welcome()//欢迎界面

{

char x;

while(1)

{

system("cls");

cout<

cout<

cout<

cout<

cout<

cout<

cout<

cout<

cout<

cout<

cout<

cout<

SetPos(16,9);

x=getch();

if(x<='9'&&x>='1')//设置等级

{

level=x-'0';

break;

}

}

}

void Box::UpdataMap()//更新画面(关键)

{

int clear;

int i,j,k;

int nx,ny;

int flag;

for(i=0;i<4;i++)//更新map数组的信息

{

nx=hotpoint[0]+sharp[ID][i*2];

ny=hotpoint[1]+sharp[ID][i*2+1];

map[nx][ny]=1;

}

if(hotpoint[0]

top=hotpoint[0];

clear=0;//消除的格数

for(i=hotpoint[0];i

{

flag=0;

for(j=0;j<12;j++)//检测是否可以消除此行

{

if(map[i][j]==0)//代表有空格,不能消除

{

flag=1;//1表示不能消除

break;

}

}

if(flag==0)//可以消除

{

for(k=i;k>=top;k--)//从当前位置向上所有的点下移一行

{

if(k==0)//最高点特殊处理

for(j=0;j<12;j++)

{

map[k][j]=0;

SetPos((j+1)*2,k+1);

cout<

}

else

{

for(j=0;j<12;j++)

{

map[k][j]=map[k-1][j];

SetPos((j+1)*2,k+1);

if(map[k][j]==0)

cout<

else

cout<

}

}

}

top++;//消除成功,最高点下移

clear++;

point+=clear*10*level;

}

}

SetColor(0);

SetPos(16*2,17);

cout<

}

void Box::Run()//运行游戏

{

int i=0;

char x;

int Count;//计数器

int nextID;

int temp;

srand((int)time(0));//将随机数的起点设置为time(0):不带秒

ID=rand()%15;//随机生成ID和下一个ID

nextID=rand()%15;//这里为了方便,其实每个形状不是等概率生成的

DrawBox(hotpoint[0],hotpoint[1],ID);//绘制图形

DrawBox(3,17,nextID);

Count=1000-level*100;//等级决定计数,这里是用Count控制时间,来控制下落的速度

while(1)

{

if(i>=Count)

{

i=0;//计数器清零

if(Judge(hotpoint[0]+1,hotpoint[1]))//如果下个位置无效(即到底)

{

UpdataMap();//更新画面

ID=nextID;//生成新ID,用原等待ID替换为当前ID

hotpoint[0]=0;//热点更新

hotpoint[1]=5;

Redraw(3,17,nextID);

nextID=rand()%15;

DrawBox(hotpoint[0],hotpoint[1],ID);

DrawBox(3,17,nextID);

if(Judge(hotpoint[0],hotpoint[1]))//无法绘制开始图形,游戏结束

{

//getch();

system("cls");

SetPos(25,15);

cout<

system("pause");//就是在命令行上输出一行类似于“Press any key to exit”

exit(0);//关闭所有文件,退出正在执行的程序,返回0代表正常结束

}

}

else

{

Redraw(hotpoint[0],hotpoint[1],ID);//没有到底,方块下移一位

hotpoint[0]++;//热点下移

DrawBox(hotpoint[0],hotpoint[1],ID);

}

}

if(kbhit())//读取键盘信息

{

x=getch();

if(x=='a'||x=='A')//左移

{

if(Judge(hotpoint[0],hotpoint[1]-1)==0)

{

Redraw(hotpoint[0],hotpoint[1],ID);

hotpoint[1]-=1;

DrawBox(hotpoint[0],hotpoint[1],ID);

}

}

if(x=='d'||x=='D')//右移

{

if(Judge(hotpoint[0],hotpoint[1]+1)==0)

{

Redraw(hotpoint[0],hotpoint[1],ID);

hotpoint[1]+=1;

DrawBox(hotpoint[0],hotpoint[1],ID);

}

}

if(x=='s'||x=='S')//向下加速!!!!!!!!此处可以改进,可以改进加速效果。改成+3之后,会出现BUG,最后几个无法加速

{

if(Judge(hotpoint[0]+3,hotpoint[1])==0)

{

Redraw(hotpoint[0],hotpoint[1],ID);

hotpoint[0]+=1;

DrawBox(hotpoint[0],hotpoint[1],ID);

}

}

if(x=='w'||x=='W')//转动方块

{

temp=ID;

Turn();

if(!Judge(hotpoint[0],hotpoint[1]))

{

Redraw(hotpoint[0],hotpoint[1],temp);

DrawBox(hotpoint[0],hotpoint[1],ID);

}

else

ID=temp;

}

if(x=='p'||x=='P')

{

//getch();

//system("cls");

Pause();

}

if(x=='q'||x=='Q')

{

system("cls");

SetPos(25,15);

cout<

system("pause");

exit(0);

}

while(kbhit())//读掉剩下的键盘信息

getch();

}

Sleep(1);//等待1毫秒

i++;//计数器加1

}

}

bool Box::Judge(int x,int y)//判断当前是否可以绘制方块

{

int i;

int nx,ny;

for(i=0;i<4;i++)

{

nx=x+sharp[ID][i*2];

ny=y+sharp[ID][i*2+1];

if(nx<0||nx>=23||ny<0||ny>=12||map[nx][ny]==1)//不能,返回1

return 1;

}

return 0;

}

void Box::Pause()

{

system("cls");

while(1)

{

SetPos(30,13);

cout<

if(getch()=='p'||getch()=='P')

break;

}

SetPos(30,13);

cout<

DrawMap();

int i ,j;

for(i=0;i<23;i++)

for(j=0;j<12;j++)

if(map[i][j]==1)

{

SetPos((j+1)*2,i+1);

cout<

}

}

int main()//主函数

{

Box game;

game.Welcome();

system("cls");

game.DrawMap();

game.Run();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值