先說這種俄羅斯方塊的游戲規則('w','a','s','d' -> 旋轉,左邊,快速下降,右邊):
1、右邊4x4方塊群內左鍵自造積木,右鍵放下積木(只有等當前積木下落停靠后,右鍵放下新的積木才有效)。
2、右面的墻是粘性墻,會黏住最右邊的積木而只能下降不能向左(這會形成分散型積木,從而出現真空靜止的積木)。
3、靠上固定的積木就會一同固定(也就是說每塊積木之間都有粘性)
(VC08下編譯通過)
源文件這里下載: SelfTetrisV1.1.rar
1、右邊4x4方塊群內左鍵自造積木,右鍵放下積木(只有等當前積木下落停靠后,右鍵放下新的積木才有效)。
2、右面的墻是粘性墻,會黏住最右邊的積木而只能下降不能向左(這會形成分散型積木,從而出現真空靜止的積木)。
3、靠上固定的積木就會一同固定(也就是說每塊積木之間都有粘性)
左手鍵盤wasd,右手(或者女朋友的手)操作鼠標左鍵來構造新積木,右鍵放下構造的積木。
(VC08下編譯通過)
1
/**//* SelfTetris.h */
2
3
4
#include <windows.h>
5
6
class SelfTetris
7

{
8
#define DELTA_LEFTTOP 20
9
#define PV(v) (DELTA_LEFTTOP+(v)*D_LEN)
10
#define BIN_FOR_BEGINE(i,j,topi,topj) for(i=0;i!=(topi);++i)for(j=0;j!=(topj);++j)
11
public:
12
void Action();
13
int IsMove(int x,int y);/**//* 是否能向(x,y)向量移動 */
14
int IsDis(int y);/**//* 是否消除第y行 */
15
int GoCurdle(int x,int y,int isFall,int isX);/**//* 按(x,y)向量*/
16
void KeyDown(WPARAM wparam);
17
void Run(int x,int y,int isX);/**//* 一次移動 */
18
void RotateBlocks();
19
void CastBlocks();
20
void SetBlocks(int mx,int my);
21
int Rectangle(int i,int j,int isStill);/**//* 在游戲矩陣內畫矩形,isStill為是否畫靜止類型的矩形 */
22
SelfTetris(int dtime_=100);
23
public:
24
static const int W_NUM=18,H_NUM=35,D_LEN=15,H_HIDE=1;/**//* 游戲區域寬,高,單位長度象素,頂部是否隱藏*/
25
int canDrop,_x,_y,obj[4][4];/**//* _x,_y 為當前下落積木重心 ,obj為當前構造積木形狀, canDrop為是否可下新積木*/
26
int scores;/**//* 分數,臨時變量*/
27
int board[H_NUM][W_NUM];/**//* 俄羅斯方塊游戲區域矩陣 */
28
int x,y,dtime,i,j;/**//* x,y,i,j為臨時變量 dtime為游戲action周期*/
29
HDC hdc;
30
};
31


2

3

4

5

6

7



8

9

10

11

12

13


14


15


16

17


18

19

20

21


22

23

24


25


26


27


28


29

30

31

1
/**//* SelfTetris.cpp */
2
3
#include "SelfTetris.h"
4
5
int SelfTetris::Rectangle(int i,int j,int isStill)
6

{
7
isStill=isStill?GRAY_BRUSH:WHITE_BRUSH;
8
SelectObject (hdc, GetStockObject (isStill)) ;
9
::Rectangle(hdc,PV(j),PV(i),PV(j+1),PV(i+1));
10
SelectObject (hdc, GetStockObject (GRAY_BRUSH)) ;
11
return 0;
12
}
13
int SelfTetris::IsMove(int x,int y)
14

{
15
BIN_FOR_BEGINE(i,j,H_NUM,W_NUM)
16
if((board[i][j]==2)&&((i+y>=H_NUM||i+y<=-1)||(board[i+y][j+x]==1)))
17
return -1;
18
else if((board[i][j]==2)&&((j+x>=W_NUM||j+x<=-1)))
19
return 0;
20
return 1;
21
}
22
int SelfTetris::IsDis(int y)
23

{
24
for(j=0;j!=W_NUM;j++)
25
if(board[y][j]!=1) return 0;
26
for(j=0;j!=W_NUM;j++) board[y][j]=0;
27
for(int i=y-1;i!=-1;--i)
28
for(int j=0;j!=W_NUM;++j)
29
if(board[i][j]==1)
30
{
31
board[i+1][j]=1;
32
i>=H_HIDE?Rectangle(i+1,j,1):1;
33
board[i][j]=0;
34
}
35
return 1;
36
}
37
int SelfTetris::GoCurdle(int x,int y,int isFall,int isX)
38

{
39
int tag=0,a,b,d;
40
a=W_NUM-1,b=-1,d=-1;
41
if(x==-1) b=W_NUM-1,a=0,d=1;
42
for(i=H_NUM-1;i!=-1;--i)
43
for(j=a;j!=b;j+=d)
44
if(board[i][j]==2)
45
{
46
if(isFall==-1)
{
47
canDrop=1;
48
board[i][j]=1;
49
i>=H_HIDE&&isX==0?Rectangle(i,j,1):1;
50
}else if(isFall==1)
51
{
52
board[i+y][j+x]=2,board[i][j]=0;
53
i>=H_HIDE&&isX==0?Rectangle(i+y,j+x,0):1;
54
tag=1;
55
}
56
}else if(board[i][j]==1)
57
i>=H_HIDE&&isX==0?Rectangle(i,j,1):1;
58
if(tag==1) _x+=x,_y+=y;
59
if(isX==0)
60
BIN_FOR_BEGINE(i,j,4,4)
61
Rectangle(H_NUM/2+4+i,W_NUM+4+j,!(obj[i][j]==1));
62
return isFall;
63
}
64
void SelfTetris::KeyDown(WPARAM wparam)
65

{
66
switch (wparam)
67
{
68
case 0x41:i=-1;break;
69
case 0x57: RotateBlocks();break;
70
case 0x53:i=2;break;
71
case 0x44:i=1;
72
}
73
}
74
void SelfTetris::Run(int x,int y,int isX)
75

{
76
SelectObject (hdc, GetStockObject (BLACK_PEN)) ;
77
::Rectangle(hdc,DELTA_LEFTTOP,DELTA_LEFTTOP+H_HIDE*D_LEN,DELTA_LEFTTOP+W_NUM*D_LEN,DELTA_LEFTTOP+H_NUM*D_LEN);
78
SelectObject (hdc, GetStockObject (GRAY_BRUSH)) ;
79
int mul=0;
80
GoCurdle(x,y,IsMove(x,y),isX);
81
for(i=0;i!=H_NUM;i++)
82
IsDis(i)?++mul>=2?scores+=10*mul:scores+=10:1;
83
static wchar_t str[40];
84
SelectObject (hdc, GetStockObject (BLACK_PEN));
85
wsprintf(str,L" Total Score : %d ",scores);
86
TextOut(hdc,320,200,str,wcslen(str));
87
wsprintf(str,L" Game Level : %d ",scores/10+1);
88
TextOut(hdc,320,250,str,wcslen(str));
89
}
90
91
void SelfTetris::RotateBlocks()
92

{
93
int _board[H_NUM][W_NUM]=
{0};
94
BIN_FOR_BEGINE(x,y,H_NUM,W_NUM)
95
if(board[x][y]==2)
96
if((_x+_y-x)>=W_NUM||(_x+_y-x)<=-1||(_y-(_x-y))>=H_NUM||
97
(_y-(_x-y))<=-1||board[_y-(_x-y)][_x+(_y-x)]==1)
98
return;
99
BIN_FOR_BEGINE(x,y,H_NUM,W_NUM)
100
if(board[x][y]==2)
101
board[x][y]=0,_board[_y-(_x-y)][_x+(_y-x)]=2;
102
BIN_FOR_BEGINE(x,y,H_NUM,W_NUM)
103
if(_board[x][y]==2)
104
board[x][y]=_board[x][y];
105
}
106
void SelfTetris::SetBlocks(int mx,int my)
107

{
108
BIN_FOR_BEGINE(x,y,4,4)
109
if(my>PV(H_NUM/2+4+x)&&
110
my<PV(H_NUM/2+4+x+1)&&
111
mx>PV(W_NUM+4+y)&&
112
mx<PV(W_NUM+4+y+1))
113
obj[x][y]=(obj[x][y]+1)%2;
114
}
115
void SelfTetris::CastBlocks()
116

{
117
if(canDrop==0)
118
return;
119
BIN_FOR_BEGINE(x,y,4,4)
120
if(obj[x][y]==1)
121
board[0+x][W_NUM/2+y]=2;
122
canDrop=0;
123
_x=W_NUM/2+2;
124
_y=2;
125
}
126
void SelfTetris::Action()
127

{
128
if(i==2) Run(0,1,1);
129
else if(i!=0) Run(i,0,1);
130
for(x=0;x!=scores/10+1;x++)
131
Run(0,1,0);
132
i=0;
133
}
134
SelfTetris::SelfTetris(int dtime_)
135

{
136
canDrop=0;
137
memset(obj,0,sizeof(int)*16);
138
memset(board,0,sizeof(int)*H_NUM*W_NUM);
139
board[0][W_NUM/2-1]=board[0][W_NUM/2+2]=board[0][W_NUM/2+4]=board[0][W_NUM/2+3]=2;
140
_x=W_NUM/2+2;
141
_y=2;
142
i=j=0;
143
scores=0;
144
dtime=dtime_;
145
}


2

3

4

5

6



7

8

9

10

11

12

13

14



15

16

17

18

19

20

21

22

23



24

25

26

27

28

29

30



31

32

33

34

35

36

37

38



39

40

41

42

43

44

45



46



47

48

49

50

51



52

53

54

55

56

57

58

59

60

61

62

63

64

65



66

67



68

69

70

71

72

73

74

75



76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92



93



94

95

96

97

98

99

100

101

102

103

104

105

106

107



108

109

110

111

112

113

114

115

116



117

118

119

120

121

122

123

124

125

126

127



128

129

130

131

132

133

134

135



136

137

138

139

140

141

142

143

144

145

1
/**//* TetrisGame.cpp */
2
3
#include "SelfTetris.h"
4
5
SelfTetris aTetris(100);
6
7
LRESULT CALLBACK WindowProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
8

{
9
aTetris.hdc=GetDC(hwnd);
10
int mx = (int)LOWORD(lparam),my = (int)HIWORD(lparam);
11
switch(msg)
12
{
13
case WM_KEYDOWN:
14
aTetris.KeyDown(wparam);
15
break;
16
case WM_LBUTTONDOWN:
17
aTetris.SetBlocks(mx,my);
18
break;
19
case WM_RBUTTONUP:
20
aTetris.CastBlocks();
21
break;
22
case WM_CREATE:
23
SetTimer(hwnd,10,aTetris.dtime,0);
24
break;
25
case WM_TIMER:
26
27
aTetris.Action();
28
break;
29
case WM_PAINT:
30
break;
31
case WM_CLOSE :
32
MessageBoxW(0,L"非常感謝測試~",L"SelfTetrisv1.0",0);
33
break;
34
case WM_QUIT:
35
case WM_DESTROY:
36
PostQuitMessage(0);
37
break;
38
default:break;
39
}
40
ReleaseDC(hwnd,aTetris.hdc);
41
return DefWindowProc(hwnd, msg, wparam, lparam);
42
}
43
44
45
int WINAPI WinMain(HINSTANCE hinstance,HINSTANCE hprevinstance,LPSTR lpcmdline,int ncmdshow)
46

{
47
WNDCLASSEX winclass=
{sizeof(WNDCLASSEX),CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW,
48
WindowProc,0,0,hinstance,LoadIcon(NULL, IDI_APPLICATION),
49
LoadCursor(NULL, IDC_ARROW),(HBRUSH__*)GetStockObject(BLACK_BRUSH),0,
50
L"SelfTetris",0};
51
HWND hwnd;
52
MSG msg;
53
if (!RegisterClassEx(&winclass))
54
return 0;
55
if (!(hwnd = CreateWindowEx(NULL,L"SelfTetris",L"SelfTetrisV1.0",
56
WS_OVERLAPPEDWINDOW | WS_VISIBLE,0,0,455,600,NULL,NULL,hinstance,NULL)))
57
return 0;
58
59
while(GetMessage(&msg,NULL,0,0))
60
{
61
TranslateMessage(&msg);
62
DispatchMessage(&msg);
63
}
64
return msg.wParam;
65
}


2

3

4

5

6

7

8



9

10

11

12



13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46



47



48

49

50

51

52

53

54

55

56

57

58

59

60



61

62

63

64

65

源文件這里下載: SelfTetrisV1.1.rar
- -bnr 你有更短的?貼鏈接
以及...右側的墻帶有粘性...這TMD是為什么啊為什么啊為什么啊!!!
這都被你發現了 我用了高響應模式的PeekMessage 現在改成GetMessage 在我電腦上CPU占用率已經是1%~25%之間了。
右邊粘性墻有一種方法可以擺脫粘性,就是按w鍵翻轉。
thanks