C语言俄罗斯方块Word文档下载推荐.docx
《C语言俄罗斯方块Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《C语言俄罗斯方块Word文档下载推荐.docx(18页珍藏版)》请在冰豆网上搜索。
/*voidDoUpShift(HDC);
*/voidDoRedirection(HDC);
voidDoAccelerate(HDC);
intcur_left,cur_top;
//记录方块当前的位置
intwidth_block,height_block;
//方块的宽带和高度
staticbyte*block=NULL;
//方块,方块为随机大小,采用动态分配内存方式,所以这里是指针变量
voidDrawPanel(HDChdc);
//绘制表格
voidRefreshPanel(HDChdc);
//刷新面板
boolIsTouchBottom(HDC);
//判断是否到达底部
voidClearRow(HDC);
//消行
byteg_panel[ROWS][COLS]={0};
intscore=0;
//分数
//升级所需分数值
#defineSCORE_LEVEL_INC80
//intmain(){
intWINAPIWinMain(HINSTANCEhInstance,
HINSTANCEhPrevInstance,
LPSTRlpCmdLine,
intnCmdShow){
//HINSTANCEhInstance=GetModuleHandle(NULL);
WNDCLASSwndClass;
MSGuMsg;
wndClass.style=CS_HREDRAW|CS_VREDRAW;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndClass.lpfnWndProc=WndProc;
wndClass.hInstance=hInstance;
wndClass.lpszClassName=TEXT("
Tetris"
);
wndClass.lpszMenuName=NULL;
if(!
RegisterClass(&
wndClass)){
printf("
RegisterClassOccurError!
"
exit
(1);
}
hWnd=CreateWindow(wndClass.lpszClassName,
TEXT("
TetrisDemo"
),
WS_OVERLAPPEDWINDOW,
0,0,0,0,
NULL,
hInstance,
NULL);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
while(GetMessage(&
uMsg,NULL,0,0)){
TranslateMessage(&
uMsg);
DispatchMessage(&
returnuMsg.wParam;
}
LRESULTCALLBACKWndProc(HWNDhwnd,UINTmessage,WPARAMwParam,LPARAMlParam){
HDChdc;
PAINTSTRUCTps;
//intx,y;
//在这个函数块中没有用到,其实
switch(message){
caseWM_CREATE:
MoveWindow(hwnd,400,10,CELL*COLS+8,CELL*COLS+32,FALSE);
//这里CELL*COLS+8表示的意义是窗口的宽,CELL*COLS+32表示的高;
该句补上宽和高
srand((unsignedint)time(NULL));
ExportBlock();
//根据上面的随机种子生成一个输出的俄罗斯方块(落下来的)
timer_id=SetTimer(hwnd,ID_TIMER,interval_base-level*interval_unit,NULL);
//参数2:
触发计时器的事件,参数3:
计时器的时间间隔
return0;
//既然有计时器,当然就要对计时器消息进行处理
caseWM_TIMER:
hdc=GetDC(hwnd);
DoDownShift(hdc);
//生成的方块下落
ReleaseDC(hwnd,hdc);
caseWM_KEYDOWN:
switch(wParam){
caseVK_LEFT:
//左方向键——左移?
if(!
isPause)DoLeftShift(hdc);
break;
caseVK_RIGHT:
isPause)DoRightShift(hdc);
//右方向键——右移?
caseVK_UP:
isPause)/*DoUpShift(hdc);
*/DoRedirection(hdc);
//转向?
caseVK_DOWN:
//DoDownShift(hdc);
isPause)DoAccelerate(hdc);
caseVK_SPACE:
isPause=/*true;
*/!
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);
}
caseWM_DESTROY:
if(block)free(block);
//block表示每次往下掉的方块
if(timer_id)KillTimer(hwnd,ID_TIMER);
PostQuitMessage(0);
caseWM_PAINT:
hdc=BeginPaint(hwnd,&
ps);
DrawPanel(hdc);
//绘制面板
RefreshPanel(hdc);
//刷新
EndPaint(hwnd,&
returnDefWindowProc(hwnd,message,wParam,lParam);
//下面,按照我们在WndProc()函数中需要用到的子函数来写出其定义
boolExportBlock(){//输出方块
intsel;
if(block){
free(block);
//释放之前分配的内存
block=NULL;
sel=rand()%7;
switch(sel){
case0:
//水平条
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;
//奇怪,作者的坐标系到底是怎样的观念,这里怎么用0-height_block,表示方块还未完全显示
cur_left=(COLS-width_block)/2;
break;
case1:
//三角
width_block=3;
height_block=2;
*(block+0)=0;
//可以理解为*(block+0*width_block+0)=0,即第一行的第一个方格,下面同理
*(block+2)=0;
//*(block+0*width_block+2)=0
//*(block+1*width_block+0)=1,第二行开始
*(block+4)=1;
//*(block+1*width_block+1)=1
*(block+5)=1;
//*(block+1*width_block+2)=1
case2:
//左横折
//可以理解为*(block+0*width_block+0)=1,下面同理|
*(block+1)=0;
//*(block+0*width_block+1)=0|||
//*(block+1*width_block+0)=1
case3:
//右横折
//可以理解为*(block+0*width_block+0)=0,下面同理 |
//*(block+0*width_block+1)=0| | |
case4:
//左闪电
//可以理解为*(block+0*width_block+0)=1,下面同理 | |
//*(block+0*width_block+1)=1 | |
*(block+3)=0;
//*(block+1*width_block+0)=0
case5:
//右闪电
//可以理解为*(block+0*width_block+0)=0,下面同理||
//*(block+0*width_block+1)=1
//*(block+0*width_block+2)=1||
*(block+5)=0;
//*(block+1*width_block+2)=0
case6:
//石头
width_block=2;
//可以理解为*(block+0*width_block+0)=1,下面同理
returnblock!
=NULL;
voidDoDownShift(HDChdc){//下移
if(NULL==block)return;
if(IsTouchBottom(hdc)){//到底部
//消行处理
ClearRow(hdc);
//输出下一个方块
cur_top++;
RefreshPanel(hdc);
voidDoLeftShift(HDChdc){//左移
intx,y;
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--;
voidDoRightShift(HDChdc){//右移
if(COLS-width_block==cur_left)return;
//方块完整显示前不能右移
for(x=width_block-1;
x>
=0;
x--){//从右边开始扫描,获取该行最右边的实心方格块
//判断当前方格在面板上右边一个方格是否为实心,是就代表不能再右移
if(g_panel[cur_top+y][cur_left+x+1])return;
//只判断最右边的一个实心方格
cur_left++;
voidDoRedirection(HDChdc){//改变方向
inti,j;
byte*temp=NULL;
//方块完整显示前不能转向
temp=(byte*)malloc(sizeof(byte)*width_block*height_block);
for(i=0;
i<
i++){
for(j=0;
j<
j++){
//temp[i][j]=block[height_block-j-1][i];
*(temp+i*height_block+j)=*(block+(height_block-j-1)*width_block+i);
//给方块重新定位
intincHeight=width_block-height_block;
intincWidth=height_block-width_block;
inttemp_cur_top=cur_top-incHeight/2;
inttemp_cur_left=cur_left-incWidth/2;
//system("
cls"
//printf("
temp_top=%d,temp_left=%d"
temp_cur_top,temp_cur_left);
//判断当前空间是否足够让方块改变方向
intmax_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;
max_len;
//转向所需的空间内有已被占用的实心方格存在,即转向失败
if(g_panel[temp_cur_top+i][temp_cur_left+j]){
free(temp);
return;
//把临时变量的值赋给block,只能赋值,而不能赋指针值
//block[i][j]=temp[i][j];
*(block+i*width_block+j)=*(temp+i*width_block+j);