方向控制: 方向键;
变形 : 上键
该项目是我在研习<<windows程序设计>>第五版的过程中设计和完成的。设计的知识点主要有windows消息机制,GDI
画图,双缓冲绘图,计时器,文件读写,以及相关的win32API函数。
界面和布局的设计:为了尽可能避免由于不同分辨率而导致的界面不一致和不友好,我采用了相对大小来创建界面元素,
以高度为基准。如此可以满足除800*600以外的分辨率的机器。
主要逻辑:
A.. 初始化,程序涉及到6种图案,每种图案4种形态,每种图案都由4个单位元素组成,采用数组来存储其
位置和颜色,初始化的图案,颜色都是随机的,因此整个游戏的色彩很丰富,初始化位置在游戏区的中间;
B. 移动以及边界,设置每500ms图案自动向下移动一个单位元素,方向键的移动单位也是一个单元元素。每次移动只需改变相应数组元素的值。程序中定义一个BOOL的二维数组记录整个游戏区的每个单位元素的状态:是否有图案填充,这样在判定左右边界时,只需要判定当前图案的左右是否有图案或是否移动到游戏区域的边界;
C. 图案的消去,在每次图案“着地”程序都会从最底层检验二维BOOL数组,若有某行状态全为真,则将该行用背景色刷新,该行以上的行都向下移动一个单位元素。
当然,这个程序还有bug,而且在后期,我发现暴露了很多的问题,我开始感觉,我的设计有问题,希望看到的人,不吝赐教!!!
![](http://hi.csdn.net/attachment/201108/18/0_1313678752XUc4.gif)
下面贴出源代码:
//Tetrics.h
#if !defined(AFX_TETRIS_H__E473E981_22C4_4647_A965_4BCCF97ADDDA__INCLUDED_)
#define AFX_TETRIS_H__E473E981_22C4_4647_A965_4BCCF97ADDDA__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "resource.h"
#define MAX_LOADSTRING 100
#define SHAPE_NUM 5 //种类
#define PATTERN_NUM 4 //形态
#define UNIT 1
#define COL_NUM 10 //列数
#define ROW_NUM 18 //行数
#define CELL_COUNT 4
#define IDC_MAIN_BUTTON_START 101
#define IDC_MAIN_BUTTON_PAUSE 102
#define IDC_MAIN_BUTTON_STOP 103
#define IDC_MAIN_BUTTON_EXIT 105
#define IDC_MAIN_STATIC_SCORE 106
#define IDC_MAIN_STATIC_NUM 107
// Global Variables:
HDC hdcMem;
HBRUSH hBrush;
int width,height,showWidth;
int cellSize;
int cxScreen, cyScreen;
COLORREF col=0,nextcol=0; //记忆每个图案的颜色
int shape,pattern; //方块的类型和形态
int nextshape,nextpattern;//下一个方块的类型和形态
int grade = 0;
COLORREF color[ROW_NUM][COL_NUM]; //记录每个单元格的颜色
bool isFilled[ROW_NUM][COL_NUM]; //记录每个单元格的状态:是否被填充
enum {LEFT,RIGHT,DOWN,CHANGE} direc; //左,右,下,变形(上键)
typedef struct
{
int ix;
int iy;
}Point;
typedef struct
{
Point shape[CELL_COUNT];
}ShapeLoc;
//用于还原图案的初始位置
ShapeLoc shapeInit[SHAPE_NUM][PATTERN_NUM]= //凸形,Z形,L形,直条,田形
{
{
{4,0,3,1,4,1,5,1},{4,0,4,1,4,2,5,1},
{3,0,4,0,5,0,4,1},{4,0,4,1,4,2,3,1}
},
{
{3,0,4,0,4,1,5,1},{4,0,4,1,5,1,5,2},
{4,0,5,0,3,1,4,1},{3,1,3,2,4,0,4,1}
},
{
{3,0,4,0,5,0,5,1},{3,0,4,0,4,1,4,2},
{5,0,3,1,4,1,5,1},{4,0,4,1,4,2,5,2}
},
{
{3,0,4,0,5,0,6,0},{4,0,4,1,4,2,4,3},
{3,0,4,0,5,0,6,0},{4,0,4,1,4,2,4,3}
},
{
{3,0,4,0,3,1,4,1},{3,0,4,0,3,1,4,1},
{3,0,4,0,3,1,4,1},{3,0,4,0,3,1,4,1}
}
};
用于动态记录图案的运动位置
ShapeLoc shapeMuti[SHAPE_NUM][PATTERN_NUM]=
{
{
{4,0,3,1,4,1,5,1},{4,0,4,1,4,2,5,1},
{3,0,4,0,5,0,4,1},{4,0,4,1,4,2,3,1}
},
{
{3,0,4,0,4,1,5,1},{4,0,4,1,5,1,5,2},
{4,0,5,0,3,1,4,1},{3,1,3,2,4,0,4,1}
},
{
{3,0,4,0,5,0,5,1},{3,0,4,0,4,1,4,2},
{5,0,3,1,4,1,5,1},{4,0,4,1,4,2,5,2}
},
{
{3,0,4,0,5,0,6,0},{4,0,4,1,4,2,4,3},
{3,0,4,0,5,0,6,0},{4,0,4,1,4,2,4,3}
},
{
{3,0,4,0,3,1,4,1},{3,0,4,0,3,1,4,1},
{3,0,4,0,3,1,4,1},{3,0,4,0,3,1,4,1}
}
};
//enum {HILL_TU,Z_SHAPE,HILL_AO,L_SHAPE,LINE,MY_RECT} em_shape;
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING];
struct //定义结构体,存储BUTTON的相关信息,以便后面用for循环创建BUTTTON,简化编程
{
int iID ;
TCHAR *szText ;
}
button[] = //BUTTON数组
{
IDC_MAIN_BUTTON_START, TEXT("开始"), // Button identifier
IDC_MAIN_BUTTON_STOP, TEXT("停止"),
IDC_MAIN_BUTTON_EXIT, TEXT("关闭"),
};
#define NUM sizeof(button)/sizeof(button[0])
//Tetrics.c
// Tetris.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "Tetris.h"
#include <time.h>
#include <stdio.h>
#include <string>
#include <Mmsystem.h>
#pragma comment (lib,"winmm.lib")
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); //关于对话框
LRESULT CALLBACK Over(HWND hDlg,UINT message, WPARAM wParam, LPARAM lParam); //游戏结束对话框
void DrawFullMap(HWND hWnd) ; //刷新整个游戏区域
void EreaseOrig(ShapeLoc *loc); //擦除移动前的图案
void RedrawShape(ShapeLoc *loc); //重画移动后的图案
void Move(HWND hWnd,HDC hdc,RECT rc,int direction); //移动
void InitDrawInfo(); //初始化图案,样式,以及画刷颜色
void DrawNextShape(HDC hdc,RECT rc); //下一个图案
void InitCloAndFilled(); //初始化游戏区域信息
void DeleteUserDC(HBITMAP hBitmap); //释放DC资源
void ResetNextRc(HDC hdc,RECT rc); //刷新非游戏区域
void ModifyCoordinate(); //修正移动过程中图案的不合法位置
void SetGrade(HWND hWnd); //分数记录
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TETRIS, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TETRIS);
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage is only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_OWNDC ;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_ICON_MAIN);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_HIGHLIGHT+1);//要修改
wcex.lpszMenuName = (LPCSTR)IDC_TETRIS;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = NULL;//LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW &~WS_MAXIMIZEBOX &~WS_THICKFRAME,
0,0,0,0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
static HBITMAP hBitmap;
// static HBRUSH hBrushStatic;
static HDC hdc;
static HPEN hPen;
//static HBRUSH hBrush;
static BOOL reset = FALSE;
static BOOL start = TRUE;
static BOOL stop = FALSE;
static HWND hwndButton[NUM+2]; //BUTTTON + 2*STATIC
static RECT rc; //方块的移动区域
static RECT nextRc;//下一个方块的绘图区域
static BOOL Replay = FALSE;
// TCHAR szHello[MAX_LOADSTRING];
//LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
//KillTimer(hWnd,1);
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
/*case IDM_OVER:
DialogBox(hInst, (LPCTSTR)IDD_DIALOG_GAMEOVER, hWnd, (DLGPROC)Over);
break;*/
case IDC_MAIN_BUTTON_EXIT:
DeleteUserDC(hBitmap);
DestroyWindow(hWnd);
break;
case IDC_MAIN_BUTTON_START:
hdc = GetDC(hWnd);
if(start) //游戏开始
{
InitCloAndFilled();
DrawFullMap(hWnd);
InitDrawInfo();
RedrawShape(&shapeMuti[shape][pattern]);
BitBlt(hdc,rc.left,rc.top,width,height,hdcMem,0,0,SRCCOPY);
DrawNextShape(hdc,nextRc);
SetFocus(hWnd); //使游戏区域获得焦点
SetTimer(hWnd,1,500,NULL);
stop = TRUE;
}
else
{
SetTimer(hWnd,1,500,NULL);
SetFocus(hWnd);
}
ReleaseDC(hWnd,hdc);
break;
case IDC_MAIN_BUTTON_STOP:
if(stop)
{
KillTimer(hWnd,1); //暂停,关闭计时器
start = FALSE;
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_CREATE: //设置游戏区域大小,创建界面元素
{ //HDC hdc = GetDC(hWnd);
cxScreen = GetSystemMetrics (SM_CXFULLSCREEN);
cyScreen = GetSystemMetrics (SM_CYFULLSCREEN);
height = cyScreen- GetSystemMetrics (SM_CYCAPTION)-GetSystemMetrics(SM_CYMENU);
cellSize = (int)(height/ROW_NUM); //一个单元个的大小
width = cellSize*COL_NUM; //方块区域的宽度
showWidth = cellSize*9; //方块区域的高度
MoveWindow(hWnd,cxScreen/4,0,width+showWidth,cyScreen-4*GetSystemMetrics(SM_CYFIXEDFRAME),TRUE);
for(int i=0;i<NUM;i++)//创建多个BUTTON
{
hwndButton[i] =CreateWindow (TEXT("BUTTON"),button[i].szText,WS_CHILD | WS_VISIBLE |BS_DEFPUSHBUTTON,
cellSize*(COL_NUM+2*i),height-cellSize*5/4,2*cellSize,cellSize,hWnd,(HMENU)button[i].iID,GetModuleHandle(NULL), NULL) ;
}
// hwndButton[NUM] =CreateWindow(TEXT("STATIC"),TEXT("得分"),WS_CHILD | WS_VISIBLE |SS_CENTER,
// cellSize*(COL_NUM+4),height/2,2*cellSize,cellSize/2,hWnd,(HMENU)IDC_MAIN_STATIC_SCORE,GetModuleHandle(NULL), NULL) ;
hwndButton[NUM+1] =CreateWindow (TEXT("STATIC"),("0"),WS_CHILD | WS_VISIBLE |SS_CENTER,
cellSize*(COL_NUM+6),height-cellSize*5/4,2*cellSize,cellSize,hWnd,(HMENU)IDC_MAIN_STATIC_NUM,GetModuleHandle(NULL), NULL) ;
}
break;
case WM_SIZE:
GetClientRect(hWnd,&rc);
hdc = GetDC(hWnd);
hdcMem = CreateCompatibleDC(hdc);//创建内存DC
hBitmap = CreateCompatibleBitmap(hdc,width,height);//创建位图
SelectObject(hdcMem,hBitmap);
ReleaseDC(hWnd,hdc);
SetRect(&nextRc,width+cellSize,rc.top+cellSize,width+7*cellSize,rc.top+6*cellSize);
break;
case WM_DISPLAYCHANGE://处理分辨率改变事件
cxScreen = GetSystemMetrics (SM_CXFULLSCREEN);
cyScreen = GetSystemMetrics (SM_CYFULLSCREEN);
height = cyScreen- GetSystemMetrics (SM_CYCAPTION)-GetSystemMetrics (SM_CYMENU);
cellSize = (int)(height/(ROW_NUM)); //一个单元个的大小
width = cellSize*COL_NUM; //方块区域的宽度
showWidth = cellSize*8; //右边显示区
MoveWindow(hWnd,cxScreen/4,0,width+showWidth,cyScreen,TRUE);//设置窗口大小
break;
case WM_PAINT:
{ hdc = BeginPaint(hWnd, &ps);
HDC hdcCompatible = CreateCompatibleDC(hdc);//客户区右半部分,小人
HBITMAP hBitmap1 = LoadBitmap(hInst,MAKEINTRESOURCE(IDB_BITMAP_SHOW));
SelectObject(hdcCompatible,hBitmap1);
BitBlt(hdc,width,0,width+showWidth,cyScreen,hdcCompatible,0,0,SRCCOPY);
DeleteDC(hdcCompatible);
//hBrush =(HBRUSH)SelectObject(hdc,CreateSolidBrush(RGB(0,255,125)));
hPen=(HPEN)SelectObject(hdc,CreatePen(PS_SOLID,2,RGB(255,0,0)));
MoveToEx(hdc,width,rc.top,NULL);
LineTo(hdc,width,rc.bottom);
// Rectangle(hdc,width,rc.top,rc.right,rc.bottom);
ResetNextRc(hdc,nextRc);
DrawFullMap(hWnd);//实现消去时的界面重绘
BitBlt(hdc,rc.left,rc.top,width,height,hdcMem,0,0,SRCCOPY);
DeleteObject(SelectObject(hdc,hPen));
// DeleteObject(SelectObject(hdc,hBrush));
EndPaint(hWnd, &ps);
}
break;
case WM_TIMER:
{
hdc = GetDC(hWnd);
EreaseOrig(&shapeMuti[shape][pattern]);//擦除移动前的图案
Move(hWnd,hdc,nextRc,DOWN);//向下移动一个单位,没500ms
RedrawShape(&shapeMuti[shape][pattern]);//绘制移动后的图案
BitBlt(hdc,rc.left,rc.top,width,height,hdcMem,0,0,SRCCOPY);//块传输都当前DC
ReleaseDC(hWnd,hdc);
}
break;
case WM_KEYDOWN:
hdc = GetDC(hWnd);
switch(wParam)
{
case VK_LEFT: //方向左键
EreaseOrig(&shapeMuti[shape][pattern]);
Move(hWnd,hdc,nextRc,LEFT);
RedrawShape(&shapeMuti[shape][pattern]);
BitBlt(hdc,rc.left,rc.top,width,height,hdcMem,0,0,SRCCOPY);
break;
case VK_RIGHT: //方向右键
EreaseOrig(&shapeMuti[shape][pattern]);
Move(hWnd,hdc,nextRc,RIGHT);
RedrawShape(&shapeMuti[shape][pattern]);
BitBlt(hdc,rc.left,rc.top,width,height,hdcMem,0,0,SRCCOPY);
break;
case VK_DOWN: //方向下键
EreaseOrig(&shapeMuti[shape][pattern]);
Move(hWnd,hdc,nextRc,DOWN);
RedrawShape(&shapeMuti[shape][pattern]);
BitBlt(hdc,rc.left,rc.top,width,height,hdcMem,0,0,SRCCOPY);
break;
case VK_UP: //改变样式
EreaseOrig(&shapeMuti[shape][pattern]);
pattern = (pattern+1)%PATTERN_NUM;
Move(hWnd,hdc,nextRc,CHANGE);
break;
}
ReleaseDC(hWnd,hdc);
break;
case WM_DESTROY:
DeleteUserDC(hBitmap);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK||LOWORD(wParam) == IDCANCEL)
{
// SendMessage(GetParent(hDlg),WM_COMMAND,WM_TIMER,0);
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
// Mesage handler for gameover box.
LRESULT CALLBACK Over(HWND hDlg,UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
SendMessage(GetParent(hDlg),WM_COMMAND,IDC_MAIN_BUTTON_EXIT,0);
return TRUE;
}
if(LOWORD(wParam) == IDCANCEL)
{
InitCloAndFilled();
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
//重新使改变了坐标的图案,恢复初始位置,以便下次的绘制
void ResetShapeLoc(ShapeLoc *curr,ShapeLoc *orig,int pattern,int cell_count)
{
int i,j;
for(i=0;i<pattern;++i)
{
for(j=0;j<cell_count;++j)
{
curr[i].shape[j].ix = orig[i].shape[j].ix;
curr[i].shape[j].iy = orig[i].shape[j].iy;
}
}
}
void ResetNextRc(HDC hdc,RECT rc)//右半区的贴图
{
HDC hdcCompatible = CreateCompatibleDC(hdc);
HBITMAP hBitmap1 = LoadBitmap(hInst,MAKEINTRESOURCE(IDB_BITMAP_SHOW));
SelectObject(hdcCompatible,hBitmap1);
BitBlt(hdc,width,0,width+showWidth,cyScreen,hdcCompatible,0,0,SRCCOPY);
DeleteDC(hdcCompatible);
//hBrush =(HBRUSH)SelectObject(hdc,CreateSolidBrush(RGB(0,0,0)));
//Rectangle(hdc,rc.left,rc.top,rc.right,rc.bottom);
// DeleteObject(SelectObject(hdc,hBrush));
}
void DrawNextShape(HDC hdc,RECT rc)//绘制下一个
{
//srand((UINT)time(NULL));
nextshape = rand()%SHAPE_NUM; //形状
nextpattern = rand()%PATTERN_NUM; //样式
nextcol = RGB(rand()%256,rand()%256,rand()%256);//颜色
ResetNextRc(hdc,rc);
hBrush =(HBRUSH)SelectObject(hdc,CreateSolidBrush(nextcol));
for(int i=0;i<CELL_COUNT;++i)
{
Rectangle(hdc,(shapeMuti[nextshape][nextpattern].shape[i].ix+9)*cellSize,(shapeMuti[nextshape][nextpattern].shape[i].iy+2)*cellSize,
(shapeMuti[nextshape][nextpattern].shape[i].ix+10)*cellSize,(shapeMuti[nextshape][nextpattern].shape[i].iy+3)*cellSize);
}
}
void InitDrawInfo()//初始化绘制信息
{
srand((UINT)time(NULL));
shape = rand()%SHAPE_NUM;
pattern = rand()%PATTERN_NUM;
col = RGB(rand()%256,rand()%256,rand()%256);
hBrush =(HBRUSH)SelectObject(hdcMem,CreateSolidBrush(col));
}
void DeleteUserDC(HBITMAP hBitmap)//释放相关内存资源
{
if(hdcMem!=NULL)
{
DeleteDC(hdcMem);
DeleteObject(hBitmap);
hdcMem = NULL;
hBitmap = NULL;
}
}
void DeleteDrawInfo()
{
if(hBrush!=NULL)
{
DeleteObject(SelectObject(hdcMem,hBrush));
hBrush = NULL;
}
}
BOOL isAnyFilled(int row, int column)//检查某行是否至少有一个单元格被绘制
{
int j;
for(j=0;j<column;++j)
{
if(isFilled[row][j])
{
return TRUE;
break;
}
}
if(j==column)
{
return FALSE;
}
else
{
return TRUE;
}
}
void InitCloAndFilled() //初始设置,颜色为0;未被绘制
{
int i,j;
for(i=0;i<ROW_NUM;++i)
{
for(j=0;j<COL_NUM;++j)
{
color[i][j] = 0;
isFilled[i][j] = 0;
}
}
}
void DrawFullMap(HWND hWnd) //消去时重绘
{
int i,j;
for(i=ROW_NUM-1;i>-1;--i) //对整个区域做标记
{
if(isAnyFilled(i,COL_NUM))
{
for(j=0;j<COL_NUM;++j)
{
if(!isFilled[i][j])
{
break;
}
}
if(j==COL_NUM)
{
::grade++; //分数
PlaySound(TEXT("grade.WAV"),NULL,SND_FILENAME | SND_ASYNC);//播放音频
for(int k=i;k>-1;--k) //下移
{
if(isAnyFilled(k,COL_NUM))
{
for(j=0;j<COL_NUM;++j)
{
color[k][j] = color[k-1][j];
isFilled[k][j] = isFilled[k-1][j];
}
i=ROW_NUM;
}
}
}
}
else
{
break;
}
}
for(i=ROW_NUM-1;i>-1;--i)//对整个区域进行绘制
{
if(isAnyFilled(i,COL_NUM))
{
for(j=0;j<COL_NUM;++j)
{
hBrush =(HBRUSH)SelectObject(hdcMem,CreateSolidBrush(color[i][j]));
Rectangle(hdcMem,j*cellSize,i*cellSize,(j+1)*cellSize,(i+1)*cellSize);
if(hBrush!=NULL)
{
DeleteObject(SelectObject(hdcMem,hBrush));
hBrush = NULL;
}
}
}
else
{
hBrush =(HBRUSH)SelectObject(hdcMem,CreateSolidBrush(0));
Rectangle(hdcMem,0,0,(i+1)*cellSize,(i+1)*cellSize);
if(hBrush!=NULL)
{
DeleteObject(SelectObject(hdcMem,hBrush));
hBrush = NULL;
}
break;
}
}
SetGrade(hWnd);
}
void SetGrade(HWND hWnd)
{
TCHAR strGrade[10];
itoa(::grade,strGrade,10);
::SetWindowText(GetDlgItem(hWnd,IDC_MAIN_STATIC_NUM),strcat(strGrade,"00"));
}
void EreaseOrig(ShapeLoc *loc)
{
int i;
hBrush =(HBRUSH)SelectObject(hdcMem,CreateSolidBrush(0));
for(i=0;i<CELL_COUNT;++i)
{
Rectangle(hdcMem,loc->shape[i].ix*cellSize,loc->shape[i].iy*cellSize,
(loc->shape[i].ix+1)*cellSize,(loc->shape[i].iy+1)*cellSize);
}
if(hBrush!=NULL)
{
DeleteObject(SelectObject(hdcMem,hBrush));
hBrush = NULL;
}
}
void RedrawShape(ShapeLoc *loc)
{
int i;
for(i=0;i<CELL_COUNT;++i)
{
if(!isFilled[loc->shape[i].iy][loc->shape[i].ix])
{
Rectangle(hdcMem,loc->shape[i].ix*cellSize,loc->shape[i].iy*cellSize,
(loc->shape[i].ix+1)*cellSize,(loc->shape[i].iy+1)*cellSize);
}
}
}
void ModifyFullMap(ShapeLoc *loc)
{
int i;
for(i=0;i<CELL_COUNT;++i)
{
isFilled[loc->shape[i].iy][loc->shape[i].ix] = TRUE;
color[loc->shape[i].iy][loc->shape[i].ix] = col;
}
col = 0; //重置为背景色,准备下一个图案的颜色
}
BOOL IsLeftBoundary(ShapeLoc *loc)//左边界判定
{
int i,x,y;
x = loc->shape[0].ix;
y = loc->shape[0].iy;
for(i=1;i<CELL_COUNT;++i)
{
if( x > loc->shape[i].ix)
{
x = loc->shape[i].ix;
//y = loc->shape[i].iy;
}
}
for(i=0;i<CELL_COUNT;++i)
{
if((x-1)>-1 && color[loc->shape[i].iy][loc->shape[i].ix-1]!=0)
{
return true;
}
}
if(x <= 0) //到了左边界或者左边已经有方块
{
return true;
}
else
{
return false;
}
}
BOOL IsRightBoundary(ShapeLoc *loc)//右边界判定
{
int i,x,y;
x = loc->shape[0].ix;
y = loc->shape[0].iy;
for(i=1;i<CELL_COUNT;++i)
{
if(loc->shape[0].ix < loc->shape[i].ix)
{
x = loc->shape[i].ix;
//y = loc->shape[i].iy;
}
}
for(i=0;i<CELL_COUNT;++i)
{
if((x+1)<COL_NUM && color[loc->shape[i].iy][loc->shape[i].ix+1]!=0)
{
return true;
}
}
if(x >= COL_NUM-1) //到了右边界或者右边已经有方块
{
return true;
}
else
{
return false;
}
}
BOOL IsBottomBoundary(ShapeLoc *loc)//下边界判定
{
int i,y;
BOOL ret = FALSE;
y = loc->shape[0].iy;
for(i=1;i<CELL_COUNT;++i)
{
if(loc->shape[0].iy < loc->shape[i].iy)
{
y = loc->shape[i].iy;
}
}
for(i=0;i<CELL_COUNT;++i)
{
if(loc->shape[i].iy+1<ROW_NUM)
{
if(color[loc->shape[i].iy+1][loc->shape[i].ix]!=0 )
{
ret = TRUE;
break;
}
}
}
if(y >= ROW_NUM-1 || ret)
{
return TRUE;
}
else
{
return FALSE;
}
}
BOOL IsGameOver(HWND hWnd)//游戏是否结束的判定
{
BOOL ret = FALSE;
for(int i=0;i<COL_NUM;++i)
{
if(isFilled[0][i]!=0)
{
ret = TRUE;
break;
}
}
return ret;
}
void MoveLeft()//左移
{
int i,j;
if(!IsLeftBoundary(&shapeMuti[shape][pattern]))
{
for(i=0;i<PATTERN_NUM;++i)
{
for(j=0;j<CELL_COUNT;++j)
{
{
shapeMuti[shape][i].shape[j].ix -= UNIT;
}
}
}
}
}
void MoveRight()//右移
{
int i,j;
if(!IsRightBoundary(&shapeMuti[shape][pattern]))
{
for(i=0;i<PATTERN_NUM;++i)
{
for(j=0;j<CELL_COUNT;++j)
{
{
shapeMuti[shape][i].shape[j].ix += UNIT;
}
}
}
}
}
void MoveDown(HWND hWnd,HDC hdc,RECT rc)//下移
{
int i,j;
if(!IsBottomBoundary(&shapeMuti[shape][pattern]))//未到下边界
{
for(i=0;i<PATTERN_NUM;++i)
{
for(j=0;j<CELL_COUNT;++j)
{
if(shapeMuti[shape][i].shape[j].iy +UNIT<ROW_NUM)
{
shapeMuti[shape][i].shape[j].iy += UNIT;
}
}
}
}
else
{
ModifyFullMap(&shapeMuti[shape][pattern]);//记录当前图案的颜色,和状态
ResetShapeLoc(shapeMuti[shape],shapeInit[shape],PATTERN_NUM,CELL_COUNT);
if(!IsGameOver(hWnd)) //已到下边界,但游戏为结束
{
//InitDrawInfo(hdc,hBrush);
shape = nextshape;
pattern = nextpattern;
col = nextcol;
hBrush =(HBRUSH)SelectObject(hdcMem,CreateSolidBrush(col));
DrawNextShape(hdc,rc);
DrawFullMap(hWnd);
}
else //游戏结束
{
KillTimer(hWnd,1);
SetFocus(NULL);
DialogBox(hInst, (LPCTSTR)IDD_DIALOG_GAMEOVER, hWnd, (DLGPROC)Over);
//hBrush =(HBRUSH)SelectObject(hdc,CreateSolidBrush(0));
}
}
}
void Move(HWND hWnd,HDC hdc,RECT rc,int direction)
{
switch(direction)
{
case LEFT:
MoveLeft();
break;
case RIGHT:
MoveRight();
break;
case DOWN:
MoveDown(hWnd,hdc,rc);
break;
case CHANGE:
ModifyCoordinate();
break;
}
}
void LeftOverflow() //左溢出
{
int i;
int min=0;
for(i=0;i<CELL_COUNT;++i)
{
if(shapeMuti[shape][pattern].shape[i].ix<min)
{
min = shapeMuti[shape][pattern].shape[i].ix; //min<=0
}
}
if(min<0)
{
for(i=0;i<CELL_COUNT;++i)
{
shapeMuti[shape][pattern].shape[i].ix-=min;//右移min个单位
}
}
}
void RightOverflow()//右溢出
{
int i;
int max = 9;
for(i=0;i<CELL_COUNT;++i)
{
if(shapeMuti[shape][pattern].shape[i].ix>max)
{
max = shapeMuti[shape][pattern].shape[i].ix; //max>=9
}
}
if(max>9)
{
for(i=0;i<CELL_COUNT;++i)
{
shapeMuti[shape][pattern].shape[i].ix-=(max-9);//左移max-9个单位
}
}
}
void BottomOverflow()//下溢出
{
int i,j;
int max=0;
for(i=0;i<CELL_COUNT;++i)
{
j = shapeMuti[shape][pattern].shape[i].ix;
for(int k=0;k<ROW_NUM;++k)
{
if(isFilled[k][j])
{
break;
}
}
if(k!=ROW_NUM)
{
if(shapeMuti[shape][pattern].shape[i].iy-k>=max)
{
max = shapeMuti[shape][pattern].shape[i].iy-k;
}
}
}
for(i=0;i<CELL_COUNT;++i)
{
shapeMuti[shape][pattern].shape[i].iy-=(max+1);
}
}
void ModifyCoordinate()
{
LeftOverflow();
RightOverflow();
BottomOverflow();
}
#endif // !defined(AFX_TETRIS_H__E473E981_22C4_4647_A965_4BCCF97ADDDA__INCLUDED_)