方向控制: 方向键;
变形 : 上键
该项目是我在研习<<windows程序设计>>第五版的过程中设计和完成的。设计的知识点主要有windows消息机制,GDI
画图,双缓冲绘图,计时器,文件读写,以及相关的win32API函数。
界面和布局的设计:为了尽可能避免由于不同分辨率而导致的界面不一致和不友好,我采用了相对大小来创建界面元素,
以高度为基准。如此可以满足除800*600以外的分辨率的机器。
主要逻辑:
A.. 初始化,程序涉及到6种图案,每种图案4种形态,每种图案都由4个单位元素组成,采用数组来存储其
位置和颜色,初始化的图案,颜色都是随机的,因此整个游戏的色彩很丰富,初始化位置在游戏区的中间;
B. 移动以及边界,设置每500ms图案自动向下移动一个单位元素,方向键的移动单位也是一个单元元素。每次移动只需改变相应数组元素的值。程序中定义一个BOOL的二维数组记录整个游戏区的每个单位元素的状态:是否有图案填充,这样在判定左右边界时,只需要判定当前图案的左右是否有图案或是否移动到游戏区域的边界;
C. 图案的消去,在每次图案“着地”程序都会从最底层检验二维BOOL数组,若有某行状态全为真,则将该行用背景色刷新,该行以上的行都向下移动一个单位元素。
当然,这个程序还有bug,而且在后期,我发现暴露了很多的问题,我开始感觉,我的设计有问题,希望看到的人,不吝赐教!!!
下面贴出源代码:
//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_T