`````````
学 院: 数计学院
班 级: 13级数媒班
学 号:
姓 名:
摘 要
……………………………………………………………………………………………………..
关键字:
目录
第一部分 设计总概..........................................................................................................
摘要…………………………………………………………………………………………………
一、设计目的..............................................................................................................
二、设计要求..............................................................................................................
三、设计内容..............................................................................................................
四、系统分析与设计...................................................................................................
第二部分 数据结构设计..................................................................................................
第三部分 功能实现与程序调试………………………………………………………………….
第四部分 完成设计..........................................................................................................
一、实习日记..............................................................................................................
二、实习总结..............................................................................................................
三、教师评语..............................................................................................................
四、程序使用说明书………………………………………………………………………….
第一部分 设计总概
一、设计目的
二、设计要求
三、设计内容
四、系统分析与设计
第二部分 数据结构设计
第三部分 功能实现与程序调试
第四部分 完成设计
一、实习日记:
二、实习总结:
………………………
三、教师评语:
设计成绩: 指导老师签名:
摘 要
使用C语言编写一个俄罗斯方块游戏系统,要求程序运行后有一个图形用户界面,实现各种方块的生产,包括形状和颜色等信息,完成左右下旋转的功能,在消行的同时分数加10,在点击暂停或者按下空格的时候暂停或开始游戏,最后结束游戏.
关键字:音乐、背景、按键控制、暂停、继续、停止,难度级别
第一部分 设计总概
一、 设计目的:
本课程设计是一个综合性的实践教学环节,目的在于促进学生复习和巩固计算机软件设计知识,加深对软件设计方法、软件设计技术和设计思想的理解,并能运用所学知识进行开发。希望通过本课程设计中简单系统的开发,使学生掌握软件设计的基本方法和基本流程,提高自己的综合应用能力。
二、设计要求
利用C++编写俄罗斯方块游戏,使俄罗斯游戏能够在Microsoft Visual C++6.0上运行该游戏。
二、 设计内容:俄罗斯方块
(1)游戏等级:游戏分为难中易三个等级,等级越高,方块下落速度越快;
(2)由方向键控制游戏:上键控制方块变形、下键控制方块下移并判断是否有消行、左键控制方块左移、右键控制方块右移;
(3)游戏积分:一次性消的行数越多加的分数越多,当达到一定分数自动提高一个游戏等级。
三、 系统分析与设计
1.程序功能模块:
2.程序流程图:
第二部分 数据结构设计
1.游戏需求
随机给出不同的形状(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型)下落填充给定的区域,若填满一条便消掉,记分,当达到一定的分数时,过关,每关方块下落的速度不同,若在游戏中各形状填满了给定区域,为输者。
2.游戏界面需求:
良好的用户界面,以键盘操作,有关数显示和分数显示。让方块在一定的区域内
运动和变形,并且显示下一个即将出现的方块。
3.游戏形状(方块)需求:
良好的方块形状设计,绘制七种常见的基本图形(长条形、Z字形、反Z形、田字形、7字形、反7形、T字型),各个方块要能实现它的变形,可设为顺时针或逆 时针变形,一般为逆时针。
第三部分 功能实现与程序调试
程序:
// testBlock.cpp : Defines the entry point for the application.
//
#define CreateWindow CreateWindowA
#include "stdafx.h"
#include "resource.h"
#include<mmsystem.h>//PlaySound函数的头文件
#pragma comment(lib, "WINMM.LIB")
#include "commctrl.h"
#pragma comment(lib, "comctl32.lib")
#include <windows.h>
#include <commctrl.h>
HMENU hMenu; //菜单句柄
#define IDM_NEW 40001
#define IDM_PAUSE 40002
//#define IDM_STOP 40003
#define IDM_HELP 40008
#define IDM_MUSIC 40010
#define IDM_LEFT 1001
#define IDM_RIGHT 1002
#define IDM_UP 1003
#define IDM_DOWN 1004
#define IDC_RADIO1 1005
#define IDC_RADIO2 1006
#define COLOR_BTNFACE 15
#define MAX_LOADSTRING 100
#define TIMER_DROP_ID 1
int c = 0,contin=1;
int cnext=0;
int ch1=0;
int ch2=0;
int ch3=1;
int music=0;
BOOL bMusicOn; //音乐开关
int iMusicBG; //背景音乐
canRotate( int rank);
BOOL CALLBACK MusicDlgProc(HWND,UINT,WPARAM,LPARAM);
void TetrisMusic(BOOL);
void MusicItem(int);
static TBBUTTON tbButtons[] =
{
{0,IDC_JIXU,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1},
{1,IDC_PAUSE,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1},
{2,IDM_STOP,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1},
{0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1},
{3,IDM_MUSIC,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1},
{4,IDM_HELP1,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1},
{0,0,TBSTATE_ENABLED,TBSTYLE_SEP,0,0,-1},
{5,IDM_ABOUT,TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0,-1},
}; //工具栏数据结构
struct Block{ POINT a; POINT b; POINT c; POINT d; }; //方块模型数据结构
static Block Tetris[7][4] =
{
//□□
//□□(1)
{
{{0,0},{0,1},{1,0},{1,1}}, {{0,0},{0,1},{1,0},{1,1}},
{{0,0},{0,1},{1,0},{1,1}}, {{0,0},{0,1},{1,0},{1,1}}
},
//□□
// □□(2)
{
{{0,0},{1,0},{1,1},{2,1}}, {{1,0},{1,1},{0,1},{0,2}},
{{0,0},{1,0},{1,1},{2,1}}, {{1,0},{1,1},{0,1},{0,2}}
},
// □□
//□□ (2)
{
{{1,0},{2,0},{0,1},{1,1}}, {{0,0},{0,1},{1,1},{1,2}},
{{1,0},{2,0},{0,1},{1,1}}, {{0,0},{0,1},{1,1},{1,2}}
},
//□□□□(2)
{
{{0,0},{1,0},{2,0},{3,0}}, {{1,0},{1,1},{1,2},{1,3}},
{{0,0},{1,0},{2,0},{3,0}}, {{1,0},{1,1},{1,2},{1,3}}
},
// □
//□□□(4)
{
{{1,0},{0,1},{1,1},{2,1}}, {{0,0},{0,1},{1,1},{0,2}},
{{0,0},{1,0},{2,0},{1,1}}, {{1,0},{0,1},{1,1},{1,2}}
},
//□
//□□□(4)
{
{{0,0},{0,1},{1,1},{2,1}}, {{0,0},{1,0},{0,1},{0,2}},
{{0,0},{1,0},{2,0},{2,1}}, {{1,0},{1,1},{0,2},{1,2}}
},
// □
//□□□(4)
{
{{2,0},{0,1},{1,1},{2,1}}, {{0,0},{0,1},{0,2},{1,2}},
{{0,0},{1,0},{2,0},{0,1}}, {{0,0},{1,0},{1,1},{1,2}}
}
}; //七种方块全部变形数据结构
int x = 4 ;//以方块为单位
int y = -1;
int nBlockAreaX=10;//背景窗口
int nBlockAreaY=30;
int BlockMatrix[19][10];
int nBlockKind = 0;
int nBlockColor = 0;
int nBlockState = 0;
int nBlockAreaXnext=220;//显示窗口
int nBlockAreaYnext=37;
int BlockMatrixnext[8][6];
int nBlockKindnext = 0;
int nBlockColornext = 0;
int nBlockStatenext = 0;
int gamescore=0;
BOOL BGame=FALSE;
BOOL bGOver=FALSE;
HWND hWnd;
HDC hdc;
HDC hMemDC = NULL;
HDC hWndDC = NULL;
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
HBITMAP bmp[999] = {0};
// 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);
void DrawTetris( HDC hdc, int offsetX/*0*/, int offsetY/*0*/, int rank/*no use*/ );
void Tools(HWND hWnd);
LoadImage();
void GameStart();
void DrawNext(HDC hdc);
void GameOver();
void DrawButton(LPARAM lParam);
LPARAM lParam;
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_TESTBLOCK, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
FILE *fp=NULL;////////////
char ch[50];
fp=fopen("test.txt","r");
fgets(ch,523,fp);
ch1=atoi(ch);
fclose(fp);////////
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_TESTBLOCK);
char fileName[100] = {0};
//res\\1.bmp
for (int i = 0; i < 9; i++ )
{
sprintf(fileName, "res\\%d.bmp", i+1);
bmp[i] = (HBITMAP)LoadImage(NULL, fileName,0,0,0,LR_LOADFROMFILE); //LOADIMAGEFROMFILE
}
for( i=0;i<=18;i++)
{
for(int j=0;j<=9;j++)
{
BlockMatrix[i][j]=-1;
}
}
for(int m=0;m<=5;m++)
{
for(int n=0;n<=5;n++)
{
BlockMatrixnext[m][n]=-1;
}
}//beijing
int a=1000;
SetTimer(hWnd,TIMER_DROP_ID,a,NULL);
hWndDC = GetDC(hWnd);
hMemDC = CreateCompatibleDC(NULL);
// Main message loop:
Tools(hWnd);
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
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_ICON1);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+2);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TESTBLOCK);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ICON1));
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 200, 350, 485, NULL, NULL, hInstance, NULL);//窗口大小设置
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
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_UP:
SendMessage(hWnd,WM_KEYDOWN,VK_UP,0);
SetFocus(hWnd);
break;
case IDM_DOWN:
SendMessage(hWnd,WM_KEYDOWN,VK_DOWN,0);
SetFocus(hWnd);
break;
case IDM_RIGHT:
SendMessage(hWnd,WM_KEYDOWN,VK_RIGHT,0);
SetFocus(hWnd);
break;
case IDM_LEFT:
SendMessage(hWnd,WM_KEYDOWN,VK_LEFT,0);
SetFocus(hWnd);
break;
case IDM_START:
{
InvalidateRect(hWnd,0,1);
GameStart();
}
break;
break;//开始按键
case IDC_PAUSE://暂停
{
BGame=FALSE;
MessageBox(NULL, "你好,游戏暂停", "暂停", MB_OK);
}
break;
case IDC_JIXU://继续
{
if(contin!=0)
BGame=TRUE;
}
break;
case IDM_STOP://停止
BGame=FALSE;
GameOver();
break;
case IDC_easy:
InvalidateRect(hWnd,0,0);
ch3=1;
MessageBox(NULL, "你好,你选择的难易程度为简单", "简单", MB_OK);
SetTimer(hWnd,TIMER_DROP_ID,1000,NULL);
break;
case IDC_normal:
InvalidateRect(hWnd,0,0);
ch3=2;
MessageBox(NULL, "你好,你选择的难易程度为一般", "一般", MB_OK);
SetTimer(hWnd,TIMER_DROP_ID,500,NULL);
break;
case IDC_difficult:
MessageBox(NULL, "你好,你选择的难易程度为困难", "困难", MB_OK);
ch3=3;
InvalidateRect(hWnd,0,0);
SetTimer(hWnd,TIMER_DROP_ID,100,NULL);
break;
case IDM_beijing:
{
SelectObject(hMemDC,bmp[8]);
BitBlt(hWndDC,0,20,2000,2000,hMemDC,0,0,SRCCOPY);
InvalidateRect(hWnd,0,0);//重绘
//InvalidateRect(hwnd, NULL, false);重画时不擦除背景
}
break;
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_HELP1), hWnd, (DLGPROC)About);
break;
case IDM_HELP1:
DialogBox(hInst, MAKEINTRESOURCE(IDD_help2), hWnd, (DLGPROC)About);
break;
case IDM_MUSIC:
DialogBox(hInst,MAKEINTRESOURCE(IDD_MUSIC),hWnd,MusicDlgProc);
break;
case IDM_music1:
MusicItem(IDM_music1);
break;
case IDM_music2:
MusicItem(IDM_music2);
break;
case IDM_musicstop:
MusicItem(IDM_musicstop);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
RECT rt;
GetClientRect(hWnd, &rt);
for(int i=0;i<=18;i++)
{
for(int j=0;j<=9;j++)
{
if(BlockMatrix[i][j]==-1)
{
PatBlt(hdc,nBlockAreaX+j*20,nBlockAreaY+i*20,20,20,BLACKNESS);
}
else
{
SelectObject(hMemDC,bmp[BlockMatrix[i][j]]);
BitBlt(hdc,nBlockAreaX+j*20,nBlockAreaY+i*20,20,20,hMemDC,0,0,SRCCOPY);
}
}
}
//InvalidateRect(hWnd,0,0);
for(int m=0;m<=5;m++)
{
for(int n=0;n<=5;n++)
{
if(BlockMatrixnext[m][n]==-1)
{
PatBlt(hdc,nBlockAreaXnext+n*20,nBlockAreaYnext+m*20,20,20,BLACKNESS);
}
else
{
SelectObject(hMemDC,bmp[BlockMatrixnext[m][n]]);
BitBlt(hdc,nBlockAreaXnext+n*20,nBlockAreaYnext+m*20,20,20,hMemDC,0,0,SRCCOPY);
}
}
}
DrawTetris(hWndDC, 0, 0, 0);
DrawNext( hdc);
RECT rtTxt;
TCHAR scoreTxt[100];
sprintf(scoreTxt, " 得 分 : %d", gamescore);
rtTxt.top = 200;
rtTxt.left = 220;
rtTxt.right = rtTxt.left+200;
rtTxt.bottom = rtTxt.top+50;
DrawText(hdc, scoreTxt, strlen(scoreTxt), &rtTxt, DT_LEFT);
RECT rtTxt1;
TCHAR maxscore[100];/////////////////////////////////////////
sprintf(maxscore, " 最 高 分 : %d", ch1);
rtTxt1.top=240;
rtTxt1.left=220;
rtTxt1.right=rtTxt1.left+300;
rtTxt1.bottom=rtTxt1.top+100;
DrawText(hdc, maxscore, strlen(maxscore), &rtTxt1, DT_LEFT);
RECT rtTxt2;
TCHAR eaayORdifficult[100];
sprintf(eaayORdifficult, "难易级别 : %d", ch3);
rtTxt2.top = 280;
rtTxt2.left = 220;
rtTxt2.right = rtTxt2.left+200;
rtTxt2.bottom = rtTxt2.top+50;
DrawText(hdc, eaayORdifficult, strlen(eaayORdifficult), &rtTxt2, DT_LEFT);
EndPaint(hWnd, &ps);
}
break;//计算分数
case WM_DRAWITEM:
DrawButton(lParam); //绘制方向按钮
return TRUE;
case WM_LBUTTONDOWN:
{
}
break;
case WM_TIMER:
{
DrawTetris(hWndDC, 0, 1, 0);
}break;
case WM_KEYDOWN:
{
int virtual_code=(int)wParam;
int key_state=(int)lParam;
switch(virtual_code)
{
case VK_RIGHT:
{DrawTetris(hWndDC, 1, 0, 0);}
break;
case VK_LEFT:
{
DrawTetris(hWndDC, -1, 0, 0);
}
break;
case VK_UP:
if(canRotate(1))
{
DrawTetris( hWndDC,0,0,1);
}
break;
case VK_DOWN:
{DrawTetris(hWndDC, 0, 1, 0);}
break;
default: break;
}
}
break;
case WM_DESTROY:
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)
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
BOOL CALLBACK MusicDlgProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)
{
switch ( message )
{
case WM_INITDIALOG:
if( iMusicBG == IDR_WAVE1 ) CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO3,IDC_RADIO1);
if( iMusicBG == IDR_WAVE2 ) CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO3,IDC_RADIO2);
if( !bMusicOn ) CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO3,IDC_RADIO3);
return TRUE;
case WM_COMMAND :
switch ( LOWORD(wParam) )
{
case IDC_RADIO1:
CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO3,IDC_RADIO1);
break;
case IDC_RADIO2:
CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO3,IDC_RADIO2);
break;
case IDC_RADIO3:
CheckRadioButton(hDlg,IDC_RADIO1,IDC_RADIO3,IDC_RADIO3);
break;
case IDOK:
if ( IsDlgButtonChecked(hDlg,IDC_RADIO1) == BST_CHECKED )
{
bMusicOn = TRUE;
iMusicBG = IDR_WAVE1;
MusicItem(IDM_music1);
if ( BGame ) TetrisMusic(TRUE);
}
if ( IsDlgButtonChecked(hDlg,IDC_RADIO2) == BST_CHECKED )
{
bMusicOn = TRUE;
iMusicBG = IDR_WAVE2;
MusicItem(IDM_music2);
if ( BGame ) TetrisMusic(TRUE);
}
if ( IsDlgButtonChecked(hDlg,IDC_RADIO3) == BST_CHECKED )
{
bMusicOn = FALSE;
MusicItem(IDM_musicstop);
TetrisMusic(FALSE);
}
EndDialog(hDlg,0);
break;
case IDCANCEL:
EndDialog(hDlg,0);
break;
}
break;
}
return FALSE;
}
//音乐菜单处理
void MusicItem(int iCheckID)
{
CheckMenuRadioItem(hMenu,IDM_music1,IDM_musicstop,iCheckID,MF_BYCOMMAND);
if ( iCheckID == IDM_music1 )
{
bMusicOn = TRUE;
iMusicBG = IDR_WAVE1;
if ( BGame ) TetrisMusic(TRUE);
}else if ( iCheckID == IDM_music2 )
{
bMusicOn = TRUE;
iMusicBG = IDR_WAVE2;
if ( BGame ) TetrisMusic(TRUE);
}
else
{
bMusicOn = FALSE;
TetrisMusic(FALSE);
}
return;
}
//背景音乐
void TetrisMusic(BOOL start)
{
if ( start && bMusicOn && !bGOver )
PlaySound(MAKEINTRESOURCE(iMusicBG),NULL,SND_RESOURCE|SND_LOOP|SND_ASYNC);
else
PlaySound(NULL,NULL,NULL);
return;
}
BOOL clear( )
{
int count=0;
for(int i=18;i>=0;i--)
{
for(int j=0;j<10;j++)
{
if(BlockMatrix[i][j]==-1)
break;
}
if(j==10)
{
count++;
for(int k=i-1;k>=0;k--)
{
for(int m=0;m<10;m++)
{
BlockMatrix[k+1][m]=BlockMatrix[k][m];
}
}
i++;
if(gamescore>=ch1)
ch1=gamescore;
if(gamescore>450)
{
ch3=3;
SetTimer(hWnd,TIMER_DROP_ID,100,NULL);
}
else if(gamescore<=450&&gamescore>300)
{
ch2=2;
if(ch2>=ch3)
{
ch3=ch2;
SetTimer(hWnd,TIMER_DROP_ID,500,NULL);
}
}
}
}
if(count==1)
{
gamescore+=10;
}
if(count==2)
{
gamescore+=30;
}
if(count==3)
{
gamescore+=50;
}
if(count==4)
{
gamescore+=80;
}
InvalidateRect(hWnd,0,0);
return true;
}
void GameStart()
{
BGame=TRUE;
gamescore=0;
FILE *fp=NULL;
char ch[50];
fp=fopen("test.txt","r");
fgets(ch,523,fp);
ch1=atoi(ch);
fclose(fp);
contin=1;
for(int i=0;i<=18;i++)
{
for(int j=0;j<=9;j++)
{
BlockMatrix[i][j]=-1;
}
}
srand(GetTickCount());
nBlockKind=nBlockKindnext;
nBlockState=nBlockStatenext;
c=rand()%7;
nBlockKindnext=rand()%7;
nBlockStatenext=rand()%4;
cnext=rand()%7;
x = 4;
y = -1;
}
BOOL DownCheckCollideBlock(int offsetX, int offsetY, int rank)
{
if(y==-1)
{
return FALSE;
}
if((BlockMatrix[offsetY+y+Tetris[nBlockKind][nBlockState].a.y][x+Tetris[nBlockKind][nBlockState].a.x]!=-1)
||(BlockMatrix[offsetY+y+Tetris[nBlockKind][nBlockState].b.y][x+Tetris[nBlockKind][nBlockState].b.x]!=-1)
||(BlockMatrix[offsetY+y+Tetris[nBlockKind][nBlockState].c.y][x+Tetris[nBlockKind][nBlockState].c.x]!=-1)
||(BlockMatrix[offsetY+y+Tetris[nBlockKind][nBlockState].d.y][x+Tetris[nBlockKind][nBlockState].d.x]!=-1))
{
return TRUE;
}
return FALSE;
}
BOOL LeftOrRightCheckCollideBlock(int offsetX, int offsetY, int rank)
{
if(y==-1)
{
return FALSE;
}
if((BlockMatrix[y+Tetris[nBlockKind][nBlockState].a.y][offsetX+x+Tetris[nBlockKind][nBlockState].a.x]!=-1)
||(BlockMatrix[y+Tetris[nBlockKind][nBlockState].b.y][offsetX+x+Tetris[nBlockKind][nBlockState].b.x]!=-1)
||(BlockMatrix[y+Tetris[nBlockKind][nBlockState].c.y][offsetX+x+Tetris[nBlockKind][nBlockState].c.x]!=-1)
||(BlockMatrix[y+Tetris[nBlockKind][nBlockState].d.y][offsetX+x+Tetris[nBlockKind][nBlockState].d.x]!=-1))
{
return TRUE;
}
return FALSE;
}
BOOL canRotate( int rank)//旋转
{
if(rank==0)
{
return FALSE;
}
int tempState = (nBlockState+1)%4;
if((BlockMatrix[y+Tetris[nBlockKind][tempState].a.y][x+Tetris[nBlockKind][tempState].a.x]!=-1)
|| (BlockMatrix[y+Tetris[nBlockKind][tempState].b.y][x+Tetris[nBlockKind][tempState].b.x]!=-1)
|| (BlockMatrix[y+Tetris[nBlockKind][tempState].c.y][x+Tetris[nBlockKind][tempState].c.x]!=-1)
|| (BlockMatrix[y+Tetris[nBlockKind][tempState].d.y][x+Tetris[nBlockKind][tempState].d.x]!=-1)
||(y+Tetris[nBlockKind][tempState].a.y>18 )
|| (y+Tetris[nBlockKind][tempState].b.y>18 )
||(y+Tetris[nBlockKind][tempState].c.y>18 )
||(y+Tetris[nBlockKind][tempState].d.y>18 )
||(x+Tetris[nBlockKind][tempState].a.x<0 || x+Tetris[nBlockKind][tempState].a.x>9)
||(x+Tetris[nBlockKind][tempState].b.x<0 || x+Tetris[nBlockKind][tempState].b.x>9)
||(x+Tetris[nBlockKind][tempState].c.x<0 || x+Tetris[nBlockKind][tempState].c.x>9)
||(x+Tetris[nBlockKind][tempState].d.x<0 || x+Tetris[nBlockKind][tempState].d.x>9))
{
return FALSE;
}
return TRUE;
}
void DrawTetris( HDC hdc, int offsetX, int offsetY, int rank )
{
if(!BGame)
{
return;
}
int iX=0;
int iY=0;
if ((y+Tetris[nBlockKind][nBlockState].a.y+offsetY>18 )
|| (y+Tetris[nBlockKind][nBlockState].b.y+offsetY>18 )
||(y+Tetris[nBlockKind][nBlockState].c.y+offsetY>18 )
||(y+Tetris[nBlockKind][nBlockState].d.y+offsetY>18 )
||DownCheckCollideBlock(offsetX,offsetY,rank)
)
{
BlockMatrix[y+Tetris[nBlockKind][nBlockState].a.y][x+Tetris[nBlockKind][nBlockState].a.x] = c;//c是步骤1定义的变量,表示绘制背景时使用的图片下标。
BlockMatrix[y+Tetris[nBlockKind][nBlockState].b.y][x+Tetris[nBlockKind][nBlockState].b.x] = c;
BlockMatrix[y+Tetris[nBlockKind][nBlockState].c.y][x+Tetris[nBlockKind][nBlockState].c.x] = c;
BlockMatrix[y+Tetris[nBlockKind][nBlockState].d.y][x+Tetris[nBlockKind][nBlockState].d.x] = c;
clear();
if(y==0)
{
if(gamescore>=ch1)
{
FILE *fp=NULL;
fp=fopen("test.txt","w+");
fprintf(fp,"%d",gamescore);
fclose(fp);
}
BGame=FALSE;
//设置变量为0;
contin=0;
MessageBox(hWnd,"游戏结束","提示:",MB_OK);
}
nBlockKind=nBlockKindnext;
nBlockState=nBlockStatenext;
c=cnext;
nBlockKindnext=rand()%7;
nBlockStatenext=rand()%4;
cnext=rand()%7;
x = 4;
y = -1;
return;
}
if((x+Tetris[nBlockKind][nBlockState].a.x+offsetX<0 || x+Tetris[nBlockKind][nBlockState].a.x+offsetX>9)
||(x+Tetris[nBlockKind][nBlockState].b.x+offsetX<0 || x+Tetris[nBlockKind][nBlockState].b.x+offsetX>9)
||(x+Tetris[nBlockKind][nBlockState].c.x+offsetX<0 || x+Tetris[nBlockKind][nBlockState].c.x+offsetX>9)
||(x+Tetris[nBlockKind][nBlockState].d.x+offsetX<0 || x+Tetris[nBlockKind][nBlockState].d.x+offsetX>9 )
||LeftOrRightCheckCollideBlock(offsetX,offsetY,rank))
{
return;
}
if(offsetY+y<0)
{
return;
}
SelectObject(hMemDC,bmp[c]);
if((offsetX!=0||offsetY!=0||rank!=0)&& (y!=-1))
{
iX=x+Tetris[nBlockKind][nBlockState].a.x;
iY=y+Tetris[nBlockKind][nBlockState].a.y;
PatBlt(hdc,nBlockAreaX+iX*20,nBlockAreaY+iY*20,20,20,BLACKNESS);
iX=x+Tetris[nBlockKind][nBlockState].b.x;
iY=y+Tetris[nBlockKind][nBlockState].b.y;
PatBlt(hdc,nBlockAreaX+iX*20,nBlockAreaY+iY*20,20,20,BLACKNESS);
iX=x+Tetris[nBlockKind][nBlockState].c.x;
iY=y+Tetris[nBlockKind][nBlockState].c.y;
PatBlt(hdc,nBlockAreaX+iX*20,nBlockAreaY+iY*20,20,20,BLACKNESS);
iX=x+Tetris[nBlockKind][nBlockState].d.x;
iY=y+Tetris[nBlockKind][nBlockState].d.y;
PatBlt(hdc,nBlockAreaX+iX*20,nBlockAreaY+iY*20,20,20,BLACKNESS);
}
if(rank!=0)
{
nBlockState=(nBlockState+1)%4;
}
SelectObject(hMemDC,bmp[c]);
iX=x+Tetris[nBlockKind][nBlockState].a.x;
iY=y+Tetris[nBlockKind][nBlockState].a.y;
BitBlt(hdc,nBlockAreaX+iX*20+offsetX*20,nBlockAreaY+iY*20+offsetY*20,20,20,hMemDC,0,0,SRCCOPY);
iX=x+Tetris[nBlockKind][nBlockState].b.x;
iY=y+Tetris[nBlockKind][nBlockState].b.y;
BitBlt(hdc,nBlockAreaX+iX*20+offsetX*20,nBlockAreaY+iY*20+offsetY*20,20,20,hMemDC,0,0,SRCCOPY);
iX=x+Tetris[nBlockKind][nBlockState].c.x;
iY=y+Tetris[nBlockKind][nBlockState].c.y;
BitBlt(hdc,nBlockAreaX+iX*20+offsetX*20,nBlockAreaY+iY*20+offsetY*20,20,20,hMemDC,0,0,SRCCOPY);
iX=x+Tetris[nBlockKind][nBlockState].d.x;
iY=y+Tetris[nBlockKind][nBlockState].d.y;
BitBlt(hdc,nBlockAreaX+iX*20+offsetX*20,nBlockAreaY+iY*20+offsetY*20,20,20,hMemDC,0,0,SRCCOPY);
x=x+offsetX;
y=y+offsetY;
}
void DrawNext(HDC hdc)
{
int iX, iY;
SelectObject(hMemDC,bmp[cnext]);
iX = 1 + Tetris[nBlockKindnext][nBlockStatenext].a.x;
iY = 1 + Tetris[nBlockKindnext][nBlockStatenext].a.y;
BitBlt(hdc,nBlockAreaXnext+iX*20,nBlockAreaYnext+iY*20,20,20,hMemDC,0,0,SRCCOPY);
iX = 1 + Tetris[nBlockKindnext][nBlockStatenext].b.x;
iY = 1 + Tetris[nBlockKindnext][nBlockStatenext].b.y;
BitBlt(hdc,nBlockAreaXnext+iX*20,nBlockAreaYnext+iY*20,20,20,hMemDC,0,0,SRCCOPY);
iX = 1 + Tetris[nBlockKindnext][nBlockStatenext].c.x;
iY = 1 + Tetris[nBlockKindnext][nBlockStatenext].c.y;
BitBlt(hdc,nBlockAreaXnext+iX*20,nBlockAreaYnext+iY*20,20,20,hMemDC,0,0,SRCCOPY);
iX = 1 + Tetris[nBlockKindnext][nBlockStatenext].d.x;
iY = 1 + Tetris[nBlockKindnext][nBlockStatenext].d.y;
BitBlt(hdc,nBlockAreaXnext+iX*20,nBlockAreaYnext+iY*20,20,20,hMemDC,0,0,SRCCOPY);
return;
}
void GameOver()
{
InvalidateRect(hWnd,0,0);
for(int i=0;i<=18;i++)
{
for(int j=0;j<=9;j++)
{
BlockMatrix[i][j]=-1;
}
}
BGame=false;
BOOL bGOver=true;
return;
}
void DrawButton(LPARAM lParam)
{
HDC hdc;
LPDRAWITEMSTRUCT pdis;
HPEN hpen;
pdis = (LPDRAWITEMSTRUCT)lParam; //包含自绘信息的结构体
hdc = pdis->hDC;
hpen = CreatePen(PS_SOLID,1,RGB(0,0,128));
SelectObject(hdc,hpen);
switch ( pdis->CtlID )
{
case IDM_UP:
//FillRect(pdis->hDC,&pdis->rcItem,(HBRUSH)(COLOR_BTNFACE+1));
SendMessage(pdis->hwndItem,WM_ERASEBKGND,(WPARAM)pdis->hDC,NULL);
if ( pdis->itemState & ODS_SELECTED )
{
MoveToEx(hdc,13,1,NULL);
LineTo(hdc,1,25);
LineTo(hdc,25,25);
LineTo(hdc,13,1);
MoveToEx(hdc,12,3,NULL);
LineTo(hdc,2,24);
}
else
{
MoveToEx(hdc,12,1,NULL);
LineTo(hdc,1,24);
LineTo(hdc,24,24);
LineTo(hdc,12,1);
MoveToEx(hdc,13,2,NULL);
LineTo(hdc,25,25);
LineTo(hdc,2,25);
}
break;
case IDM_DOWN:
//FillRect(pdis->hDC,&pdis->rcItem,(HBRUSH)(COLOR_BTNFACE+1));
SendMessage(pdis->hwndItem,WM_ERASEBKGND,(WPARAM)pdis->hDC,NULL);
if ( pdis->itemState & ODS_SELECTED )
{
MoveToEx(hdc,1,1,NULL);
LineTo(hdc,13,25);
LineTo(hdc,25,1);
LineTo(hdc,1,1);
MoveToEx(hdc,1,2,NULL);
LineTo(hdc,24,2);
}
else
{
MoveToEx(hdc,1,1,NULL);
LineTo(hdc,13,24);
LineTo(hdc,24,1);
LineTo(hdc,1,1);
MoveToEx(hdc,25,2,NULL);
LineTo(hdc,13,25);
LineTo(hdc,1,2);
}
break;
case IDM_LEFT:
//FillRect(pdis->hDC,&pdis->rcItem,(HBRUSH)(COLOR_BTNFACE+1));
SendMessage(pdis->hwndItem,WM_ERASEBKGND,(WPARAM)pdis->hDC,NULL);
if ( pdis->itemState & ODS_SELECTED )
{
MoveToEx(hdc,1,13,NULL);
LineTo(hdc,25,25);
LineTo(hdc,25,1);
LineTo(hdc,1,13);
MoveToEx(hdc,2,13,NULL);
LineTo(hdc,24,2);
}
else
{
MoveToEx(hdc,1,12,NULL);
LineTo(hdc,24,23);
LineTo(hdc,24,1);
LineTo(hdc,1,12);
MoveToEx(hdc,1,13,NULL);
LineTo(hdc,25,25);
LineTo(hdc,25,1);
}
break;
case IDM_RIGHT:
//FillRect(pdis->hDC,&pdis->rcItem,(HBRUSH)(COLOR_BTNFACE+1));
SendMessage(pdis->hwndItem,WM_ERASEBKGND,(WPARAM)pdis->hDC,NULL);
if ( pdis->itemState & ODS_SELECTED )
{
MoveToEx(hdc,1,1,NULL);
LineTo(hdc,1,25);
LineTo(hdc,25,12);
LineTo(hdc,1,1);
MoveToEx(hdc,2,24,NULL);
LineTo(hdc,2,2);
LineTo(hdc,24,13);
}
else
{
MoveToEx(hdc,1,1,NULL);
LineTo(hdc,1,24);
LineTo(hdc,24,12);
LineTo(hdc,1,1);
MoveToEx(hdc,1,25,NULL);
LineTo(hdc,25,13);
}
break;
}
DeleteObject(hpen);
return;
}
void Tools(HWND hWnd)
{
CreateToolbarEx(
hWnd, //hwnd 父窗口句柄
WS_VISIBLE|WS_CHILD|TBSTYLE_FLAT|TBSTYLE_TOOLTIPS|CCS_NODIVIDER, //ws 工具栏风格
IDR_TOOLBAR1, //wID 工具栏的子窗口ID
6, //nBitmaps 位图中包含多少个按钮小图标
hInst, //hBMInst 包含位图资源的模块句柄
IDB_BITMAP1, //wBMID 位图资源ID
tbButtons, //lpButtons
8, //iNumButtons 按钮总数
16, //dxButton 单个按钮宽度
16, //dyButton 单个按钮高度
16, //dxBitmap 单个按钮小图标的宽度
16, //dyBitmap 单个按钮小图标的高度
sizeof(TBBUTTON)); //uStructSize
CreateWindow(
TEXT("button"),
NULL,
WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,
280,340,
26,26,
hWnd,
(HMENU)IDM_UP,
hInst,
NULL);
//方向键 上
CreateWindow(
TEXT("button"),
NULL,
WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,
280,340,
26,26,
hWnd,
(HMENU)IDM_UP,
hInst,
NULL);
//方向键 下
CreateWindow(
TEXT("button"),
NULL,
WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,
280,370,
26,26,
hWnd,
(HMENU)IDM_DOWN,
hInst,
NULL);
//方向键 左
CreateWindow(
TEXT("button"),
NULL,
WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,
253,355,
26,26,
hWnd,
(HMENU)IDM_LEFT,
hInst,
NULL);
//方向键 右
CreateWindow(
TEXT("button"),
NULL,
WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,
307,355,
26,26,
hWnd,
(HMENU)IDM_RIGHT,
hInst,
NULL);
//工具栏下的黑线1
CreateWindow(
TEXT("static"), //lpClassName 类名
NULL, //lpWindowName 标题
WS_CHILD|WS_VISIBLE|SS_BLACKFRAME,
1,24,
358,1,
hWnd, //hWndParent
NULL, //hMenu
hInst,
NULL); //lpParam 额外的参数
CreateWindow(
TEXT("static"),
NULL,
WS_CHILD|WS_VISIBLE|SS_GRAYFRAME,
218,35,
125,125,
hWnd,
NULL,
hInst,
NULL);
//得分边框
CreateWindow(
TEXT("static"),
NULL,
WS_CHILD|WS_VISIBLE|SS_GRAYFRAME,
300,200,
50,16,
hWnd,
NULL,
hInst,
NULL);
//最高得分边框
CreateWindow(
TEXT("static"),
NULL,
WS_CHILD|WS_VISIBLE|SS_GRAYFRAME,
300,240,
50,18,
hWnd,
NULL,
hInst,
NULL);
//难以级别边框
CreateWindow(
TEXT("static"),
NULL,
WS_CHILD|WS_VISIBLE|SS_GRAYFRAME,
300,280,
50,18,
hWnd,
NULL,
hInst,
NULL);
CreateWindow(
TEXT("static"),
TEXT(""),
WS_CHILD|WS_VISIBLE|SS_LEFT|WS_DISABLED,
0,415,
500,18,
hWnd,
NULL,
hInst,
NULL);
//游戏区的外框
CreateWindow(
TEXT("static"),
NULL,
WS_CHILD|WS_VISIBLE|SS_GRAYFRAME,
7,28,
206,386,
hWnd,
NULL,
hInst,
NULL);
//背景图片
//hWnd:要更新的客户区所在的窗体的句柄。如果为NULL,则系统将在函数返回前重新绘制所有的窗口,
//然后发送 WM_ERASEBKGND 和 WM_NCPAINT 给窗口过程处理函数。
//lpRect:无效区域的矩形代表,它是一个结构体指针,存放着矩形的大小。
//如果为NULL,全部的窗口客户区域将被增加到更新区域中。
//bErase:指出无效矩形被标记为有效后,是否重画该区域,重画时用预先定义好的画刷。当指定TRUE时需要重画。
}
2.运行程序:
完成设计
实习总结:
上个学期学习C++的时候,主要是局限于读课本,记住课本上的一些知识和概念,但很少自己亲自动手去编写代码,总是眼高手低,当真正的去编写这个俄罗斯游戏的时候就体会到编写代码真的好难,尤其是刚开始的想的时候,根本不知道如何下手。后来通过上网查询和请教一些编程比较好的同学后才有了一个基本的思路,自己又重新翻阅了一下课本,将课本上的知识又重新细致的复习了一遍,最终借助于网络和同学的帮助完成了这个实验。通过这个实验发现自己在编程方面还有很大的欠缺,编程能力很差劲,不过通过这个实验,也让我对上学期学习的C++知识有了一个很好很全面的复习,这是这个实验带给我最大的收获。必须要亲自动手多写,多看代码才能真正的学好C++。
一、 教师评语: