分享
 
 
 

一个俄罗斯方块游戏源程序

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

文件一

///////////////////[stdafx.cpp]/////////////////////////

// stdafx.cpp : source file that includes just the standard includes

// ToyBricks.pch will be the pre-compiled header

// stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H

// and not in this fil

文件二

//////////////////////////////////////[stdafx.h]//////////////////////////////////////////

// stdafx.h : include file for standard system include files,

// or project specific include files that are used frequently, but

// are changed infrequently

//

#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)

#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers

#include <windows.h>

// TODO: reference additional headers your program requires here

//{{AFX_INSERT_LOCATION}}

// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)

文件三

/////////////////////////////////[game.cpp]////////////////////////////////////////////////////

// ToyBricks.cpp : Defines the entry point for the application.

//

#include "StdAfx.h"

/*******************************************************/

#include <windows.h> //windows.h文件中包含应用程序中所需的数据类型和数据结构的定义

#include <time.h> //包含SetTimer()、KillTimer()等关于定时器的函数

#include <stdlib.h>

#define CELL 15 // 【方格】的边长(pix)

#define W 20 // 游戏区宽(12个【方格】边长,8个格子用来绘制"下一个"方块)

#define H 26 // 游戏区高(26个【方格】边长)

#define MS_NEWBLOCK WM_USER+1 // 消息ID,产生新的【方块】

#define MS_DRAW WM_USER+2 // 消息ID,用来画【方块】

#define MS_NEXTBLOCK WM_USER+3 //消息ID,用来显示下一个【俄罗斯方块】形状

//------------------------窗口函数的说明------------------------

LRESULT CALLBACK WndProc ( HWND, UINT, WPARAM, LPARAM);

//---------------------------------------------------------------

int WINAPI WinMain ( HINSTANCE hInstance,

HINSTANCE hPrevInstance,

PSTR szCmdLine,

int iCmdShow)

{

static char AppName[]="ToyBrick"; //窗口类名

HWND hwnd;

MSG msg; //消息结构

WNDCLASSEX wndclass; //窗口类

int iScreenWide; //定义一个整型变量来取得窗口的宽度

wndclass.cbSize = sizeof(wndclass);

wndclass.style = CS_HREDRAW|CS_VREDRAW;//窗口类型

//CS_HREDRAW :Redraws the entire window if a movement or size

// adjustment changes the width of the client area.

//CS_VREDRAW :Redraws the entire window if a movement or size

// adjustment changes the height of the client area.

wndclass.lpfnWndProc = WndProc; //窗口处理函数为 WndProc

wndclass.cbClsExtra = 0; //窗口类无扩展

wndclass.cbWndExtra = 0; //窗口实例无扩展

wndclass.hInstance = hInstance; //当前实例句柄

wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); //默认图标

wndclass.hCursor = LoadCursor (NULL,IDC_ARROW); //箭头光标

wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH); //背景为黑色

wndclass.lpszMenuName = NULL; //窗口中无菜单

wndclass.lpszClassName = AppName; //类名为"ToyBrick"

wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION);

//----------------------------------窗口类的注册-----------------------------------------

if(!RegisterClassEx (&wndclass)) //如果注册失败则发出警报声音,返回FALSE

{

MessageBeep(0);

return FALSE;

}

// 获取显示器分辨率的X值iScreenWide,将程序窗口置于屏幕中央

iScreenWide=GetSystemMetrics (SM_CXFULLSCREEN);

hwnd =CreateWindow (

AppName, //窗口类名

"俄罗斯方块模拟项目(软件学院.钱彦江)", //窗口实例的标题名

WS_MINIMIZEBOX|WS_SYSMENU , //窗口的风格

iScreenWide/2-W*CELL/2, //窗口左上角横坐标(X)

CELL, //窗口左上角纵坐标(Y)

W*CELL, //窗口的宽

H*CELL, //窗口的高

NULL, //窗口无父窗口

NULL, //窗口无主菜单

hInstance, //创建此窗口的应用程序的当前句柄

NULL //不使用该值

);

if(!hwnd) return FALSE;

//显示窗口

ShowWindow (hwnd,iCmdShow);

//绘制用户区

UpdateWindow (hwnd);

MessageBox(hwnd," 开始游戏\n\n_软件学院模拟项目","开始",MB_OK);

SendMessage(hwnd,MS_NEWBLOCK,0,0);

SetTimer (hwnd, 1, 500,NULL);

//消息循环

while (GetMessage (&msg, NULL, 0, 0))

{

TranslateMessage (&msg);

DispatchMessage (&msg);

}

//消息循环结束即程序终止时将消息返回系统

return msg.wParam;

}

// 函数DrawRact: 画【正方形】----- (□)

// 参数: 设备环境句柄和【正方形】的四角坐标

void DrawRect (HDC hdc, int l, int t, int r, int b)

{

MoveToEx (hdc, l, t, NULL); //将光标移动到(l,t)

LineTo (hdc, r, t);

LineTo (hdc, r, b);

LineTo (hdc, l, b);

LineTo (hdc, l,t);

}

// 函数DrawCell: 画【方格】-----(红色■)

// 参数: 设备环境句柄和【方格】的四角坐标

void DrawCell (HDC hdc, int l, int t, int r, int b)

{

HBRUSH hbrush;

hbrush=CreateSolidBrush(RGB(255,0,0)); // 红色画刷

SelectObject(hdc,hbrush);

Rectangle(hdc,l, t, r, b);

DeleteObject (hbrush);

}

//绘出游戏区域的方格,其中包括"游戏空间"和"显示下一个【方块】空间"

//此函数包含在Cover函数中。参数:设备环境句柄

void DrawGamePlace(HDC hdc)

{

int i,j;

HPEN hpen1,hpen2;

hpen1=CreatePen(PS_SOLID,1,RGB(0,255,0));

hpen2=CreatePen(PS_DASHDOTDOT,3,RGB(0,0,255));

//绘制分割线

SelectObject(hdc,hpen2);

MoveToEx(hdc,(W-8)*CELL,0,NULL);

LineTo(hdc,(W-8)*CELL,H*CELL);

//绘制游戏区域方格线(绿色)

SelectObject(hdc,hpen1);

for (i=1; i<H-1; i++)

for(j=1; j<=W-8; j++)

DrawRect (hdc, (j-1)*CELL, (i-1)*CELL, j*CELL, i*CELL);

//绘制"显示下一个"区域的方格线

for(i=5;i<9;i++) // 5≤i≤8

for(j=W-5;j<W-1;j++) // 15≤j≤18

DrawRect (hdc, (j-1)*CELL, (i-1)*CELL, j*CELL, i*CELL);

DeleteObject(hpen2);

DeleteObject(hpen1);

}

// 函数DrawBlock: 画游戏中出现的【俄罗斯方块】

// 参数: 设备环境句柄和【俄罗斯方块】中四个【方格】在游戏区域中的位置

// 每个【俄罗斯方块】由四个【方格】组成7种不同的形状

void DrawBlock (HDC hdc, int block[4][2])

{

int i;

for(i=0; i<4; i++)

DrawCell (hdc, (block[i][0]-1)*CELL, (block[i][1]-1)*CELL, //....

block[i][0]*CELL, block[i][1]*CELL);

}

// 函数Cover: 清除原来位置的【俄罗斯方块】

// 参数: 设备环境句柄和待清除的【俄罗斯方块】

//作用(1) 清除【俄罗斯方块】即在该【俄罗斯方块】的每个【方格】处画一个正方形的白块

// (2) 重新绘制游戏区域的方格

void Cover (HDC hdc, int org[4][2])

{

int i;

HBRUSH hbrush;

//重新绘制游戏区域

DrawGamePlace(hdc);

hbrush=(HBRUSH)GetStockObject (WHITE_BRUSH);

SelectObject (hdc,hbrush );

for(i=0; i<4; i++)

Rectangle ( hdc, (org[i][0]-1)*CELL, (org[i][1]-1)*CELL, //.....

org[i][0]*CELL, org[i][1]*CELL);

DeleteObject(hbrush);

}

//-------------------窗口过程函数WndProc-----------------------------

LRESULT CALLBACK WndProc ( HWND hwnd,

UINT iMsg,

WPARAM wParam,

LPARAM lParam )

{

int i,j,k,lines,r;

static int top, sel, flag;

static int cells[W-6][H]; // 控制游戏区域的【方格矩阵】

static int org[4][2], block[4][2],org2[4][2]; // 【方块】

HDC hdc;

HPEN hpen;

PAINTSTRUCT ps;

switch (iMsg)

{

case WM_CREATE:

//当一个应用程序使用函数CreateWindow或CreateWindowEx来创建一个窗口时,

//系统将发送该消息给此新建窗口过程。该消息将在创建窗口之后,显示窗口

//之前发送该消息,该消息将在CreateWindow或CreateWindowEx函数返回之前发送。

top=H-1;

// 将第一列和最后一列【方格】置1,控制【方块】不超出游戏区域

for(i=0; i<H; i++)

{

cells[0][i]=1;

cells[W-7][i]=1;

}

// 将最底下一行【方格】置1,控制【方块】不超出游戏区域

for(i=0; i<W-6; i++)

cells[i][H-1]=1;

// 其他【方格】置0,游戏方块只能在这里移动

for(i=1; i<=W-8; i++)

for(j=0; j<H-1; j++)

cells[i][j]=0;

return 0;

case MS_NEWBLOCK:

flag=0; // flag表示【方块】旋转了几次

for(i=top; i<H-1; i++)

{

lines =0;

// 循环语句检查是否有某一行全部被【方格】都填满

for(j=1; j<=W-7; j++)

if(! cells[j][i])

{

lines=1;

break;

}

// 若该行被填满,则将上一行的填充状态复制到该行,依此类推

// 即从该行开始,所有的【方格】都下移一行

if(!lines)

{ for(j=1;j<W-7; j++)

for(k=i; k>=top; k--)

cells[j][k]=cells[j][k-1];

top++;

//该函数把指定窗口用户区域内的矩形加入到该窗口的更新区域之外

//使该矩形无效。这个无效的矩形,连同更新区域中的其他区域,在收到下

//一条WM_PAINT消息时将被重画。无效区一直积累在更新区域之中,直到

//下一条WM_PAINT消息发生时对该区域进行处理。

InvalidateRect(hwnd, NULL, TRUE);

}

}

// 产生随机数0~7,分别代表【方块】的7种形状

srand( (unsigned)time( NULL ) );

sel =rand()%7;

//【方块】形状初始化

//【方块】的形状由其每个【方格】的位置决定

// 游戏区宽W=20,block[?][0]=4/5/6/7,block[?][1]=0/1/2

// 这样【方块】初始位置在游戏区域的最顶部的中央

switch(sel)

{

case 0:

// ▓▓

// ▓▓

org[0][0]=block[0][0] =5; org[0][1]=block[0][1] =0;

org[1][0]=block[1][0] =6; org[1][1]=block[1][1] =0;

org[2][0]=block[2][0] =5; org[2][1]=block[2][1] =1;

org[3][0]=block[3][0] =6; org[3][1]=block[3][1] =1;

for(i=0;i<4;i++)

{

org2[i][0]=org[i][0]+11;

org2[i][1]=org[i][1]+5;

}

break;

case 1:

//▓▓▓▓

org[0][0]=block[0][0] =4; org[0][1]=block[0][1] =0;

org[1][0]=block[1][0] =5; org[1][1]=block[1][1] =0;

org[2][0]=block[2][0] =6; org[2][1]=block[2][1] =0;

org[3][0]=block[3][0] =7; org[3][1]=block[3][1] =0;

for(i=0;i<4;i++)

{

org2[i][0]=org[i][0]+11;

org2[i][1]=org[i][1]+5;

}

break;

case 2:

//▓

//▓▓

// ▓

org[0][0]=block[0][0] =5; org[0][1]=block[0][1] =0;

org[1][0]=block[1][0] =5; org[1][1]=block[1][1] =1;

org[2][0]=block[2][0] =6; org[2][1]=block[2][1] =1;

org[3][0]=block[3][0] =6; org[3][1]=block[3][1] =2;

for(i=0;i<4;i++)

{

org2[i][0]=org[i][0]+11;

org2[i][1]=org[i][1]+5;

}

break;

case 3:

// ▓

//▓▓

//▓

org[0][0]=block[0][0] =6; org[0][1]=block[0][1] =0;

org[1][0]=block[1][0] =6; org[1][1]=block[1][1] =1;

org[2][0]=block[2][0] =5; org[2][1]=block[2][1] =1;

org[3][0]=block[3][0] =5; org[3][1]=block[3][1] =2;

for(i=0;i<4;i++)

{

org2[i][0]=org[i][0]+11;

org2[i][1]=org[i][1]+5;

}

break;

case 4:

//▓

//▓

//▓▓

org[0][0]=block[0][0] =5; org[0][1]=block[0][1] =0;

org[1][0]=block[1][0] =5; org[1][1]=block[1][1] =1;

org[2][0]=block[2][0] =5; org[2][1]=block[2][1] =2;

org[3][0]=block[3][0] =6; org[3][1]=block[3][1] =2;

for(i=0;i<4;i++)

{

org2[i][0]=org[i][0]+11;

org2[i][1]=org[i][1]+5;

}

break;

case 5:

// ▓

// ▓

//▓▓

org[0][0]=block[0][0] =5; org[0][1]=block[0][1] =0;

org[1][0]=block[1][0] =5; org[1][1]=block[1][1] =1;

org[2][0]=block[2][0] =5; org[2][1]=block[2][1] =2;

org[3][0]=block[3][0] =4; org[3][1]=block[3][1] =2;

for(i=0;i<4;i++)

{

org2[i][0]=org[i][0]+11;

org2[i][1]=org[i][1]+5;

}

break;

case 6:

// ▓

//▓▓▓

org[0][0]=block[0][0] =5; org[0][1]=block[0][1] =0;

org[1][0]=block[1][0] =4; org[1][1]=block[1][1] =1;

org[2][0]=block[2][0] =5; org[2][1]=block[2][1] =1;

org[3][0]=block[3][0] =6; org[3][1]=block[3][1] =1;

for(i=0;i<4;i++)

{

org2[i][0]=org[i][0]+11;

org2[i][1]=org[i][1]+5;

}

SendMessage (hwnd, MS_NEXTBLOCK, 0, 0);

break;

default:

SendMessage (hwnd, MS_NEWBLOCK, 0, 0);

SendMessage (hwnd, MS_NEXTBLOCK, 0, 0);

break;

}

return 0;

case WM_TIMER:

// 每个时间节拍【方块】自动下移一行

for(i=0; i<4; i++)

block[i][1]++;

// 检查【方块】下移是否被档住,即判断下移后新位置是否有【方格】

for(i=0; i<4; i++)

if(cells[ block[i][0] ][ block[i][1] ])

{

SendMessage (hwnd, MS_NEXTBLOCK, 0, 0);

for(i=0; i<4; i++)

cells[ org[i][0] ][ org[i][1] ]=1;

if(top>org[0][1]-2)

top=org[0][1]-2;

if (top<1)

{

KillTimer (hwnd, 1);

MessageBox (hwnd, "游戏结束,即将退出 !\n四川大学软件学院", "退出", MB_OK);

PostQuitMessage (0);

}

SendMessage (hwnd, MS_NEWBLOCK, 0, 0);

return 0;

}

SendMessage (hwnd, MS_DRAW, 0, 0);

return 0;

// 响应键盘控制

case WM_KEYDOWN:

r=0;

switch((int)wParam)

{

case VK_LEFT:

for(i=0; i<4; i++)

block[i][0]--;

break;

case VK_RIGHT:

for(i=0; i<4; i++)

block[i][0]++;

break;

case VK_DOWN:

for(i=0; i<4; i++)

block[i][1]++;

break;

// 按[向上键],【方块】顺时针旋转

//【方块】的旋转不是真正的旋转,而是根据不同的【方块】形状和该【方块】旋转过的

// 次数来移动其中的一个或几个【方格】,从而达到旋转的效果 。这样做很复杂,算法

// 不够理想,但是能够保持【方块】旋转时的重心比较稳定。

case VK_UP:

r=1;

flag++; //【方块】旋转加1

switch(sel) // sel代表当前【方块】的形状

{

case 0: break;

case 1:

flag =flag%2;

for(i=0; i<4; i++)

{

block[i][(flag+1)%2] =org[2][(flag+1)%2];

block[i][flag] =org[2][flag]-2+i;

}

break;

case 2:

flag =flag%2;

if(flag)

{ block[0][1] +=2; block[3][0] -=2; }

else

{ block[0][1] -=2; block[3][0] +=2; }

break;

case 3:

flag =flag%2;

if(flag)

{ block[0][1] +=2; block[3][0] +=2; }

else

{ block[0][1] -=2; block[3][0] -=2; }

break;

case 4:

flag=flag%4;

switch(flag)

{

case 0:

block[2][0] +=2; block[3][0] +=2;

block[2][1] +=1; block[3][1] +=1;

break;

case 1:

block[2][0] +=1; block[3][0] +=1;

block[2][1] -=2; block[3][1] -=2;

break;

case 2:

block[2][0] -=2; block[3][0] -=2;

block[2][1] -=1; block[3][1] -=1;

break;

case 3:

block[2][0] -=1; block[3][0] -=1;

block[2][1] +=2; block[3][1] +=2;

break;

}

break;

case 5:

flag=flag%4;

switch(flag)

{

case 0:

block[2][0] +=1; block[3][0] +=1;

block[2][1] +=2; block[3][1] +=2;

break;

case 1:

block[2][0] +=2; block[3][0] +=2;

block[2][1] -=1; block[3][1] -=1;

break;

case 2:

block[2][0] -=1; block[3][0] -=1;

block[2][1] -=2; block[3][1] -=2;

break;

case 3:

block[2][0] -=2; block[3][0] -=2;

block[2][1] +=1; block[3][1] +=1;

break;

}

break;

case 6:

flag =flag%4;

switch(flag)

{

case 0:

block[0][0]++; block[0][1]--;

block[1][0]--; block[1][1]--;

block[3][0]++; block[3][1]++;

break;

case 1:

block[1][0]++; block[1][1]++; break;

case 2:

block[0][0]--; block[0][1]++; break;

case 3:

block[3][0]--; block[3][1]--; break;

}

break;

}

break;

}

// 判断【方块】旋转后新位置是否有【方格】,若有,则旋转取消

for(i=0; i<4; i++)

if(cells[ block[i][0] ][ block[i][1] ])

{

if(r) flag +=3;

for(i=0; i<4; i++)

for(j=0; j<2; j++)

block[i][j]=org[i][j];

return 0;

}

SendMessage(hwnd, MS_DRAW, 0, 0);;

return 0;

// 清楚当前【方块】,并在显示“下一个方块”处绘制下一个【方块】

case MS_NEXTBLOCK:

hdc=GetDC(hwnd);

Cover(hdc,org2);

// DrawBlock(hdc,org2);

return 0;

// 清除当前【方块】,并在新的位置重新绘制【方块】

case MS_DRAW:

hdc =GetDC (hwnd);

Cover (hdc, org);

DrawBlock(hdc,org2);

for(i=0; i<4; i++)

for(j=0; j<2; j++)

org[i][j]=block[i][j];

DrawBlock (hdc,block);

ReleaseDC (hwnd, hdc);

return 0;

// 按照【方格矩阵】重绘游戏区域的【方格】

case WM_PAINT:

hdc =BeginPaint (hwnd, &ps);

DrawGamePlace(hdc);

TextOut(hdc,15*CELL,12*CELL,"Score",lstrlen("Score"));

TextOut(hdc,15*CELL,13*CELL,"i",lstrlen("i"));

TextOut(hdc,15*CELL,15*CELL,"Level",lstrlen("Level"));

TextOut(hdc,15*CELL-5,19*CELL,"钱彦江",lstrlen("钱彦江"));

hpen =CreatePen (PS_SOLID,1,RGB(0,255,0));

SelectObject (hdc,hpen);

for (i=top; i<H-1; i++)

for(j=1; j<=W-8; j++)

if( cells[j][i] )

DrawCell (hdc, (j-1)*CELL, (i-1)*CELL, j*CELL, i*CELL);

DeleteObject (hpen);

EndPaint (hwnd, &ps);

return 0;

case WM_DESTROY:

KillTimer (hwnd, 1);

PostQuitMessage (0);

return 0;

}

return DefWindowProc (hwnd, iMsg, wParam, lParam);

}

/*************************-----结------束------*******************************/

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有