这是他做的俄罗斯方块:
下面是他的代码,他是在VS2003中写得,我没用过,哈哈,有些格式还不清楚呢,他的代码比我的干净,整齐多了,这方面我要好好注意下才行。
///stdafx.h///
// stdafx.h : 标准系统包含文件的包含文件,
// 或是常用但不常更改的项目特定的包含文件
//
#pragma once
#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料
// Windows 头文件:
#include <windows.h>
// C 运行时头文件
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
// TODO: 在此处引用程序要求的附加头文件
//resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by Tetris.rc
//
#define IDC_MYICON 2
#define IDD_TETRIS_DIALOG 102
#define IDS_APP_TITLE 103
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDI_TETRIS 107
#define IDI_SMALL 108
#define IDC_TETRIS 109
#define IDR_MAINFRAME 128
#define ID_Menu 32772
#define IDM_PAUSE 32774
#define IDM_NEW 32775
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 129
#define _APS_NEXT_COMMAND_VALUE 32776
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif
/Tetris.h//
#pragma once
#include "resource.h"
///
/Tetrisdata.h//
#include <time.h>
#define X 12 //定义一行方块的数目
#define Y 25 //定义一列方块的数目
#define COL 4 //定义显示方块使用的颜色数量
//函数声明:
extern int createblock(void);
extern int loadblock(void);
extern int gameinit();
extern int moveright();
extern int moveleft();
extern int movedown();
extern int canmove(int);
extern int turn();
extern int isbottom();
extern int clear();
extern int downline(int line);
static int tetris[Y+5][X+2]; //整个游戏区域的数组
//存储所有方块的形态的数组
static int block[19][16]={
0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,/*11*/
0,0,0,0,0,1,0,0,1,1,0,0,1,0,0,0,/*12*/
0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0,/*21*/
0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,/*22*/
0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,/*31*/
0,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,/*32*/
0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0,/*33*/
0,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,/*34*/
0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,/*41*/
0,0,0,0,0,1,0,0,0,1,0,0,1,1,0,0,/*42*/
0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,/*43*/
0,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,/*44*/
0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0,/*51*/
0,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0,/*52*/
0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,/*53*/
0,0,0,0,1,0,0,0,1,1,0,0,1,0,0,0,/*54*/
0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,/*61*/
0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,/*62*/
0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0};/*71*/
static int bxy[4][2]; //当前方块的四个基本位置坐标
int current; //当前方块的种类(作为数组block的第一维)
int next; //下一个方块的种类
int speed; //当前游戏速度
int score; //当前游戏得分
int level; //当前游戏关数
long timer; //用于游戏控制定时器的变量
bool gameover; //游戏结束的标志
bool pause; //游戏暂停的标志
bool readonly; //数组bxy可以被修改的标志
/
/stdafx.cpp///
// stdafx.cpp : 只包括标准包含文件的源文件
// Tetris.pch 将成为预编译头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"
// TODO: 在 STDAFX.H 中
//引用任何所需的附加头文件,而不是在此文件中引用
///
//Tetris.cpp//
// Tetris.cpp : 定义应用程序的入口点。
//
#include "stdafx.h"
#include "Tetris.h"
#include "Tetrisdata.h" //存储游戏数据结构,全局变量以及函数声明
#define MAX_LOADSTRING 100
//#define TIMER_PRINT 1 //窗口刷新定时器ID
#define TIMER_DOWN 1 //游戏控制定时器ID
#define BLOCKLEN 15 //绘图时单位方块的边长
#define TIMELEVEL 75 //每过一关后游戏时间间隔的减少量
#define INITSPEED 700 //第一关游戏时间间隔量
#define SCOREPERLEVEL 200 //过一关需要的分数
// 全局变量:
HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名
// 此代码模块中包含的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
VOID CALLBACK PrintProc (HWND, UINT, UINT, DWORD);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable;
// 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TETRIS, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TETRIS);
// 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// 函数: MyRegisterClass()
//
// 目的: 注册窗口类。
//
// 注释:
//
// 仅当希望在已添加到 Windows 95 的
// “RegisterClassEx”函数之前此代码与 Win32 系统兼容时,
// 才需要此函数及其用法。调用此函数
// 十分重要,这样应用程序就可以获得关联的
// “格式正确的”小图标。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TETRIS);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = (LPCTSTR)IDC_TETRIS;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
return RegisterClassEx(&wcex);
}
//
// 函数: InitInstance(HANDLE, int)
//
// 目的: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // 将实例句柄存储在全局变量中
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPED|WS_SYSMENU|WS_BORDER|WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, (X+6)*BLOCKLEN, (Y+3)*BLOCKLEN, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// 函数: WndProc(HWND, unsigned, WORD, LONG)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
if (!pause)ModifyMenu(GetMenu(hWnd),IDM_PAUSE,MF_BYCOMMAND,IDM_PAUSE,"继续");
else ModifyMenu(GetMenu(hWnd),IDM_PAUSE,MF_BYCOMMAND,IDM_PAUSE,"暂停");
// 分析菜单选择:
switch (wmId)
{
case IDM_NEW:
gameinit();
break;
case IDM_PAUSE:
if (pause) pause = FALSE;
else pause = TRUE;
break;
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_CREATE:
static HBRUSH brush[4];
brush[0] = CreateSolidBrush(RGB(0,0,255) );
brush[1] = CreateSolidBrush(RGB(255,20,147));
brush[2] = CreateSolidBrush(RGB(0,255,0));
brush[3] = CreateSolidBrush(RGB(255,193,37));
gameinit();
pause = TRUE;
//SetTimer(hWnd,TIMER_PRINT,500,NULL);
timer = 0;
SetTimer(hWnd,TIMER_DOWN,TIMELEVEL,NULL);
break;
case WM_TIMER:
switch (wParam){
/* case TIMER_PRINT:
InvalidateRect (hWnd, NULL, TRUE) ;
break;*/
case TIMER_DOWN:
if (pause)break;
else {
if(timer < speed){
timer += TIMELEVEL;
break;
}
else {
if(canmove(3)){
movedown();
InvalidateRect (hWnd, NULL, TRUE) ;
timer = TIMELEVEL;
}
else {
isbottom();
InvalidateRect (hWnd, NULL, TRUE) ;
timer = TIMELEVEL;
}
if (gameover){
pause = TRUE;
if (MessageBox(hWnd,"Game Over!Retry?","Tetris",MB_YESNO)==IDYES)gameinit();
else exit(0);
}
}
break;
}
default : break;
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: 在此添加任意绘图代码...
int i,j;
//画方格:
for (i=0; i<=X; i++){
MoveToEx(hdc,i*BLOCKLEN,0,NULL);
LineTo(hdc,i*BLOCKLEN,BLOCKLEN*(Y-1));
}
for (i=0; i<Y; i++){
MoveToEx(hdc,0,i*BLOCKLEN,NULL);
LineTo(hdc,BLOCKLEN*X,i*BLOCKLEN);
}
//画方块:
int x,y,k;
for (i=1; i<=Y; i++){
for (j=1; j<=X; j++){
if (tetris[i][j]!=0){
k = tetris[i][j];
if (k>COL) k -= COL;
SelectObject (hdc, brush[k-1]);
x = (j-1)*BLOCKLEN;
y = (Y-1-i)*BLOCKLEN;
Rectangle(hdc,x,y,x+BLOCKLEN,y+BLOCKLEN);
}
}
}
//显示下一个方块:
for (i=0; i<=4; i++){
MoveToEx(hdc,(X+1)*BLOCKLEN,i*BLOCKLEN,NULL);
LineTo(hdc,(X+5)*BLOCKLEN,i*BLOCKLEN);
}
for (i=0; i<=4; i++){
MoveToEx(hdc,(X+1+i)*BLOCKLEN,0,NULL);
LineTo(hdc,(X+1+i)*BLOCKLEN,4*BLOCKLEN);
}
SelectObject (hdc, brush[1]);
for (i=0; i<4; i++){
for (j=0; j<4; j++){
if (block[next][i*4+j]==1){
x = (X+1+j)*BLOCKLEN;
y = i*BLOCKLEN;
Rectangle(hdc,x,y,x+BLOCKLEN,y+BLOCKLEN);
}
}
}
//显示分数:
char szbuf[10];
TextOut(hdc,(X+1)*BLOCKLEN,6*BLOCKLEN,"Score",strlen("Score"));
TextOut(hdc,(X+1)*BLOCKLEN,7*BLOCKLEN,szbuf,wsprintf (szbuf,"%d",score));
//显示关卡:
TextOut(hdc,(X+1)*BLOCKLEN,9*BLOCKLEN,szbuf,wsprintf(szbuf,"Level:%2d",level));
EndPaint(hWnd, &ps);
break;
case WM_KEYDOWN:
hdc = GetDC(hWnd);
if (pause)break;
else
switch (wParam){
case VK_LEFT:
if (canmove(1)) moveleft();
InvalidateRect (hWnd, NULL, TRUE) ;
break;
case VK_RIGHT:
if (canmove(2)) moveright();
InvalidateRect (hWnd, NULL, TRUE) ;
break;
case VK_DOWN:
while (canmove(3)) movedown();
isbottom();
InvalidateRect (hWnd, NULL, TRUE) ;
break;
case VK_UP:
turn();
InvalidateRect (hWnd, NULL, TRUE) ;
break;
default:break;
}
ReleaseDC (hWnd, hdc);
break;
case WM_DESTROY:
//KillTimer(hWnd,TIMER_PRINT);
KillTimer(hWnd,TIMER_DOWN);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “关于”框的消息处理程序。
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)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
/**************************************游戏控制函数******************************************/
//游戏初始化:
int gameinit(void)
{
int i,j;
gameover = FALSE;
for (i=0; i<Y+5; i++)
for (j=0; j<X+2; j++)
tetris[i][j] = 0;
for (j=0; j<X+2; j++){
tetris[0][j] = 1;
}
for (i=0; i<Y+5; i++){
tetris[i][0] = 1;
tetris[i][X+1] = 1;
}
next = createblock();
current = next;
next = createblock();
score = 0;
speed = INITSPEED;
level = 1;
readonly = FALSE;
loadblock();
pause = FALSE;
return 0;
}
//随机生成方块种类:
int createblock(void)
{
srand((unsigned)time(NULL));
return rand()%19;
}
//装载生成的方块:
int loadblock(void)
{
int i,j;
int *p;
p = &block[current][0];
int *pt;
pt = &bxy[0][0];
int color;
color = rand()%COL;
for (i=Y+4; i>Y; i--){
for (j=1; j<5; j++){
if (*p==1){
tetris[i][j] = *p+COL+color;
*pt = j;
*pt++;
*pt = i;
*pt++;
}
else tetris[i][j] = 0;
p++;
}
}
moveright();
moveright();
moveright();
moveright();
if (!canmove(3))gameover=TRUE;
return 0;
}
//判断当前方块能否移动,参数代表移动的类型:
int canmove(int how) /*1 for left, 2 for right, 3 for down*/
{
if (how==1){
int i,x,y;
for (i=0; i<4; i++){
x = bxy[i][0];
y = bxy[i][1];
if (tetris[y][x-1]>0 && tetris[y][x-1]<COL+1)break;
}
if (i==4)return TRUE;
else {
readonly = FALSE;
return FALSE;
};
}
else if (how==2){
int i,x,y;
for (i=0; i<4; i++){
x = bxy[i][0];
y = bxy[i][1];
if (tetris[y][x+1]>0 && tetris[y][x+1]<COL+1)break;
}
if (i==4)return TRUE;
else {
readonly = FALSE;
return FALSE;
}
}
else if (how==3){
int i,x,y;
for (i=0; i<4; i++){
x = bxy[i][0];
y = bxy[i][1];
if (tetris[y-1][x]>0 && tetris[y-1][x]<COL+1)break;
}
if (i==4)return TRUE;
else {
readonly = FALSE;
return FALSE;
}
}
else exit(3);
}
//左移当前方块:
int moveleft()
{
if (readonly)return 0;
else readonly = TRUE;
int i,j,x,y,tmp,tbx,tby;
for (i=0; i<3; i++){
for (j=0; j<3-i; j++){
if(bxy[j][0]>bxy[j+1][0])
{tbx=bxy[j][0];bxy[j][0]=bxy[j+1][0];bxy[j+1][0]=tbx;
tby=bxy[j][1];bxy[j][1]=bxy[j+1][1];bxy[j+1][1]=tby;}
}
}
for (i=0; i<4; i++){
x = bxy[i][0];
y = bxy[i][1];
tmp = tetris[y][x-1];
tetris[y][x-1] = tetris[y][x];
tetris[y][x] = tmp;
bxy[i][0]--;
}
readonly = FALSE;
return 0;
}
//右移当前方块:
int moveright()
{
if (readonly)return 0;
else readonly = TRUE;
int i,j,x,y,tmp,tbx,tby;
for (i=0; i<3; i++){
for (j=0; j<3-i; j++){
if(bxy[j][0]<bxy[j+1][0])
{tbx=bxy[j][0];bxy[j][0]=bxy[j+1][0];bxy[j+1][0]=tbx;
tby=bxy[j][1];bxy[j][1]=bxy[j+1][1];bxy[j+1][1]=tby;}
}
}
for (i=0; i<4; i++){
x = bxy[i][0];
y = bxy[i][1];
tmp = tetris[y][x+1];
tetris[y][x+1] = tetris[y][x];
tetris[y][x] = tmp;
bxy[i][0]++;
}
readonly = FALSE;
return 0;
}
//下降当前方块:
int movedown()
{
if (readonly)return 0;
else readonly = TRUE;
int i,j,x,y,tmp,tbx,tby;
for (i=0; i<3; i++){
for (j=0; j<3-i; j++){
if(bxy[j][1]>bxy[j+1][1])
{tbx=bxy[j][0];bxy[j][0]=bxy[j+1][0];bxy[j+1][0]=tbx;
tby=bxy[j][1];bxy[j][1]=bxy[j+1][1];bxy[j+1][1]=tby;}
}
}
for (i=0; i<4; i++){
x = bxy[i][0];
y = bxy[i][1];
tmp = tetris[y-1][x];
tetris[y-1][x] = tetris[y][x];
tetris[y][x] = tmp;
bxy[i][1]--;
}
readonly = FALSE;
return 0;
}
//当前方块到达底部时的操作:
int isbottom()
{
int i,x,y;
if (!canmove(3)){
for (i=0; i<4; i++){
x = bxy[i][0];
y = bxy[i][1];
tetris[y][x] -= COL;
}
}
clear();
current = next;
next = createblock();
loadblock();
return 0;
}
//旋转当前方块:
int turn()
{
if (readonly)return 0;
else readonly = TRUE;
int i,j,k,minx,miny,tmp,backupbxy[4][2],backupminx,backupminy,x,y;
//保存当前坐标
for (i=0; i<4; i++){
for (j=0; j<2; j++)
backupbxy[i][j] = bxy[i][j];
}
//得到当前方块最左下角坐标
minx = bxy[0][0];
miny = bxy[0][1];
for (i=0; i<4; i++){
if (minx > bxy[i][0]) minx = bxy[i][0];
if (miny > bxy[i][1]) miny = bxy[i][1];
}
for (i=0; i<4; i++){
//换算成相对坐标
backupbxy[i][0] -= minx;
backupbxy[i][1] -= miny;
//坐标旋转
tmp = backupbxy[i][0];
backupbxy[i][0] = backupbxy[i][1];
backupbxy[i][1] = 3-tmp;
}
backupminx = backupbxy[0][0];
backupminy = backupbxy[0][1];
for (i=0; i<4; i++){
if (backupminx > backupbxy[i][0]) backupminx = backupbxy[i][0];
if (backupminy > backupbxy[i][1]) backupminy = backupbxy[i][1];
}
for(i=0; i<4; i++){
backupbxy[i][0] -= backupminx;
backupbxy[i][1] -= backupminy;
}
for(i=0; i<4; i++){
//旋转后的坐标还原到原始位置
backupbxy[i][0] += minx;
backupbxy[i][1] += miny;
//判断旋转后是否出界
if (backupbxy[i][0]>X || backupbxy[i][0]<1)break;
if (backupbxy[i][1]>Y+2 || backupbxy[i][1]<1)break;
//判断是否有障碍物阻挡
x = backupbxy[i][0];
y = backupbxy[i][1];
if (tetris[y][x]>0 && tetris[y][x]<COL+1)break;
}
//如果不出界,清除原方块,求出旋转后方块
tmp = tetris[bxy[0][1]][bxy[0][0]];
if (i>=4){
for (k=0; k<4; k++) tetris[bxy[k][1]][bxy[k][0]] = 0;
for (k=0; k<4; k++) tetris[backupbxy[k][1]][backupbxy[k][0]] = tmp;
for (j=0; j<4; j++)
for (k=0; k<2; k++)
bxy[j][k] = backupbxy[j][k];
}
readonly = FALSE;
return 0;
}
//判断能否消行以及加分
int clear()
{
int i,j;
for (i=1; i<=Y; i++){
for (j=1; j<=X; j++){
if (tetris[i][j]==0 || tetris[i][j]>COL)break;
}
if (j > X){
downline(i);
score += 10;
level = score/SCOREPERLEVEL + 1;
speed = INITSPEED-TIMELEVEL*level;
}
}
return 0;
}
//从指定行开始,上方的行全部下移一行,参数为指定的行数:
int downline(int line)
{
int i,j;
for (i=line; i<Y; i++){
for (j=1; j<=X; j++){
if (tetris[i+1][j]<COL+1)tetris[i][j] = tetris[i+1][j];
else tetris[i][j] = 0;
}
}
clear();
return 0;
}
///