C++控制台实现俄罗斯方块游戏

2025-05-27 0 13

之前学了些C++的课程,一直想着说编点小游戏,可是MFC又不想学,所以就只能变成控制台的小游戏。

俄罗斯方块一定是很多人小时候玩过的游戏。接下来就说说设计想法。

主要实现,选择游戏的等级,加速下降,不同形状不同颜色,暂停和退出功能。

首先是类的设计。

?

1

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
class Box

{

private:

int map[23][12];//画面坐标,记录有方块的点,也是游戏界面

int hotpoint[2];//当前活动的点,所有图形都是以此为基准绘制的

int top;//当前最高位置

int point;//分数

int level;//等级

int ID;//当前活动图形的ID号

int colorID;//图形的颜色ID。

public:

Box()//初始化

{

int i,j;

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

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

map[i][j]=0;

hotpoint[0]=0;

hotpoint[1]=5;

point=0;

level=1;

top=99;

ID=0;

}

void SetColor(int color);//颜色

void DrawMap();//画游戏的大界面

bool Judge(int x,int y);//判断当前位置能否绘制图形

void Welcome();//欢迎界面

void DrawBox(int x,int y,int num);//绘制图形

void Redraw(int x,int y,int num);//擦除图形

void Run();//运行

void Turn();//转动方块

void UpdataMap();//更新画面

void Pause();//暂停

};

接下来就是一些常量和光标函数,便于保存和调用

?

1

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
#define A1 0//A代表长条型,B为方块,C为L型,D为闪电型

#define A2 1

#define B 2

#define C11 3

#define C12 4

#define C13 5

#define C14 6

#define C21 7

#define C22 8

#define C23 9

#define C24 10

#define D11 11

#define D12 12

#define D21 13

#define D22 14

void SetPos(int i,int j)//设定光标位置

{

COORD pos={i,j};

SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);

}

const int sharp[15][8]=

{

{0,0,1,0,2,0,3,0},{0,0,0,1,0,2,0,3},

{0,0,1,0,0,1,1,1},

{0,0,1,0,1,1,1,2},{0,1,1,1,2,0,2,1},{0,0,0,1,0,2,1,2},{0,0,0,1,1,0,2,0},

{1,0,1,1,1,2,0,2},{0,0,0,1,1,1,2,1},{0,0,0,1,0,2,1,0},{0,0,1,0,2,0,2,1},

{0,0,0,1,1,1,1,2},{0,1,1,0,1,1,2,0},

{0,1,0,2,1,0,1,1},{0,0,1,0,1,1,2,1}

};//形状点的各个坐标,先纵后横

const int high[15]={4,1,2,2,3,2,3,2,3,2,3,2,3,2,3};//这个数组是用来保存各个形状高度的,以上面的坐标相对应

类方法的实现

?

1

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

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355
void Box::SetColor(int colorID)

{

int n_color;

switch(colorID)

{

case 0: n_color = 0x08;break;

case 1: n_color = 0x0C;break;

case 2: n_color = 0x0D;break;

case 3: n_color = 0x0E;break;

case 4: n_color = 0x0A;break;

}

SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), n_color);

}

void Box::DrawMap()//画界面

{

int i;

SetColor(0);//界面颜色

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

{

SetPos(i*2,0);

cout<<"■";

}

for(i=1;i<=24;i++)

{

SetPos(0,i);

cout<<"■";

SetPos(13*2,i);

cout<<"■";

}

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

{

SetPos(i*2,24);

cout<<"■";

}

i=15;

for(i=15;i<=25;i++)

{

SetPos(i*2,0);

cout<<"■";

}

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

{

SetPos(15*2,i);

cout<<"■";

SetPos(25*2,i);

cout<<"■";

}

for(i=15;i<=25;i++)

{

SetPos(i*2,9);

cout<<"■";

}

SetPos(16*2,16);

cout<<"俄罗斯方块";

SetPos(16*2,17);

cout<<"分数:"<<point;

SetPos(16*2,18);

cout<<"级别:"<<level;

}

void Box::DrawBox(int x,int y,int num)//绘制图形

{

int i;

int nx,ny;

if (num<2)SetColor(1);//0、1是长条

else if(num<3) SetColor(2);//2 方块

else if(num<11) SetColor(3);//3、4、5、6、7、8、9、10

else SetColor(4);

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

{

nx=x+sharp[num][i*2];

ny=y+sharp[num][i*2+1];

SetPos((ny+1)*2,nx+1);//利用sharp数组相对于点x,y绘制形状

//SetColor(i+1);

cout<<"■";

}

}

void Box::Redraw(int x,int y,int num)//擦除图形,原理同上

{

int i;

int nx,ny;

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

{

nx=x+sharp[num][i*2];

ny=y+sharp[num][i*2+1];

SetPos((ny+1)*2,nx+1);

cout<<" ";

}

}

void Box::Turn()//转动图形,单纯的该ID而已

{

switch(ID)

{

case A1: ID=A2; break;

case A2: ID=A1; break;

case B: ID=B; break;

case C11: ID=C12; break;

case C12: ID=C13; break;

case C13: ID=C14; break;

case C14: ID=C11; break;

case C21: ID=C22; break;

case C22: ID=C23; break;

case C23: ID=C24; break;

case C24: ID=C21; break;

case D11: ID=D12; break;

case D12: ID=D11; break;

case D21: ID=D22; break;

case D22: ID=D21; break;

}

}

void Box::Welcome()//欢迎界面

{

char x;

while(1)

{

system("cls");

cout<<"■■■■■■■■■■■■■■■■■■■"<<endl;

cout<<"■ 俄罗斯方块控制台版 ■"<<endl;

cout<<"■■■■■■■■■■■■■■■■■■■"<<endl;

cout<<"■ A,D左右移动 S向下加速 ■"<<endl;

cout<<"■ W 转动方块 P暂停游戏 ■"<<endl;

cout<<"■ Q退出游戏 ■"<<endl;

cout<<"■■■■■■■■■■■■■■■■■■■"<<endl;

cout<<"■ ■"<<endl;

cout<<"■ 按1-9选择等级!! ■"<<endl;

cout<<"■ ■"<<endl;

cout<<"■ ■"<<endl;

cout<<"■■■■■■■■■■■■■■■■■■■"<<endl;

SetPos(16,9);

x=getch();

if(x<='9'&&x>='1')//设置等级

{

level=x-'0';

break;

}

}

}

void Box::UpdataMap()//更新画面(关键)

{

int clear;

int i,j,k;

int nx,ny;

int flag;

for(i=0;i<4;i++)//更新map数组的信息

{

nx=hotpoint[0]+sharp[ID][i*2];

ny=hotpoint[1]+sharp[ID][i*2+1];

map[nx][ny]=1;

}

if(hotpoint[0]<top)//如果热点高于顶点则更新顶点,这里0表示的是纵向的

top=hotpoint[0];

clear=0;//消除的格数

for(i=hotpoint[0];i<hotpoint[0]+high[ID];i++)

{

flag=0;

for(j=0;j<12;j++)//检测是否可以消除此行

{

if(map[i][j]==0)//代表有空格,不能消除

{

flag=1;//1表示不能消除

break;

}

}

if(flag==0)//可以消除

{

for(k=i;k>=top;k--)//从当前位置向上所有的点下移一行

{

if(k==0)//最高点特殊处理

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

{

map[k][j]=0;

SetPos((j+1)*2,k+1);

cout<<" ";

}

else

{

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

{

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

SetPos((j+1)*2,k+1);

if(map[k][j]==0)

cout<<" ";

else

cout<<"■";

}

}

}

top++;//消除成功,最高点下移

clear++;

point+=clear*10*level;

}

}

SetColor(0);

SetPos(16*2,17);

cout<<"分数:"<<point;

}

void Box::Run()//运行游戏

{

int i=0;

char x;

int Count;//计数器

int nextID;

int temp;

srand((int)time(0));//将随机数的起点设置为time(0):不带秒

ID=rand()%15;//随机生成ID和下一个ID

nextID=rand()%15;//这里为了方便,其实每个形状不是等概率生成的

DrawBox(hotpoint[0],hotpoint[1],ID);//绘制图形

DrawBox(3,17,nextID);

Count=1000-level*100;//等级决定计数,这里是用Count控制时间,来控制下落的速度

while(1)

{

if(i>=Count)

{

i=0;//计数器清零

if(Judge(hotpoint[0]+1,hotpoint[1]))//如果下个位置无效(即到底)

{

UpdataMap();//更新画面

ID=nextID;//生成新ID,用原等待ID替换为当前ID

hotpoint[0]=0;//热点更新

hotpoint[1]=5;

Redraw(3,17,nextID);

nextID=rand()%15;

DrawBox(hotpoint[0],hotpoint[1],ID);

DrawBox(3,17,nextID);

if(Judge(hotpoint[0],hotpoint[1]))//无法绘制开始图形,游戏结束

{

//getch();

system("cls");

SetPos(25,15);

cout<<"游戏结束!!!最终得分为:"<<point<<endl;

system("pause");//就是在命令行上输出一行类似于“Press any key to exit”

exit(0);//关闭所有文件,退出正在执行的程序,返回0代表正常结束

}

}

else

{

Redraw(hotpoint[0],hotpoint[1],ID);//没有到底,方块下移一位

hotpoint[0]++;//热点下移

DrawBox(hotpoint[0],hotpoint[1],ID);

}

}

if(kbhit())//读取键盘信息

{

x=getch();

if(x=='a'||x=='A')//左移

{

if(Judge(hotpoint[0],hotpoint[1]-1)==0)

{

Redraw(hotpoint[0],hotpoint[1],ID);

hotpoint[1]-=1;

DrawBox(hotpoint[0],hotpoint[1],ID);

}

}

if(x=='d'||x=='D')//右移

{

if(Judge(hotpoint[0],hotpoint[1]+1)==0)

{

Redraw(hotpoint[0],hotpoint[1],ID);

hotpoint[1]+=1;

DrawBox(hotpoint[0],hotpoint[1],ID);

}

}

if(x=='s'||x=='S')//向下加速!!!!!!!!此处可以改进,可以改进加速效果。改成+3之后,会出现BUG,最后几个无法加速

{

if(Judge(hotpoint[0]+3,hotpoint[1])==0)

{

Redraw(hotpoint[0],hotpoint[1],ID);

hotpoint[0]+=1;

DrawBox(hotpoint[0],hotpoint[1],ID);

}

}

if(x=='w'||x=='W')//转动方块

{

temp=ID;

Turn();

if(!Judge(hotpoint[0],hotpoint[1]))

{

Redraw(hotpoint[0],hotpoint[1],temp);

DrawBox(hotpoint[0],hotpoint[1],ID);

}

else

ID=temp;

}

if(x=='p'||x=='P')

{

//getch();

//system("cls");

Pause();

}

if(x=='q'||x=='Q')

{

system("cls");

SetPos(25,15);

cout<<"游戏结束!!!最终得分为:"<<point<<endl;

system("pause");

exit(0);

}

while(kbhit())//读掉剩下的键盘信息

getch();

}

Sleep(1);//等待1毫秒

i++;//计数器加1

}

}

int Box::Judge(int x,int y)//判断当前是否可以绘制方块

{

int i;

int nx,ny;

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

{

nx=x+sharp[ID][i*2];

ny=y+sharp[ID][i*2+1];

if(nx<0||nx>=23||ny<0||ny>=12||map[nx][ny]==1)//不能,返回1

return 1;

}

return 0;

}

void Box::Pause()

{

system("cls");

while(1)

{

SetPos(30,13);

cout<<"暂停等待,咖啡时间^-^"<<endl;

if(getch()=='p'||getch()=='P')

break;

}

SetPos(30,13);

cout<<" "<<endl;

DrawMap();

int i ,j;

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

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

if(map[i][j]==1)

{

SetPos((j+1)*2,i+1);

cout<<"■";

}

}

?

1

2

3

4

5

6

7

8
void main()//主函数

{

Box game;

game.Welcome();

system("cls");

game.DrawMap();

game.Run();

}

待改进的点:

1、加速下降的时候,从代码中也可以发现,最后几格没法加速。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持快网idc。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 C++控制台实现俄罗斯方块游戏 https://www.kuaiidc.com/72939.html

相关文章

发表评论
暂无评论