-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathShap.cpp
1962 lines (1794 loc) · 60.4 KB
/
Shap.cpp
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
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#include "Shap.h"
const string fileAccountNumber = "res\\AccountNumber.txt";
const string fileAccountName = "res\\AccountName.txt";
const string fileAccountPassword = "res\\AccountPassword.txt";
const string fileMaxScore = "res\\MaxScore.txt";
Shap::Shap()
{
//初始化640 * 480 的绘图屏幕,并禁用关闭窗口按钮
initgraph(800, 744, NOCLOSE);
// 设置背景色为白色
setbkcolor(0xFFFFFF);
// 用背景色清空屏幕
cleardevice();
HWND hwnd;
// 1.设置窗口句柄变量保存窗口信息
hwnd = GetHWnd();
// 2.获取窗口句柄
SetWindowText(hwnd, _T("俄罗斯方块"));
}
Shap::~Shap()
{
_getch(); //按任意键继续
closegraph(); //关闭绘图窗口
}
//初始化
void Shap::Initialization()
{
//初始化640 * 480 的绘图屏幕,并禁用关闭窗口按钮
//初始化绘图窗口在 Tetris.cpp 文件中初始化
//initgraph(800, 744, SHOWCONSOLE | NOCLOSE);
// 设置背景色为白色
background.backgroundInitialization(); //背景初始化
setbkcolor(0xFFFFFF);
// 用背景色清空屏幕
cleardevice();
//设置左边矩形框
setfillcolor(0xd8dbdc); //左边框设置当前填充颜色 : 灰色
fillrectangle(0, 0, 550, 744); //画矩形框,4个参数分别为左上右下的坐标
setfillcolor(0x5fe1f2); //右边框设置当前填充颜色 :黄色
fillrectangle(550, 0, 800, 744);
//游戏边框
setfillcolor(0xEDECEC); //比灰白更白一点,游戏内框的颜色
solidrectangle(73, 0, 476, 744); //宽:13格,每格24
setfillcolor(0xd8dbdc);
solidrectangle(0, 713, 550, 744);
//完成背景的生成后,重新定义坐标原点
setorigin(73 - 31, 0); //定义坐标原点,考虑到方块的移动和旋转,坐标原点的x坐标要向左偏移一格,即31
settextstyle(25, 20, _T("宋体"), 0, 0, FW_EXTRABOLD, false, false, false); //设置字体样式:长,宽,字体名称,//有3个重载函数
settextcolor(0);
setbkcolor(0x5fe1f2); //右边框设置当前填充颜色 :黄色
setbkmode(OPAQUE); //用背景色填充文字的背景(抠图),更加美观
//字体y坐标再减 30
outtextxy(530, 20, _T("Hello:"));
outtextxy(530, 120, _T("Next:"));
setfillcolor(0xFFFFFF);
solidrectangle(560, 180, 720, 340); //覆盖 hello 下面的字体
outtextxy(530, 370, _T("MaxScore:"));
outtextxy(530, 470, _T("NowScore:"));
outtextxy(530, 570, _T("Lines:"));
settextcolor(0xFF5555); //亮蓝色
settextstyle(20, 15, _T("宋体"), 0, 0, FW_EXTRABOLD, false, false, false); //设置字体样式:长,宽,字体名称,//有3个重载函数
outtextxy(520, 670, _T("暂停(P)"));
outtextxy(650, 670, _T("退出(B)"));
settextcolor(0);
//初始化右边框的分数
setfillcolor(0x5fe1f2);
//用背景色矩形框覆盖
solidrectangle(520, 405, 799, 465); //覆盖 maxScore 下面的数字
solidrectangle(520, 505, 799, 565); //覆盖 nextScore 下面的数字
solidrectangle(520, 605, 799, 665); //覆盖 lines 下面的数字
eliminateLine = 0; //初始化消除的总行数
sumScore = 0; //初始化总分数
wchar_t tempSumScore[15];
wchar_t tempEliminateLine[15];
_stprintf_s(tempSumScore, _T("%d"), sumScore); // 将变量值格式化写入到中间变量 tempSumScore 中, _T("")是 unicode 的用法
_stprintf_s(tempEliminateLine, _T("%d"), eliminateLine);
settextstyle(25, 20, _T("宋体"), 0, 0, FW_EXTRABOLD, false, false, false); //设置字体样式:长,宽,字体名称,//有3个重载函数
outtextxy(580, 520, tempSumScore);
outtextxy(580, 620, tempEliminateLine);
setfillcolor(0xFF5555);
solidcircle(3, 3, 2);
accountIndex = 0; //该下标从1开始,即第一个学生的下标为1
gameoverChooseFlag = 0; //初始化为 0,避免上一次对gameoverChooseFlag的赋值对后面程序的影响
}
//每次开始游戏时只调用一次,生成第一个随机方块,显示用户名称和该用户最高分
void Shap::random1()
{
int accountNumber;
//string tempMaxScore; //临时变量,最高分,因为getline函数读取出来的是一个字符串
string tempAccountName; //账号名称
wchar_t wcharMaxScore[15];
wchar_t wcharAccountName[15];
fstream fileAccount;
//首先判断是否要显示用户名字,如果该用户事账号密码登录,则显示账号名称和最高分,如果是游客登录,则不显示账号和最高分
if (accountIndex != 0)
{
//得到账号个数
fileAccount.open(fileAccountNumber, ios_base::in);
fileAccount >> accountNumber;
fileAccount.close();
fileAccount.open(fileAccountName, ios_base::in);
//因为accountIndex从1开始,即第一个学生的下标为1,注意这里是i=1,i <= accountNumber
for (int i = 1; i <= accountNumber; i++) {
getline(fileAccount, tempAccountName, '\n');
if (i == accountIndex)
{
break;
}
}
fileAccount.close();
//显示最高分
fileAccount.open(fileMaxScore, ios_base::in);
for (int i = 1; i <= accountNumber; i++)
{
getline(fileAccount, maxScore, '\n');
if (i == accountIndex)
{
break;
}
}
}
//显示账号名称
swprintf(wcharAccountName, 100, L"%S", tempAccountName.c_str()); //注意大写,name1指向的内存区域存储这wchar_t类型的
swprintf(wcharMaxScore, 100, L"%S", maxScore.c_str());
outtextxy(530, 70, wcharAccountName);
outtextxy(580, 420, wcharMaxScore);
srand(int(time(0)));
blockColor1 = (rand() % 7) + 1;
//对应的颜色分别为 红, 灰蓝, 黄, 绿,青,蓝,紫
switch (blockColor1)
{
case 1:
color1 = "0x5555FF"; //红色
break;
case 2:
color1 = "0xEBACD2"; //粉色
break;
case 3:
color1 = "0x55FFFF"; //黄色
break;
case 4:
color1 = "0x55FF55"; //绿色
break;
case 5:
color1 = "0xFFFF55"; //天青色
break;
case 6:
color1 = "0xFF5555"; //深蓝色
break;
case 7:
color1 = "0xAA00AA"; //紫色
break;
default:
break;
}
blockNumber1 = (rand() % 19); //0 ~ 18,方块编号
}
//生成后续的随机方块
void Shap::random2()
{
srand(int(time(0)) + 1); //防止和第一次生成的随机数一样
blockColor2 = (rand() % 7) + 1;
//对应的颜色分别为 红, 灰蓝, 黄, 绿,青,蓝,紫
switch (blockColor2)
{
case 1:
color2 = "0x5555FF"; //红色
break;
case 2:
color2 = "0xEBACD2"; //粉色
break;
case 3:
color2 = "0x55FFFF"; //黄色
break;
case 4:
color2 = "0x55FF55"; //绿色
break;
case 5:
color2 = "0xFFFF55"; //天青色
break;
case 6:
color2 = "0xFF5555"; //深蓝色
break;
case 7:
color2 = "0xAA00AA"; //紫色
break;
default:
break;
}
blockNumber2 = (rand() % 19); //0 ~ 18,方块编号
}
//绘画当前方块,这里的deviationX, deviationY 是4 * 4 方框的左上角的点相对于原点坐标的偏移格数,
void Shap::draw(int deviationX, int deviationY, int type, string newColor)
{
/*
注: deviationX, deviationY 表示包含方块的 4 * 4 方框的左上角的点相对于 原点坐标的偏移格数,
由 x, y 乘以每小格的长度,得到Ox, Oy,表示 4 * 4 方框的左上角的坐标
然后在根据方块的类型type ,以Ox, Oy 为参考,画出相应的方块
默认每一个小方块是 31 * 31, 考虑到美观,实现有颜色的 为 28 * 28
*/
//Ox, Oy,表示 4 * 4 方框的左上角的坐标
int Ox, Oy;
Ox = deviationX * 31;
Oy = deviationY * 31;
nowX = Ox;
nowY = Oy;
setColor(newColor);
solidrectangle(Ox + 31 * site[type][1] + 1.5, Oy + 31 * site[type][2] + 1.5, Ox + 31 * site[type][1] + 1.5 + 28, Oy + 31 * site[type][2] + 1.5 + 28);
solidrectangle(Ox + 31 * site[type][3] + 1.5, Oy + 31 * site[type][4] + 1.5, Ox + 31 * site[type][3] + 1.5 + 28, Oy + 31 * site[type][4] + 1.5 + 28);
solidrectangle(Ox + 31 * site[type][5] + 1.5, Oy + 31 * site[type][6] + 1.5, Ox + 31 * site[type][5] + 1.5 + 28, Oy + 31 * site[type][6] + 1.5 + 28);
solidrectangle(Ox + 31 * site[type][7] + 1.5, Oy + 31 * site[type][8] + 1.5, Ox + 31 * site[type][7] + 1.5 + 28, Oy + 31 * site[type][8] + 1.5 + 28);
/*cout << deviationX << ", " << deviationY << endl;
cout << deviationY + site[type][2] << endl;
cout << deviationX + site[type][2] << endl;*/
//在地图上标记该点,//用每一个小方格的左上角的坐标来代替该小方块的坐标,这里记录的是偏移的格数
//因为background中的数组是第一个元素是行,第二个元素是列,所以第一个元素对应坐标y,第二个元素对应坐标x
background.setBackgroundTrue(deviationY + site[type][2], deviationX + site[type][1]);
background.setBackgroundTrue(deviationY + site[type][4], deviationX + site[type][3]);
background.setBackgroundTrue(deviationY + site[type][6], deviationX + site[type][5]);
background.setBackgroundTrue(deviationY + site[type][8], deviationX + site[type][7]);
cout << "draw newColor == " << color1 << endl;
//为每一个小方块标记颜色
background.setColors(deviationY + site[type][2], deviationX + site[type][1], newColor);
background.setColors(deviationY + site[type][4], deviationX + site[type][3], newColor);
background.setColors(deviationY + site[type][6], deviationX + site[type][5], newColor);
background.setColors(deviationY + site[type][8], deviationX + site[type][7], newColor);
}
//在右侧区域画下一次即将出现的方块,更好的提示用户
void Shap::drawNextBlock(int type, string newColor)
{
//Ox, Oy,表示 4 * 4 方框的左上角的坐标
int Ox, Oy;
Ox = 590;
Oy = 210;
//清空当前绘画区域
setfillcolor(0xFFFFFF);
solidrectangle(560, 180, 720, 340); //用白色方框先覆盖该区域(作用是清空上一次的画图图像),在重新画图
setColor(newColor);
solidrectangle(Ox + 31 * site[type][1] + 1.5, Oy + 31 * site[type][2] + 1.5, Ox + 31 * site[type][1] + 1.5 + 28, Oy + 31 * site[type][2] + 1.5 + 28);
solidrectangle(Ox + 31 * site[type][3] + 1.5, Oy + 31 * site[type][4] + 1.5, Ox + 31 * site[type][3] + 1.5 + 28, Oy + 31 * site[type][4] + 1.5 + 28);
solidrectangle(Ox + 31 * site[type][5] + 1.5, Oy + 31 * site[type][6] + 1.5, Ox + 31 * site[type][5] + 1.5 + 28, Oy + 31 * site[type][6] + 1.5 + 28);
solidrectangle(Ox + 31 * site[type][7] + 1.5, Oy + 31 * site[type][8] + 1.5, Ox + 31 * site[type][7] + 1.5 + 28, Oy + 31 * site[type][8] + 1.5 + 28);
}
//传入的参数x, y 是 4 * 4 方框的左上角的坐标,flag = 1表示左移, flag = 2表示右移,type表示方块的编号
void Shap::move(int flag, int type, int x, int y)
{
//4 * 4 方框的左上角的点相对于原点坐标的偏移格数,
//cout << "x, y ==" << x << "," << y << endl;
int deviationX, deviationY;
deviationX = x / 31;
deviationY = y / 31;
bool ifempty1, ifempty2, ifempty3, ifempty4 = false;
bool ifLeftEmpty = false;
bool ifRightEmpty = false;
//左移
if (flag == 1) {
switch (type)
{
ifLeftEmpty = false; //每次进入switch的时候都要初始化ifLeftEmpty的值(重要)
case 16:
ifempty1 = false;
ifempty1 = background.ifEmpty(deviationY + moveLeft[type][2], deviationX + moveLeft[type][1]);
if (ifempty1 == true)
{
ifLeftEmpty = true;
}
break;
case 0:
case 2:
case 4:
case 6:
case 8:
case 10:
case 12:
case 14:
case 18:
ifempty1 = false;
ifempty2 = false;
ifempty1 = background.ifEmpty(deviationY + moveLeft[type][2], deviationX + moveLeft[type][1]);
ifempty2 = background.ifEmpty(deviationY + moveLeft[type][4], deviationX + moveLeft[type][3]);
if (ifempty1 == true && ifempty2 == true)
{
ifLeftEmpty = true;
}
break;
case 1:
case 3:
case 5:
case 7:
case 9:
case 11:
case 13:
case 15:
ifempty1 = false;
ifempty2 = false;
ifempty3 = false;
ifempty1 = background.ifEmpty(deviationY + moveLeft[type][2], deviationX + moveLeft[type][1]);
ifempty2 = background.ifEmpty(deviationY + moveLeft[type][4], deviationX + moveLeft[type][3]);
ifempty3 = background.ifEmpty(deviationY + moveLeft[type][6], deviationX + moveLeft[type][5]);
if (ifempty1 == true && ifempty2 == true && ifempty3 == true)
{
ifLeftEmpty = true;
}
case 17:
ifempty1 = false;
ifempty2 = false;
ifempty3 = false;
ifempty4 = false;
ifempty1 = background.ifEmpty(deviationY + moveLeft[type][2], deviationX + moveLeft[type][1]);
ifempty2 = background.ifEmpty(deviationY + moveLeft[type][4], deviationX + moveLeft[type][3]);
ifempty3 = background.ifEmpty(deviationY + moveLeft[type][6], deviationX + moveLeft[type][5]);
ifempty4 = background.ifEmpty(deviationY + moveLeft[type][8], deviationX + moveLeft[type][7]);
if (ifempty1 == true && ifempty2 == true && ifempty3 == true)
{
ifLeftEmpty = true;
}
default:
break;
}
if (ifLeftEmpty)
{
//nowX = nowX - 31;
clear(deviationX, deviationY, type);
draw(deviationX - 1, deviationY, type, color1);
}
}
//右移
else if (flag == 2)
{
switch (type)
{
ifRightEmpty = false; //每次进入switch循环都要重置ifRightEmpty的值为false
//以下四种情况分别表示阻挡该方块右移的位置有几个,从1 到4
case 16:
ifempty1 = false;
ifempty1 = background.ifEmpty(deviationY + moveRight[type][2], deviationX + moveRight[type][1]);
if (ifempty1 == true)
{
ifRightEmpty = true;
}
break;
case 0:
case 2:
case 4:
case 6:
case 8:
case 10:
case 12:
case 14:
case 18:
ifempty1 = false;
ifempty2 = false;
ifempty1 = background.ifEmpty(deviationY + moveRight[type][2], deviationX + moveRight[type][1]);
ifempty2 = background.ifEmpty(deviationY + moveRight[type][4], deviationX + moveRight[type][3]);
if (ifempty1 == true && ifempty2 == true)
{
ifRightEmpty = true;
}
/*cout << "ifRightEmpty is" << ifRightEmpty << endl;*/
break;
case 1:
case 3:
case 5:
case 7:
case 9:
case 11:
case 13:
case 15:
ifempty1 = false;
ifempty2 = false;
ifempty3 = false;
ifempty1 = background.ifEmpty(deviationY + moveRight[type][2], deviationX + moveRight[type][1]);
ifempty2 = background.ifEmpty(deviationY + moveRight[type][4], deviationX + moveRight[type][3]);
ifempty3 = background.ifEmpty(deviationY + moveRight[type][6], deviationX + moveRight[type][5]);
if (ifempty1 == true && ifempty2 == true && ifempty3 == true)
{
ifRightEmpty = true;
}
//cout << "ifRightEmpty is" << ifRightEmpty << endl;
break;
case 17:
ifempty1 = false;
ifempty2 = false;
ifempty3 = false;
ifempty4 = false;
ifempty1 = background.ifEmpty(deviationY + moveRight[type][2], deviationX + moveRight[type][1]);
ifempty2 = background.ifEmpty(deviationY + moveRight[type][4], deviationX + moveRight[type][3]);
ifempty3 = background.ifEmpty(deviationY + moveRight[type][6], deviationX + moveRight[type][5]);
ifempty4 = background.ifEmpty(deviationY + moveRight[type][8], deviationX + moveRight[type][7]);
if (ifempty1 == true && ifempty2 == true && ifempty3 == true && ifempty4 == true)
{
ifRightEmpty = true;
}
//cout << "ifRightEmpty is" << ifRightEmpty << endl;
break;
default:
break;
}
if (ifRightEmpty)
{
//nowX = nowX + 1;
clear(deviationX, deviationY, type);
draw(deviationX + 1, deviationY, type, color1);
}
}
}
// turn 传入的参数x, y 是 4 * 4 方框的左上角的坐标
void Shap::turn(int type, int x, int y)
{
//4 * 4 方框的左上角的点相对于原点坐标的偏移格数,
int deviationX, deviationY;
deviationX = x / 31;
deviationY = y / 31;
bool ifempty1, ifempty2, ifempty3, ifempty4 = false;
bool ifTurnIsEmpty = false;
switch (type)
{
ifTurnIsEmpty = false;
case 18:
ifTurnIsEmpty = true;
break;
case 8:
case 9:
case 10:
case 11:
ifempty1 = false;
ifempty1 = background.ifEmpty(deviationY + turnIsempty[type][2], deviationX + turnIsempty[type][1]);
if (ifempty1 == true)
{
ifTurnIsEmpty = true;
}
break;
case 3:
case 5:
case 6:
case 12:
case 13:
case 14:
case 15:
ifempty1 = false;
ifempty2 = false;
ifempty1 = background.ifEmpty(deviationY + turnIsempty[type][2], deviationX + turnIsempty[type][1]);
ifempty2 = background.ifEmpty(deviationY + turnIsempty[type][4], deviationX + turnIsempty[type][3]);
if (ifempty1 == true && ifempty2 == true)
{
ifTurnIsEmpty = true;
}
break;
case 0:
case 1:
case 2:
case 4:
case 7:
case 16:
case 17:
ifempty1 = false;
ifempty2 = false;
ifempty3 = false;
ifempty1 = background.ifEmpty(deviationY + turnIsempty[type][2], deviationX + turnIsempty[type][1]);
ifempty2 = background.ifEmpty(deviationY + turnIsempty[type][4], deviationX + turnIsempty[type][3]);
ifempty3 = background.ifEmpty(deviationY + turnIsempty[type][6], deviationX + turnIsempty[type][5]);
if (ifempty1 == true && ifempty2 == true && ifempty3 == true)
{
ifTurnIsEmpty = true;
}
break;
default:
break;
}
//ifTurnIsEmpty 为真时,表示方块可以旋转
if (ifTurnIsEmpty)
{
clear(deviationX, deviationY, type);
//根据方块的编号,确定旋转之后的方块编号,进而画出旋转之后的方块
//旋转之后,同时要改变 Shap 类中的 number
switch (type)
{
//下面的是:type + 1
case 0:
case 1:
case 2:
case 4:
case 5:
case 6:
case 8:
case 9:
case 10:
case 12:
case 14:
case 16:
blockNumber1 = type + 1;
break;
//下面的是:type - 3
case 3:
case 7:
case 11:
blockNumber1 = type - 3;
break;
//下面的是:type - 1
case 13:
case 15:
case 17:
blockNumber1 = type - 1;
break;
//下面的是:type不变
case 18:
break;
default:
break;
}
draw(deviationX, deviationY, blockNumber1, color1);
}
}
//方块自由下落
bool Shap::down()
{
bool ifempty1, ifempty2, ifempty3, ifempty4; //每个方块由4个小方块构成
//竖直方向总共有24格,因为最底下一格是边界,所以是0——22,总共23格是游戏区域
bool flagIfDown = false; //该方块能否下落
//然后判断该方块能否下落,如果能,则再重新画一个下落一个后的方块
switch (blockNumber1)
{
case 17:
ifempty1 = false;
ifempty1 = background.ifEmpty(nowY / 31 + moveDown[blockNumber1][2], nowX / 31 + moveDown[blockNumber1][1]);
if (ifempty1 == true) {
flagIfDown = true;
}
break;
case 1:
case 3:
case 5:
case 7:
case 9:
case 11:
case 13:
case 15:
case 18:
ifempty1 = false;
ifempty2 = false;
ifempty1 = background.ifEmpty(nowY / 31 + moveDown[blockNumber1][2], nowX / 31 + moveDown[blockNumber1][1]);
ifempty2 = background.ifEmpty(nowY / 31 + moveDown[blockNumber1][4], nowX / 31 + moveDown[blockNumber1][3]);
if (ifempty1 == true && ifempty2 == true)
{
flagIfDown = true;
}
break;
case 0:
case 2:
case 4:
case 6:
case 8:
case 10:
case 12:
case 14:
ifempty1 = false;
ifempty2 = false;
ifempty3 = false;
ifempty1 = background.ifEmpty(nowY / 31 + moveDown[blockNumber1][2], nowX / 31 + moveDown[blockNumber1][1]);
ifempty2 = background.ifEmpty(nowY / 31 + moveDown[blockNumber1][4], nowX / 31 + moveDown[blockNumber1][3]);
ifempty3 = background.ifEmpty(nowY / 31 + moveDown[blockNumber1][6], nowX / 31 + moveDown[blockNumber1][5]);
if (ifempty1 == true && ifempty2 == true && ifempty3 == true)
{
flagIfDown = true;
}
break;
case 16:
ifempty1 = false;
ifempty2 = false;
ifempty3 = false;
ifempty4 = false;
ifempty1 = background.ifEmpty(nowY / 31 + moveDown[blockNumber1][2], nowX / 31 + moveDown[blockNumber1][1]);
ifempty2 = background.ifEmpty(nowY / 31 + moveDown[blockNumber1][4], nowX / 31 + moveDown[blockNumber1][3]);
ifempty3 = background.ifEmpty(nowY / 31 + moveDown[blockNumber1][6], nowX / 31 + moveDown[blockNumber1][5]);
ifempty4 = background.ifEmpty(nowY / 31 + moveDown[blockNumber1][8], nowX / 31 + moveDown[blockNumber1][7]);
if (ifempty1 == true && ifempty2 == true && ifempty3 == true && ifempty4 == true
)
{
flagIfDown = true;
}
break;
default:
break;
}
if (flagIfDown == true) {
clear(nowX / 31, nowY / 31, blockNumber1);
draw(nowX / 31, nowY / 31 + 1, blockNumber1, color1);
}
return flagIfDown;
}
//传入的参数是 4 * 4 方框左上角相对于原点的偏移量
void Shap::clear(int deviationX, int deviationY, int type)
{
//在地图上标记该点,//用每一个小方格的左上角的坐标来代替该小方块的坐标,这里记录的是偏移的格数
//因为background中的数组是第一个元素是行,第二个元素是列,所以第一个元素对应坐标y,第二个元素对应坐标x
background.setBackgroundFalse(deviationY + site[type][2], deviationX + site[type][1]);
background.setBackgroundFalse(deviationY + site[type][4], deviationX + site[type][3]);
background.setBackgroundFalse(deviationY + site[type][6], deviationX + site[type][5]);
background.setBackgroundFalse(deviationY + site[type][8], deviationX + site[type][7]);
background.setColors(deviationY + site[type][2], deviationX + site[type][1], "0xEDECEC");
background.setColors(deviationY + site[type][4], deviationX + site[type][3], "0xEDECEC");
background.setColors(deviationY + site[type][6], deviationX + site[type][5], "0xEDECEC");
background.setColors(deviationY + site[type][8], deviationX + site[type][7], "0xEDECEC");
setfillcolor(0xEDECEC);
solidrectangle(nowX + 31 * site[type][1] + 1.5, nowY + 31 * site[type][2] + 1.5, nowX + 31 * site[type][1] + 1.5 + 28, nowY + 31 * site[type][2] + 1.5 + 28);
solidrectangle(nowX + 31 * site[type][3] + 1.5, nowY + 31 * site[type][4] + 1.5, nowX + 31 * site[type][3] + 1.5 + 28, nowY + 31 * site[type][4] + 1.5 + 28);
solidrectangle(nowX + 31 * site[type][5] + 1.5, nowY + 31 * site[type][6] + 1.5, nowX + 31 * site[type][5] + 1.5 + 28, nowY + 31 * site[type][6] + 1.5 + 28);
solidrectangle(nowX + 31 * site[type][7] + 1.5, nowY + 31 * site[type][8] + 1.5, nowX + 31 * site[type][7] + 1.5 + 28, nowY + 31 * site[type][8] + 1.5 + 28);
}
//设置方块的颜色
void Shap::setColor(string newColor)
{
//对应的颜色分别为 红, 橙, 黄, 绿,青,蓝,紫
if (newColor == "0x5555FF") {
setfillcolor(0x5555FF);
}
else if (newColor == "0xEBACD2")
{
setfillcolor(0xEBACD2);
}
else if (newColor == "0x55FFFF")
{
setfillcolor(0x55FFFF);
}
else if (newColor == "0x55FF55")
{
setfillcolor(0x55FF55);
}
else if (newColor == "0xFFFF55")
{
setfillcolor(0xFFFF55);
}
else if (newColor == "0xFF5555")
{
setfillcolor(0xFF5555);
}
else
{
setfillcolor(0xAA00AA);
}
}
//检查是否要对已经满行的方块进行消除
void Shap::inspect()
{
//检查哪些行已经满了
bool ifHaveFull = false;
int tempflag;
int sumLine = 0;
int lines[23];
for (int i = 22; i >= 0; i--)
{
tempflag = 1;
for (int j = 1; j < 14; j++)
{
tempflag *= background.ifFull(i, j);
}
if (tempflag == 1)
{
ifHaveFull = true;
lines[sumLine] = i;
cout << lines[sumLine] << endl;
sumLine++;
}
}
eliminateLine += sumLine; //增加以消除的总行数
if (sumLine == 1)
{
sumScore += 100;
}
else if (sumLine == 2)
{
sumScore += 300;
}
else if (sumLine == 3)
{
sumScore += 500;
}
else if (sumLine == 4)
{
sumScore += 800;
}
//更改最高分MaxScore的值
int toIntMaxScore = atoi(maxScore.c_str());
cout << "toIntMaxScore==" << toIntMaxScore << endl;
cout << "sumScore ==" << sumScore << endl;
if (sumScore >= toIntMaxScore)
{
toIntMaxScore = sumScore;
cout << "toIntMaxScore2 ==" << toIntMaxScore << endl;
maxScore = to_string(sumScore); //更改最高分对应的字符串
cout << "StringMaxScore==" << maxScore << endl;
//当最高分改变时,立即把最高分存进文件中去
fstream fileAccount;
if (accountIndex != 0)
{
int accountNumber;
//得到账号个数
fileAccount.open(fileAccountNumber, ios_base::in);
fileAccount >> accountNumber;
fileAccount.close();
//更改最高分
//从文件中读取最高分,组成一个字符串数组
string *p = new string[accountNumber]; //动态创建字符串数组
fileAccount.open(fileMaxScore, ios_base::in);
for (int i = 0; i < accountNumber; i++) {
getline(fileAccount, p[i], '\n');
}
fileAccount.close();
//因为accountIndex从1开始,即第一个学生的下标为1,所以这里应该为:accountIndex - 1
p[accountIndex - 1] = maxScore; //将最高分赋值给字符串数组中对应的元素
//在将该字符串数组写入文件中
fileAccount.open(fileMaxScore, ios_base::out);
for (int i = 0; i < accountNumber; i++)
{
fileAccount << p[i];
fileAccount << endl;
}
fileAccount.close(); //关闭文件
}
}
//更改总分SumScore,和总行数eliminateLines的值
wchar_t tempSumScore[15];
wchar_t tempEliminateLine[15];
wchar_t tempMaxScore[15];
_stprintf_s(tempSumScore, _T("%d"), sumScore); // 将变量值格式化写入到中间变量 tempSumScore 中, _T("")是 unicode 的用法
_stprintf_s(tempEliminateLine, _T("%d"), eliminateLine);
cout << "aaaa" << toIntMaxScore << endl;
_stprintf_s(tempMaxScore, _T("%d"), toIntMaxScore);
settextstyle(25, 20, _T("宋体"), 0, 0, FW_EXTRABOLD, false, false, false); //设置字体样式:长,宽,字体名称,//有3个重载函数
settextcolor(0); //黑色
setbkcolor(0x5fe1f2); //右边框设置当前填充颜色 :黄色
setbkmode(OPAQUE); //用背景色填充文字的背景(抠图),更加美观
outtextxy(580, 420, tempMaxScore);
outtextxy(580, 520, tempSumScore);
outtextxy(580, 620, tempEliminateLine);
if (ifHaveFull == true)
{
//删除已经满了的一行
for (int i = 0; i < sumLine; i++) //需要删除多少行,该函数执行多少遍
{
if (i != 0)
{
lines[i] = lines[i] + i; //因为是逐行消除,没消除一行之后,原来方格满了的一行下标会加一
}
//注意顺序,相改变颜色,在改变背景
//改变方格的颜色
int n;
for (int a = lines[i]; a > 0; a--)
{
for (int b = 1; b < 14; b++)
{
if (background.getColors(a - 1, b) == "0x5555FF")
{
n = 5592575;
}
else if (background.getColors(a - 1, b) == "0xEBACD2")
{
n = 15445202;
}
else if (background.getColors(a - 1, b) == "0x55FFFF")
{
n = 5636095;
}
else if (background.getColors(a - 1, b) == "0x55FF55")
{
n = 5635925;
}
else if (background.getColors(a - 1, b) == "0xFFFF55")
{
n = 16777045;
}
else if (background.getColors(a - 1, b) == "0xFF5555")
{
n = 16733525;
}
else if (background.getColors(a - 1, b) == "0xAA00AA")
{
n = 11141290;
}
else if (background.getColors(a - 1, b) == "0xEDECEC")
{
n = 15592684;
}
setfillcolor(n);
solidrectangle(b * 31 + 1.5, a * 31 + 1.5, b * 31 + 1.5 + 28, a * 31 + 1.5 + 28);
int temp1 = background.getXY(a - 1, b);
string temp2 = background.getColors(a - 1, b);
//Sleep(800);
background.setXY(a, b, temp1);
background.setColors(a, b, temp2);
}
}
}
}
}
//游戏结束时的界面
void Shap::gameOverUI()
{
graphdefaults(); //初始化绘图因子因为之前改变了原点坐标,对后续绘图可能会产生影响
setfillcolor(0xEDECEC); //比灰白更白一点
solidrectangle(73, 0, 476, 713); //宽:13格,每格24
settextstyle(45, 35, _T("宋体"), 0, 0, FW_EXTRABOLD, false, false, false); //设置字体样式:长,宽,字体名称,//有3个重载函数
setbkcolor(0xEDECEC); //设置字体的背景颜色(抠图)
settextcolor(0);
outtextxy(75, 200, _T("GAME OVER !"));
settextcolor(0xFF5555); //亮蓝
outtextxy(130, 370, _T("继续游戏"));
outtextxy(180, 500, _T("返回"));
MOUSEMSG m; // 定义鼠标消息
while (true)
{
m = GetMouseMsg();
if (m.x > 130 && m.x < 455 && m.y > 370 && m.y < 410)
{
setfillcolor(0x55FF55);
solidcircle(100, 387, 20);
solidcircle(440, 387, 20);
//鼠标点击事件: 点击继续游戏
//如果鼠标左键弹起消息(鼠标左键点击了)
if (m.uMsg == WM_LBUTTONUP) {
gameoverChooseFlag = 1; //选择了继续游戏,赋值为1
break; //跳出循环,gameOver函数执行完毕
}
}
else if (m.x > 180 && m.x < 380 && m.y > 500 && m.y < 540)
{
setfillcolor(0x55FF55);
solidcircle(150, 517, 20);
solidcircle(345, 517, 20);
//鼠标点击事件: 点击返回(返回主界面)
//如果鼠标左键弹起消息(鼠标左键点击了)
if (m.uMsg == WM_LBUTTONUP) {
gameoverChooseFlag = 2; //选择了返回,赋值为2
break; //跳出循环,gameOver函数执行完毕
}
}
else
{
setfillcolor(0xEDECEC);
solidcircle(100, 387, 20);
solidcircle(440, 387, 20);
solidcircle(150, 517, 20);
solidcircle(345, 517, 20);
}
}
}
//判断游戏是否结束,当方块到达顶端时,游戏结束
bool Shap::ifGameOver(int type, string newColor)
{
//Ox, Oy,表示 4 * 4 方框的左上角的坐标
int Ox, Oy;
Ox = 5 * 31;
Oy = 0 * 31;
int flag1, flag2, flag3, flag4;
flag1 = background.getXY(0 + site[type][2], 5 + site[type][1]);
flag2 = background.getXY(0 + site[type][4], 5 + site[type][3]);
flag3 = background.getXY(0 + site[type][6], 5 + site[type][5]);
flag4 = background.getXY(0 + site[type][8], 5 + site[type][7]);
//如果这4个方块中有一个已经存在小方块了,说明和即将出现的方块会重叠,说明游戏结束
if (flag1 == 1 || flag2 == 1 || flag3 == 1 || flag4 == 1)
{
return true;
}
else
{
return false;
}
}
//Tetris::Tetris()
//{
// //初始化640 * 480 的绘图屏幕,并禁用关闭窗口按钮
// initgraph(800, 744, SHOWCONSOLE | NOCLOSE);
//
// // 设置背景色为白色
// setbkcolor(0xFFFFFF);
// // 用背景色清空屏幕
// cleardevice();
//
// HWND hwnd;
// // 1.设置窗口句柄变量保存窗口信息
// hwnd = GetHWnd();
// // 2.获取窗口句柄
// SetWindowText(hwnd, _T("俄罗斯方块"));
//
// ////画两个矩形框
// //setfillcolor(0xd8dbdc); //左边框设置当前填充颜色 : 灰色
// //fillrectangle(0, 0, 550, 600); //画矩形框,4个参数分别为左上右下的坐标
// //setfillcolor(0x5fe1f2); //右边框设置当前填充颜色 :黄色
// //fillrectangle(550, 0, 800, 600);
// ////左边矩形框
// ////输出字符串
// //settextcolor(0x0000AA); //设置文字颜色:红色
// //setbkcolor(0xd8dbdc); //重新设置背景色,设置
// //setbkmode(OPAQUE); //用背景色填充文字的背景(抠图),更加美观
// //settextstyle(80, 55, _T("宋体"), 0, 0, FW_EXTRABOLD, false, false, false); //设置字体样式:长,宽,字体名称,//有3个重载函数
// //TCHAR s1[] = _T("Tetris");
// //outtextxy(110, 90, s1); //在指定位置输出字符串:x, y, 字符串
// ////输出选项
// //settextstyle(30, 30, _T("宋体"));
// //TCHAR s2[] = _T("Just StartGame"); //快速开始游戏
// //outtextxy(65, 225, s2); //在指定位置输出字符串:x, y, 字符串
// //TCHAR s3[] = _T("Regist"); //注册
// //outtextxy(180, 300, s3); //在指定位置输出字符串:x, y, 字符串
// //TCHAR s4[] = _T("Log in"); //登录
// //outtextxy(180, 375, s4); //在指定位置输出字符串:x, y, 字符串
// //TCHAR s5[] = _T("Exit"); //退出
// //outtextxy(210, 450, s5); //在指定位置输出字符串:x, y, 字符串
// ////右边矩形框
// //settextcolor(0xFF5555); //设置文字颜色:亮蓝
// //setbkcolor(0x5fe1f2); //重新设置背景色:黄色
// //setbkmode(OPAQUE); //用背景色填充文字的背景(抠图),更加美观
// //settextstyle(20, 20, _T("宋体"));
// //TCHAR sRight1[] = _T("Next:");
// //outtextxy(580, 50, sRight1);
// //TCHAR sRight2[] = _T("Score:");
// //outtextxy(580, 250, sRight2);
// //TCHAR sRight3[] = _T("Max Score:");
// //outtextxy(580, 425, sRight3);
// //MOUSEMSG m; // 定义鼠标消息
// //
// //while (true)
// //{
// // m = GetMouseMsg();
// // //圆点的y坐标同一与相对的字符串的y坐标加15
// // //左边圆点的x减30, 右边加30
// // //字体的高度为30