C语言小程序——推箱子(窄字符Version)
推箱子.c
1 #include <stdio.h> 2 #include <conio.h> 3 #include <stdlib.h> 4 #include <Windows.h> 5 #include "Game.h" 6 7 #define N 100 /* 二维数组最大100*100 */ 8 #define NTAB 24 /* 调整界面位置 */ 9 #define YES 1 /* 可以移动 */ 10 #define NO 0 /* 不能移动 */ 11 #define MAP_MAX 6 /* 最大关卡数 */ 12 13 int suc = 0;/* 通关判定 */ 14 15 void OpenMap(FILE **fp, int map); /* 打开地图文件 */ 16 void InitMap(char (*map)[N]); /* 地图初始化 */ 17 void JudgeFopen_s(errno_t err); /* 判断文件打开是否成功 */ 18 void ReadMap(char (*map)[N], FILE *fp, int *x, int *y, int *suc); /* 读取地图 */ 19 void DisplyMap(char (*map)[N]); /* 打印地图 */ 20 21 void PlayerMove(int move, int *x, int *y, char (*map)[N]); /* 玩家移动*/ 22 void JudgePlayerMove(int move, int *x, int *y, char (*map)[N]); /* 判断玩家移动方向 */ 23 int JudgeBarr(int move, int *x, int *y, char(*map)[N]); /* 判断玩家移动方向上是否有障碍物 */ 24 int JudgeBarrType(int move, int *x, int *y, char(*map)[N]); /* 判断障碍物类别 */ 25 void BoxMove(int move, int *x, int *y, char(*map)[N]); /* 箱子移动 */ 26 int IsBox(int move, int *x, int *y, char(*map)[N]); /* 判断是否推动的是箱子*/ 27 int JudgeBoxBoun(int move, int *x, int *y, char(*map)[N]); /* 判断箱子能否被推动 */ 28 void RefreshBox(int move, int *x, int *y, char(*map)[N]); /* 更新移动后的箱子的位置 */ 29 void RefreshPlayer(int move, int *x, int *y, char(*map)[N]);/* 更新移动后的玩家位置 */ 30 int JudgePlayerOri(int move, int *x, int *y, char(*map)[N]);/* 判断玩家原位置是不是空地 */ 31 int JudgeBoxDes(int move, int *x, int *y, char(*map)[N]); /* 判断箱子移动后的位置是不是目标点 */ 32 int JudgeBoxOri(int move, int *x, int *y, char(*map)[N]); /* 判断箱子原位置是不是目标点 */ 33 int JudgePlayerDes(int move, int *x, int *y, char(*map)[N]);/* 判断玩家移动后的位置是不是目标点 */ 34 int JudgeSuc(FILE **fp, int *suc, int *num, char (*map)[N], int *x, int *y); /* 判断是否通关 */ 35 void SucCount(int move, int *x, int *y, char(*map)[N], int *suc); /* 通关条件计数 */ 36 37 38 /* Game: 推箱子 */ 39 /* WASD移动 */ 40 int main() 41 { 42 FILE *fp; 43 int order; /* 指令 */ 44 int move; /* 移动方向 */ 45 char ss[N][N]; /* 地图 */ 46 int x, y; /* 玩家坐标 */ 47 int level = 1; /* 当前关卡数 */ 48 49 OpenMap(&fp, level); /* 打开存储地图的文件 */ 50 51 HideCursor(); /* 隐藏光标 */ 52 InitMap(ss); /* 初始化地图 */ 53 ReadMap(ss, fp, &x, &y, &suc);/* 读取地图 */ 54 DisplyMap(ss); /* 打印地图 */ 55 while (1) 56 { 57 order = _getch(); /* 接收指令 */ 58 move = MoveByWasd(order); /* 判断移动方向 */ 59 JudgePlayerMove(move, &x, &y, ss); /* 玩家移动 */ 60 JudgeSuc(&fp, &suc, &level, ss, &x, &y); /* 判断是否通关 */ 61 } 62 63 return 0; 64 } 65 66 /* Function: 打开地图文件*/ 67 void OpenMap(FILE **fp, int map) 68 { 69 errno_t err; 70 71 switch(map) 72 { 73 case 1: 74 { 75 err = fopen_s(fp, "m1.txt", "r"); /* 文件打开成功返回0值,否则返回非0值*/ 76 JudgeFopen_s(err); /* 判断文件打开是否成功 */ 77 break; 78 } 79 case 2: 80 { 81 err = fopen_s(fp, "m2.txt", "r"); 82 JudgeFopen_s(err); 83 break; 84 } 85 case 3: 86 { 87 err = fopen_s(fp, "m3.txt", "r"); 88 JudgeFopen_s(err); 89 break; 90 } 91 case 4: 92 { 93 err = fopen_s(fp, "m4.txt", "r"); 94 JudgeFopen_s(err); 95 break; 96 } 97 case 5: 98 { 99 err = fopen_s(fp, "m5.txt", "r"); 100 JudgeFopen_s(err); 101 break; 102 } 103 case 6: 104 { 105 err = fopen_s(fp, "m6.txt", "r"); 106 JudgeFopen_s(err); 107 break; 108 } 109 default: 110 { 111 system("cls"); 112 printf(" 没有更多了关卡了,即将退出游戏"); 113 Sleep(3000); 114 exit(0); 115 } 116 } 117 } 118 /* Function: 通关条件计数 */ 119 void SucCount(int move, int *x, int *y, char(*map)[N],int *suc) 120 { 121 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 122 { 123 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 124 { 125 return; 126 } 127 else /* 箱子移动后的位置是目标点*/ 128 { 129 (*suc)--; 130 return; 131 } 132 } 133 else /* 箱子原位置是目标点 */ 134 { 135 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 136 { 137 (*suc)++; 138 return; 139 } 140 else /* 箱子移动后的位置是目标点*/ 141 { 142 return; 143 } 144 } 145 } 146 147 /* Function: 判断是否通关 */ 148 int JudgeSuc(FILE **fp, int *suc, int *num, char (*map)[N], int *x, int *y) 149 { 150 if ((*suc) == 0) 151 { 152 (*suc) = 0; /* 关卡通关计数重置 */ 153 (*num)++; /* 关卡数+1 */ 154 155 system("cls"); 156 if ((*num) <= MAP_MAX) 157 { 158 printf(" 通关!即将进入第下一关"); 159 } 160 else 161 { 162 system("cls"); 163 printf(" 没有更多了关卡了,即将退出游戏"); 164 Sleep(3000); 165 exit(0); 166 } 167 168 Sleep(1000); 169 system("cls"); 170 171 OpenMap(fp,*num); /* 打开地图文件 */ 172 InitMap(map); /* 初始化地图 */ 173 ReadMap(map, *fp, x, y, suc);/* 读取地图 */ 174 DisplyMap(map); /* 打印地图 */ 175 176 return YES; /* 通关 */ 177 } 178 else 179 { 180 return NO; 181 } 182 } 183 /* Function: 玩家移动*/ 184 void PlayerMove(int move, int *x, int *y, char (*map)[N]) 185 { 186 switch(move) 187 { 188 case UP: 189 { 190 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 191 { 192 gotoxy(*x+NTAB, *y);printf(" ");(*y)--;gotoxy(*x+NTAB, *y);printf("I");break;/* 玩家移动 */ 193 } 194 else /* 玩家原位置是目标点 */ 195 { 196 gotoxy(*x+NTAB, *y);printf("*");(*y)--;gotoxy(*x+NTAB, *y);printf("I");break; /* 玩家移动 */ 197 } 198 } 199 case DOWN: 200 { 201 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 202 { 203 gotoxy(*x+NTAB, *y);printf(" ");(*y)++;gotoxy(*x+NTAB, *y);printf("I");break;/* 玩家移动 */ 204 } 205 else 206 { 207 gotoxy(*x+NTAB, *y);printf("*");(*y)++;gotoxy(*x+NTAB, *y);printf("I");break;/* 玩家移动 */ 208 } 209 } 210 case LEFT: 211 { 212 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 213 { 214 gotoxy(*x+NTAB, *y);printf(" ");(*x)--;gotoxy(*x+NTAB, *y);printf("I");break; /* 玩家移动 */ 215 } 216 else 217 { 218 gotoxy(*x+NTAB, *y);printf("*");(*x)--;gotoxy(*x+NTAB, *y);printf("I");break; /* 玩家移动 */ 219 } 220 } 221 case RIGHT: 222 { 223 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 224 { 225 gotoxy(*x+NTAB, *y);printf(" ");(*x)++;gotoxy(*x+NTAB, *y);printf("I");break; /* 玩家移动 */ 226 } 227 else 228 { 229 gotoxy(*x+NTAB, *y);printf("*");(*x)++;gotoxy(*x+NTAB, *y);printf("I");break; /* 玩家移动 */ 230 } 231 } 232 default: break; 233 } 234 } 235 /* Function: 判断玩家移动后的位置是不是目标点 */ 236 int JudgePlayerDes(int move, int *x, int *y, char(*map)[N]) 237 { 238 switch(move) 239 { 240 case UP: 241 { 242 if (map[(*y)-1][*x] == '*') /* 移动后的位置是目标点 */ 243 { 244 return YES; 245 } 246 else 247 { 248 return NO; 249 } 250 } 251 case DOWN: 252 { 253 if (map[(*y)+1][*x] == '*') 254 { 255 return YES; 256 } 257 else 258 { 259 return NO; 260 } 261 } 262 case LEFT: 263 { 264 if (map[*y][(*x)-1] == '*') 265 { 266 return YES; 267 } 268 else 269 { 270 return NO; 271 } 272 } 273 case RIGHT: 274 { 275 if (map[*y][(*x)+1] == '*') 276 { 277 return YES; 278 } 279 else 280 { 281 return NO; 282 } 283 } 284 default: return NO; 285 } 286 } 287 288 /* Function: 判断箱子原位置是不是目标点 */ 289 int JudgeBoxOri(int move, int *x, int *y, char(*map)[N]) 290 { 291 switch(move) 292 { 293 case UP: 294 { 295 if (map[(*y)-1][*x] == '$') /* 箱子原位置是目标点 */ 296 { 297 return NO; 298 } 299 else 300 { 301 return YES; 302 } 303 } 304 case DOWN: 305 { 306 if (map[(*y)+1][*x] == '$') /* 箱子原位置是目标点 */ 307 { 308 return NO; 309 } 310 else 311 { 312 return YES; 313 } 314 } 315 case LEFT: 316 { 317 if (map[*y][(*x)-1] == '$') /* 箱子原位置是目标点 */ 318 { 319 return NO; 320 } 321 else 322 { 323 return YES; 324 } 325 } 326 case RIGHT: 327 { 328 if (map[*y][(*x)+1] == '$') /* 箱子原位置是目标点 */ 329 { 330 return NO; 331 } 332 else 333 { 334 return YES; 335 } 336 } 337 default: return NO; 338 } 339 } 340 /* Function: 判断箱子移动后的位置是不是目标点 */ 341 int JudgeBoxDes(int move, int *x, int *y, char(*map)[N]) 342 { 343 switch(move) 344 { 345 case UP: 346 { 347 if (map[(*y)-2][*x] == '*') /* 箱子移动后是目标点 */ 348 { 349 return NO; 350 } 351 else /* 箱子移动后不是目标点 */ 352 { 353 return YES; 354 } 355 } 356 case DOWN: 357 { 358 if (map[(*y)+2][*x] == '*') 359 { 360 return NO; 361 } 362 else 363 { 364 return YES; 365 } 366 } 367 case LEFT: 368 { 369 if (map[*y][(*x)-2] == '*') 370 { 371 return NO; 372 } 373 else 374 { 375 return YES; 376 } 377 } 378 case RIGHT: 379 { 380 if (map[*y][(*x)+2] == '*') 381 { 382 return NO; 383 } 384 else 385 { 386 return YES; 387 } 388 } 389 default: return NO; 390 } 391 } 392 /* Function: 判断障碍物类别 */ 393 int JudgeBarrType(int move, int *x, int *y, char(*map)[N]) 394 { 395 switch (move) 396 { 397 case UP: 398 { 399 if (map[(*y)-1][*x] == '#') /* 如果目标地点是墙壁 */ 400 { 401 return NO; /* 无法移动 */ 402 } 403 else 404 { 405 return YES;/* 不是墙,需要进一步判断 */ 406 } 407 } 408 case DOWN: 409 { 410 if (map[(*y)+1][*x] == '#') 411 { 412 return NO; 413 } 414 else 415 { 416 return YES; 417 } 418 } 419 case LEFT: 420 { 421 if (map[*y][(*x)-1] == '#') 422 { 423 return NO; 424 } 425 else 426 { 427 return YES; 428 } 429 } 430 case RIGHT: 431 { 432 if (map[*y][(*x)+1] == '#') 433 { 434 return NO; 435 } 436 else 437 { 438 return YES; 439 } 440 } 441 default: return NO; 442 } 443 } 444 445 /* Function: 更新移动后的玩家位置 */ 446 void RefreshPlayer(int move, int *x, int *y, char(*map)[N]) 447 { 448 switch (move) 449 { 450 case UP: 451 { 452 if (JudgePlayerOri(move, x, y, map) == YES) /* 玩家原位置是空地 */ 453 { 454 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 455 { 456 map[*y][*x] = ' ';map[(*y)-1][*x] = '*';break; 457 } 458 else 459 { 460 map[*y][*x] = ' ';map[(*y)-1][*x] = 'I';break; 461 } 462 } 463 else /* 玩家原位置不是空地 */ 464 { 465 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 466 { 467 map[*y][*x] = '*';map[(*y)-1][*x] = '*';break; 468 } 469 else 470 { 471 map[*y][*x] = '*';map[(*y)-1][*x] = 'I';break; 472 } 473 } 474 } 475 case DOWN: 476 { 477 if (JudgePlayerOri(move, x, y, map) == YES) /* 玩家原位置是空地 */ 478 { 479 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 480 { 481 map[*y][*x] = ' ';map[(*y)+1][*x] = '*';break; 482 } 483 else 484 { 485 map[*y][*x] = ' ';map[(*y)+1][*x] = 'I';break; 486 } 487 } 488 else /* 玩家原位置不是空地 */ 489 { 490 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 491 { 492 map[*y][*x] = '*';map[(*y)+1][*x] = '*';break; 493 } 494 else 495 { 496 map[*y][*x] = '*';map[(*y)+1][*x] = 'I';break; 497 } 498 } 499 } 500 case LEFT: 501 { 502 if (JudgePlayerOri(move, x, y, map) == YES) /* 玩家原位置是空地 */ 503 { 504 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 505 { 506 map[*y][*x] = ' ';map[*y][(*x)-1] = '*';break; 507 } 508 else 509 { 510 map[*y][*x] = ' ';map[*y][(*x)-1] = 'I';break; 511 } 512 } 513 else /* 玩家原位置不是空地 */ 514 { 515 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 516 { 517 map[*y][*x] = '*';map[*y][(*x)-1] = '*';break; 518 } 519 else 520 { 521 map[*y][*x] = '*';map[*y][(*x)-1] = 'I';break; 522 } 523 } 524 } 525 case RIGHT: 526 { 527 if (JudgePlayerOri(move, x, y, map) == YES) /* 玩家原位置是空地 */ 528 { 529 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 530 { 531 map[*y][*x] = ' ';map[*y][(*x)+1] = '*';break; 532 } 533 else 534 { 535 map[*y][*x] = ' ';map[*y][(*x)+1] = 'I';break; 536 } 537 } 538 else /* 玩家原位置不是空地 */ 539 { 540 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 541 { 542 map[*y][*x] = '*';map[*y][(*x)+1] = '*';break; 543 } 544 else 545 { 546 map[*y][*x] = '*';map[*y][(*x)+1] = 'I';break; 547 } 548 } 549 } 550 } 551 } 552 553 /* Function: 判断玩家原位置是不是空地*/ 554 int JudgePlayerOri(int move, int *x, int *y, char(*map)[N]) 555 { 556 if (map[*y][*x] == '*') 557 { 558 return NO; 559 } 560 else 561 { 562 return YES; /* 是空地 */ 563 } 564 } 565 /* Function: 判断箱子移动之后的位置是不是目标点 */ 566 567 568 /* FunctionL 更新移动后的箱子位置 */ 569 void RefreshBox(int move, int *x, int *y, char(*map)[N]) 570 { 571 switch (move) 572 { 573 case UP: 574 { 575 SucCount(move, x, y, map, &suc); /* 通关条件计数 */ 576 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 577 { 578 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 579 { 580 map[(*y)-1][*x] = ' ';map[(*y)-2][*x] = '@';break; 581 } 582 else 583 { 584 map[(*y)-1][*x] = ' ';map[(*y)-2][*x] = '$';break; 585 } 586 } 587 else /* 箱子原位置是目标点 */ 588 { 589 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 590 { 591 map[(*y)-1][*x] = '*';map[(*y)-2][*x] = '@';break; 592 } 593 else 594 { 595 map[(*y)-1][*x] = '*';map[(*y)-2][*x] = '$';break; 596 } 597 } 598 } 599 case DOWN: 600 { 601 SucCount(move, x, y, map, &suc); /* 通关条件计数 */ 602 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 603 { 604 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 605 { 606 map[(*y)+1][*x] = ' ';map[(*y)+2][*x] = '@';break; 607 } 608 else 609 { 610 map[(*y)+1][*x] = ' ';map[(*y)+2][*x] = '$';break; 611 } 612 } 613 else /* 箱子原位置是目标点 */ 614 { 615 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 616 { 617 map[(*y)+1][*x] = '*';map[(*y)+2][*x] = '@';break; 618 } 619 else 620 { 621 map[(*y)+1][*x] = '*';map[(*y)+2][*x] = '$';break; 622 } 623 } 624 } 625 case LEFT: 626 { 627 SucCount(move, x, y, map, &suc); /* 通关条件计数 */ 628 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 629 { 630 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 631 { 632 map[*y][(*x)-1] = ' ';map[*y][(*x)-2] = '@';break; 633 } 634 else 635 { 636 map[*y][(*x)-1] = ' ';map[*y][(*x)-2] = '$';break; 637 } 638 } 639 else /* 箱子原位置是目标点 */ 640 { 641 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 642 { 643 map[*y][(*x)-1] = '*';map[*y][(*x)-2] = '@';break; 644 } 645 else 646 { 647 map[*y][(*x)-1] = '*';map[*y][(*x)-2] = '$';break; 648 } 649 } 650 } 651 652 case RIGHT: 653 { 654 SucCount(move, x, y, map, &suc); /* 通关条件计数 */ 655 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 656 { 657 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 658 { 659 map[*y][(*x)+1] = ' ';map[*y][(*x)+2] = '@';break; 660 } 661 else 662 { 663 map[*y][(*x)+1] = ' ';map[*y][(*x)+2] = '$';break; 664 } 665 } 666 else /* 箱子原位置是目标点 */ 667 { 668 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 669 { 670 map[*y][(*x)+1] = '*';map[*y][(*x)+2] = '@';break; 671 } 672 else 673 { 674 map[*y][(*x)+1] = '*';map[*y][(*x)+2] = '$';break; 675 } 676 } 677 } 678 } 679 } 680 /* Functioni: 判断箱子能否被推动 */ 681 int JudgeBoxBoun(int move, int *x, int *y, char(*map)[N]) 682 { 683 switch (move) 684 { 685 case UP: 686 { 687 if (map[(*y)-2][*x] == '#' || map[(*y)-2][*x] == '@' || map[(*y)-2][*x] == '$') /* 箱子被推动的方向 是墙壁,或者是另一个箱子*/ 688 { 689 return NO; 690 } 691 else 692 { 693 return YES; 694 } 695 } 696 case DOWN: 697 { 698 if (map[(*y)+2][*x] == '#' || map[(*y)+2][*x] == '@' || map[(*y)+2][*x] == '$') 699 { 700 return NO; 701 } 702 else 703 { 704 return YES; 705 } 706 } 707 case LEFT: 708 { 709 if (map[*y][(*x)-2] == '#' || map[*y][(*x)-2] == '@' || map[*y][(*x)-2] == '$') 710 { 711 return NO; 712 } 713 else 714 { 715 return YES; 716 } 717 } 718 case RIGHT: 719 { 720 if (map[*y][(*x)+2] == '#' || map[*y][(*x)+2] == '@' || map[*y][(*x)+2] == '$') 721 { 722 return NO; 723 } 724 else 725 { 726 return YES; 727 } 728 } 729 default: return NO; 730 } 731 } 732 733 /* Function: 判断移动方向上是否有箱子 */ 734 int IsBox(int move, int *x, int *y, char(*map)[N]) 735 { 736 switch (move) 737 { 738 case UP: 739 { 740 if (map[(*y)-1][*x] == '@' || map[(*y)-1][*x] == '$') /* 如果是在空地上的箱子 或 在目标点上的箱子 */ 741 { 742 return YES; 743 } 744 else 745 { 746 return NO; 747 } 748 } 749 case DOWN: 750 { 751 if (map[(*y)+1][*x] == '@' || map[(*y)+1][*x] == '$') 752 { 753 return YES; 754 } 755 else 756 { 757 return NO; 758 } 759 } 760 case LEFT: 761 { 762 if (map[*y][(*x)-1] == '@' || map[*y][(*x)-1] == '$') 763 { 764 return YES; 765 } 766 else 767 { 768 return NO; 769 } 770 } 771 case RIGHT: 772 { 773 if (map[*y][(*x)+1] == '@' || map[*y][(*x)+1] == '$') 774 { 775 return YES; 776 } 777 else 778 { 779 return NO; 780 } 781 } 782 default: return NO; 783 784 } 785 } 786 787 /* Function: 箱子移动 */ 788 void BoxMove(int move, int *x, int *y, char(*map)[N]) 789 { 790 switch (move) 791 { 792 case UP: 793 { 794 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 795 { 796 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 797 { 798 gotoxy(*x+NTAB, (*y)-1);printf(" ");gotoxy(*x+NTAB, (*y)-2);printf("@");break; /* 箱子移动 */ 799 } 800 else /* 箱子移动后的位置是目标点 */ 801 { 802 gotoxy(*x+NTAB, (*y)-1);printf(" ");gotoxy(*x+NTAB, (*y)-2);printf("$");break; /* 箱子移动 */ 803 } 804 } 805 else /* 箱子原位置是目标点 */ 806 { 807 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 808 { 809 gotoxy(*x+NTAB, (*y)-1);printf("*");gotoxy(*x+NTAB, (*y)-2);printf("@");break; /* 箱子移动 */ 810 } 811 else 812 { 813 gotoxy(*x+NTAB, (*y)-1);printf("*");gotoxy(*x+NTAB, (*y)-2);printf("$");break; /* 箱子移动 */ 814 } 815 } 816 } 817 case DOWN: 818 { 819 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 820 { 821 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 822 { 823 gotoxy(*x+NTAB, (*y)+1);printf(" ");gotoxy(*x+NTAB, (*y)+2);printf("@");break; /* 箱子移动 */ 824 } 825 else /* 箱子移动后的位置是目标点 */ 826 { 827 gotoxy(*x+NTAB, (*y)+1);printf(" ");gotoxy(*x+NTAB, (*y)+2);printf("$");break; /* 箱子移动 */ 828 } 829 } 830 else /* 箱子原位置是目标点 */ 831 { 832 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 833 { 834 gotoxy(*x+NTAB, (*y)+1);printf("*");gotoxy(*x+NTAB, (*y)+2);printf("@");break; /* 箱子移动 */ 835 } 836 else 837 { 838 gotoxy(*x+NTAB, (*y)+1);printf("*");gotoxy(*x+NTAB, (*y)+2);printf("$");break; /* 箱子移动 */ 839 } 840 } 841 } 842 case LEFT: 843 { 844 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 845 { 846 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 847 { 848 gotoxy((*x+NTAB)-1, *y);printf(" ");gotoxy((*x+NTAB)-2, *y);printf("@");break; /* 箱子移动 */ 849 } 850 else /* 箱子移动后的位置是目标点 */ 851 { 852 gotoxy((*x+NTAB)-1, *y);printf(" ");gotoxy((*x+NTAB)-2, *y);printf("$");break; /* 箱子移动 */ 853 } 854 } 855 else /* 箱子原位置是目标点 */ 856 { 857 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 858 { 859 gotoxy((*x+NTAB)-1, *y);printf("*");gotoxy((*x+NTAB)-2, *y);printf("@");break; /* 箱子移动 */ 860 } 861 else 862 { 863 gotoxy((*x+NTAB)-1, *y);printf("*");gotoxy((*x+NTAB)-2, *y);printf("$");break; /* 箱子移动 */ 864 } 865 } 866 } 867 case RIGHT: 868 { 869 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 870 { 871 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 872 { 873 gotoxy((*x+NTAB)+1, *y);printf(" ");gotoxy((*x+NTAB)+2, *y);printf("@");break; /* 箱子移动 */ 874 } 875 else /* 箱子移动后的位置是目标点 */ 876 { 877 gotoxy((*x+NTAB)+1, *y);printf(" ");gotoxy((*x+NTAB)+2, *y);printf("$");break; /* 箱子移动 */ 878 } 879 } 880 else /* 箱子原位置是目标点 */ 881 { 882 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 883 { 884 gotoxy((*x+NTAB)+1, *y);printf("*");gotoxy((*x+NTAB)+2, *y);printf("@");break; /* 箱子移动 */ 885 } 886 else 887 { 888 gotoxy((*x+NTAB)+2, *y);printf("*");gotoxy((*x+NTAB)+2, *y);printf("$");break; /* 箱子移动 */ 889 } 890 } 891 } 892 default: break; 893 } 894 } 895 896 /* Function:判断玩家移动方向上是否有障碍物 */ 897 int JudgeBarr(int move, int *x, int *y, char(*map)[N]) 898 { 899 switch (move) 900 { 901 case UP: 902 { 903 if (map[(*y)-1][*x] == '#' || map[(*y)-1][*x] == '@' || map[(*y)-1][*x] == '*' || map[(*y)-1][*x] == '$') /* 如果是墙壁、箱子、目标点 */ 904 { 905 return NO; /* 需要进一步判断 */ 906 } 907 else 908 { 909 return YES; /* 没有障碍物 */ 910 } 911 } 912 case DOWN: 913 { 914 if (map[(*y)+1][*x] == '#' || map[(*y)+1][*x] == '@' || map[(*y)+1][*x] == '*' || map[(*y)+1][*x] == '$') 915 { 916 return NO; 917 } 918 else 919 { 920 return YES; 921 } 922 } 923 case LEFT: 924 { 925 if (map[*y][(*x)-1] == '#' || map[*y][(*x)-1] == '@' || map[*y][(*x)-1] == '*' || map[*y][(*x)-1] == '$') 926 { 927 return NO; 928 } 929 else 930 { 931 return YES; 932 } 933 } 934 case RIGHT: 935 { 936 if (map[*y][(*x)+1] == '#' || map[*y][(*x)+1] == '@' || map[*y][(*x)+1] == '*' || map[*y][(*x)+1] == '$') 937 { 938 return NO; 939 } 940 else 941 { 942 return YES; 943 } 944 } 945 default: return NO; 946 } 947 } 948 949 /* Function:玩家移动 */ 950 void JudgePlayerMove(int move, int *x, int *y, char (*map)[N]) 951 { 952 switch (move) 953 { 954 case UP: 955 { 956 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 957 { 958 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 959 { /* 如果移动方向上是空地,那么就可以直接移动 */ 960 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 961 PlayerMove(move, x, y, map); /* 玩家移动 */ 962 break; 963 } 964 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 965 { 966 break; /* 无法移动 */ 967 } 968 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 969 { 970 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 971 { 972 BoxMove(move, x, y, map); 973 RefreshBox(move, x, y, map); 974 RefreshPlayer(move, x, y, map); 975 PlayerMove(move, x, y, map); 976 break; 977 } 978 else /* 箱子不能被推动 */ 979 { 980 break; 981 } 982 } 983 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 984 { 985 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 986 PlayerMove(move, x, y, map);/* 玩家移动 */ 987 break; 988 } 989 } 990 else /* 玩家原位置为目标点 */ 991 { 992 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 993 { /* 如果移动方向上是空地,那么就可以直接移动 */ 994 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 995 PlayerMove(move, x, y, map); /* 玩家移动 */ 996 break; 997 } 998 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 999 { 1000 break; /* 无法移动 */ 1001 } 1002 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1003 { 1004 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1005 { 1006 BoxMove(move, x, y, map); 1007 RefreshBox(move, x, y, map); 1008 RefreshPlayer(move, x, y, map); 1009 PlayerMove(move, x, y, map); 1010 break; 1011 } 1012 else /* 箱子不能被推动 */ 1013 { 1014 break; 1015 } 1016 } 1017 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1018 { 1019 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1020 PlayerMove(move, x, y, map);/* 玩家移动 */ 1021 break; 1022 } 1023 } 1024 } 1025 1026 case DOWN: 1027 { 1028 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 1029 { 1030 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 1031 { /* 如果移动方向上是空地,那么就可以直接移动 */ 1032 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 1033 PlayerMove(move, x, y, map); /* 玩家移动 */ 1034 break; 1035 } 1036 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 1037 { 1038 break; /* 无法移动 */ 1039 } 1040 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1041 { 1042 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1043 { 1044 BoxMove(move, x, y, map); 1045 RefreshBox(move, x, y, map); 1046 RefreshPlayer(move, x, y, map); 1047 PlayerMove(move, x, y, map); 1048 break; 1049 } 1050 else /* 箱子不能被推动 */ 1051 { 1052 break; 1053 } 1054 } 1055 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1056 { 1057 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1058 PlayerMove(move, x, y, map); /* 玩家移动 */ 1059 break; 1060 } 1061 } 1062 else 1063 { 1064 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 1065 { /* 如果移动方向上是空地,那么就可以直接移动 */ 1066 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 1067 PlayerMove(move, x, y, map); /* 玩家移动 */ 1068 break; 1069 } 1070 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 1071 { 1072 break; /* 无法移动 */ 1073 } 1074 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1075 { 1076 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1077 { 1078 BoxMove(move, x, y, map); 1079 RefreshBox(move, x, y, map); 1080 RefreshPlayer(move, x, y, map); 1081 PlayerMove(move, x, y, map); 1082 break; 1083 } 1084 else /* 箱子不能被推动 */ 1085 { 1086 break; 1087 } 1088 } 1089 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1090 { 1091 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1092 PlayerMove(move, x, y, map);/* 玩家移动 */ 1093 break; 1094 } 1095 } 1096 1097 case LEFT: 1098 { 1099 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 1100 { 1101 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 1102 { /* 如果移动方向上是空地,那么就可以直接移动 */ 1103 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 1104 PlayerMove(move, x, y, map); /* 玩家移动 */ 1105 break; 1106 } 1107 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 1108 { 1109 break; /* 无法移动 */ 1110 } 1111 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1112 { 1113 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1114 { 1115 BoxMove(move, x, y, map); 1116 RefreshBox(move, x, y, map); 1117 RefreshPlayer(move, x, y, map); 1118 PlayerMove(move, x, y, map); 1119 break; 1120 } 1121 else /* 箱子不能被推动 */ 1122 { 1123 break; 1124 } 1125 } 1126 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1127 { 1128 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1129 PlayerMove(move, x, y, map);/* 玩家移动 */ 1130 break; 1131 } 1132 } 1133 else 1134 { 1135 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 1136 { /* 如果移动方向上是空地,那么就可以直接移动 */ 1137 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 1138 PlayerMove(move, x, y, map); /* 玩家移动 */ 1139 break; 1140 } 1141 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 1142 { 1143 break; /* 无法移动 */ 1144 } 1145 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1146 { 1147 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1148 { 1149 BoxMove(move, x, y, map); 1150 RefreshBox(move, x, y, map); 1151 RefreshPlayer(move, x, y, map); 1152 PlayerMove(move, x, y, map); 1153 break; 1154 } 1155 else /* 箱子不能被推动 */ 1156 { 1157 break; 1158 } 1159 } 1160 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1161 { 1162 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1163 PlayerMove(move, x, y, map);/* 玩家移动 */ 1164 break; 1165 } 1166 } 1167 } 1168 case RIGHT: 1169 { 1170 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 1171 { 1172 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 1173 { /* 如果移动方向上是空地,那么就可以直接移动 */ 1174 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 1175 PlayerMove(move, x, y, map); /* 玩家移动 */ 1176 break; 1177 } 1178 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 1179 { 1180 break; /* 无法移动 */ 1181 } 1182 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1183 { 1184 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1185 { 1186 BoxMove(move, x, y, map); 1187 RefreshBox(move, x, y, map); 1188 RefreshPlayer(move, x, y, map); 1189 PlayerMove(move, x, y, map); 1190 break; 1191 } 1192 else /* 箱子不能被推动 */ 1193 { 1194 break; 1195 } 1196 } 1197 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1198 { 1199 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1200 PlayerMove(move, x, y, map);/* 玩家移动 */ 1201 break; 1202 } 1203 } 1204 else 1205 { 1206 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 1207 { /* 如果移动方向上是空地,那么就可以直接移动 */ 1208 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 1209 PlayerMove(move, x, y, map); /* 玩家移动 */ 1210 break; 1211 } 1212 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 1213 { 1214 break; /* 无法移动 */ 1215 } 1216 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1217 { 1218 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1219 { 1220 BoxMove(move, x, y, map); 1221 RefreshBox(move, x, y, map); 1222 RefreshPlayer(move, x, y, map); 1223 PlayerMove(move, x, y, map); 1224 break; 1225 } 1226 else /* 箱子不能被推动 */ 1227 { 1228 break; 1229 } 1230 } 1231 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1232 { 1233 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1234 PlayerMove(move, x, y, map);/* 玩家移动 */ 1235 break; 1236 } 1237 } 1238 } 1239 default: break; 1240 } 1241 } 1242 } 1243 1244 /* Function: 打印地图 */ 1245 void DisplyMap(char (*map)[N]) 1246 { 1247 int i, j; 1248 1249 for (i = 0; i < N ;i++) 1250 { 1251 printf(" "); 1252 for (j = 0; j < N; j++) 1253 { 1254 if (map[i][j] == -1) 1255 { 1256 break; 1257 } 1258 if (map[i][j] != ' ') 1259 { 1260 printf("%c", map[i][j]); 1261 } 1262 else if (map[i][j] == ' ') 1263 { 1264 printf("%c", map[i][j]); 1265 break; 1266 } 1267 1268 } 1269 if (map[i][j] == -1) 1270 { 1271 break; 1272 } 1273 } 1274 } 1275 1276 /* Function: 读取地图 */ 1277 void ReadMap(char (*map)[N], FILE *fp, int *x, int *y,int *suc) 1278 { 1279 int i, j; 1280 int n; 1281 1282 i = j = 0; 1283 while(!feof(fp)) /* 未读到文件末尾 */ 1284 { 1285 fscanf_s(fp, "%c", &map[i][j], sizeof(char)); 1286 if (map[i][j] == '*') 1287 { 1288 (*suc)++; /* suc的值为当前关卡目标点的个数 */ 1289 } 1290 if (map[i][j] == 'I') /* 读取到玩家图标 */ 1291 { 1292 *x = j; 1293 *y = i; 1294 } 1295 n = j; /* 存储j自增之前的值,方便判断是不是换行符*/ 1296 j++; 1297 if (map[i][n] == ' ') 1298 { 1299 i++; 1300 j = 0; 1301 } 1302 1303 } 1304 map[i][j-1] = EOF;/* 作为文件结束标志的EOF不会被读取存储到二维数组中,需要手动添加 */ 1305 } 1306 1307 /* Function: 初始化地图 */ 1308 void InitMap(char (*map)[N]) 1309 { 1310 int i, j; 1311 1312 for (i = 0;i < N; i++) 1313 { 1314 for (j = 0; j < N; j++) 1315 { 1316 map[i][j] = ' '; 1317 } 1318 } 1319 } 1320 1321 /* Function: 判断文件打开是否成功 */ 1322 void JudgeFopen_s(errno_t err) 1323 { 1324 if (err != 0) 1325 { 1326 printf("地图文件打开失败,请检查地图文件 "); 1327 system("pause"); 1328 exit(0); 1329 } 1330 }
刚开始想尝试下多文件编程就把两个子函数写在另外一个c文件里面了,函数的声明放在的Game.h里面
Move.c
1 #include <Windows.h> 2 #include "Game.h" 3 4 /* Function: WASD移动*/ 5 /* Date:2019/4/10 */ 6 int MoveByWasd(int move) 7 { 8 switch(move) 9 { 10 case 'A':case 'a': return LEFT; 11 case 'D':case 'd': return RIGHT; 12 case 'W':case 'w': return UP; 13 case 'S':case 's': return DOWN; 14 default: return WRONG; 15 } 16 } 17 18 /* Function: 隐藏光标 */ 19 /* Date:2019/4/10 */ 20 void HideCursor () 21 { 22 HANDLE hOut; 23 CONSOLE_CURSOR_INFO cur; 24 25 cur.bVisible = 0; /* 光标不可见 */ 26 cur.dwSize = 1; /* 光标大小必须要设定一个1~100之间的值,不然光标无法隐藏 */ 27 hOut = GetStdHandle(STD_OUTPUT_HANDLE); /* 获取标准输出句柄 */ 28 SetConsoleCursorInfo(hOut, &cur); /* 隐藏光标 */ 29 } 30 31 /* Function: 光标转移到指定位置 */ 32 /* Date:2019/4/12 */ 33 void gotoxy(int x, int y) 34 { 35 COORD pos = {x, y}; /* 光标坐标 */ 36 HANDLE hOut; 37 38 hOut = GetStdHandle(STD_OUTPUT_HANDLE); /* 获取标准输出句柄 */ 39 SetConsoleCursorPosition(hOut,pos); /* 移动光标到指定位置 */ 40 }
Game.h
1 int MoveByWasd(int move); 2 void gotoxy(int x, int y); 3 void HideCursor (); 4 5 #ifndef _GAME_H 6 #define _GAME_H 7 8 #define LEFT 1 9 #define RIGHT 2 10 #define UP 3 11 #define DOWN 4 12 #define WRONG 5 13 14 #endif
代码本身存在很多问题,函数命名不规范、if-else嵌套过多、switch重复判断,后面会尝试优化下逻辑,将代码行数控制到1000行以内
最终效果:
下面大概列出在完成推箱子这个C程序时大概的过程:
第一步:玩家移动
第二步:玩家移动同时控制边界(碰到墙('#')就停下来)
第三步:加入箱子,玩家推箱子时,箱子('@')和玩家('I')一起移动
第四步:推箱子时控制边界(碰到墙('#')就停下来),当推两个同一方向上连着的两个箱子时,不允许箱子移动
第五步:加入目标点('*')
第六步:箱子到达目标点('*')时,改变箱子显示符号为('$'),箱子从目标点到空地时,复原目标点('*'),改变箱子符号为('@')
第七步:玩家从目标点移动到空地时,复原目标点('*')
第八步:加入通关计数
需要考虑的情况如下:
在前面窄字符的基础上改了一个宽字符版本的的推箱子,只修改了一下推箱子.c中的代码,另外两个文件Move.c和Game.h中的内容不做修改
1 #include <stdio.h> 2 #include <conio.h> 3 #include <stdlib.h> 4 #include <Windows.h> 5 #include "Game.h" 6 #include <locale.h> 7 #include <tchar.h> 8 9 #define N 100 /* 二维数组最大100*100 */ 10 #define NTAB 24 /* 调整界面位置 */ 11 #define YES 1 /* 可以移动 */ 12 #define NO 0 /* 不能移动 */ 13 #define MAP_MAX 6 /* 最大关卡数 */ 14 15 int suc = 0;/* 通关判定 */ 16 17 void OpenMap(FILE **fp, int map); /* 打开地图文件 */ 18 void InitMap(wchar_t (*map)[N]); /* 地图初始化 */ 19 void JudgeFopen_s(errno_t err); /* 判断文件打开是否成功 */ 20 void ReadMap(wchar_t (*map)[N], FILE *fp, int *x, int *y, int *suc); /* 读取地图 */ 21 void DisplyMap(wchar_t (*map)[N]); /* 打印地图 */ 22 23 void PlayerMove(int move, int *x, int *y, wchar_t (*map)[N]); /* 玩家移动*/ 24 void JudgePlayerMove(int move, int *x, int *y, wchar_t (*map)[N]); /* 判断玩家移动方向 */ 25 int JudgeBarr(int move, int *x, int *y, wchar_t(*map)[N]); /* 判断玩家移动方向上是否有障碍物 */ 26 int JudgeBarrType(int move, int *x, int *y, wchar_t(*map)[N]); /* 判断障碍物类别 */ 27 void BoxMove(int move, int *x, int *y, wchar_t(*map)[N]); /* 箱子移动 */ 28 int IsBox(int move, int *x, int *y, wchar_t(*map)[N]); /* 判断是否推动的是箱子*/ 29 int JudgeBoxBoun(int move, int *x, int *y, wchar_t(*map)[N]); /* 判断箱子能否被推动 */ 30 void RefreshBox(int move, int *x, int *y, wchar_t(*map)[N]); /* 更新移动后的箱子的位置 */ 31 void RefreshPlayer(int move, int *x, int *y, wchar_t(*map)[N]);/* 更新移动后的玩家位置 */ 32 int JudgePlayerOri(int move, int *x, int *y, wchar_t(*map)[N]);/* 判断玩家原位置是不是空地 */ 33 int JudgeBoxDes(int move, int *x, int *y, wchar_t(*map)[N]); /* 判断箱子移动后的位置是不是目标点 */ 34 int JudgeBoxOri(int move, int *x, int *y, wchar_t(*map)[N]); /* 判断箱子原位置是不是目标点 */ 35 int JudgePlayerDes(int move, int *x, int *y, wchar_t(*map)[N]);/* 判断玩家移动后的位置是不是目标点 */ 36 int JudgeSuc(FILE **fp, int *suc, int *num, wchar_t (*map)[N], int *x, int *y); /* 判断是否通关 */ 37 void SucCount(int move, int *x, int *y, wchar_t(*map)[N], int *suc); /* 通关条件计数 */ 38 39 40 /* Game: 推箱子 */ 41 /* WASD移动 */ 42 int main() 43 { 44 FILE *fp; 45 int order; /* 指令 */ 46 int move; /* 移动方向 */ 47 wchar_t ss[N][N]; /* 地图 */ 48 int x, y; /* 玩家坐标 */ 49 int level = 1; /* 当前关卡数 */ 50 51 setlocale(LC_ALL, "chs"); 52 OpenMap(&fp, level); /* 打开存储地图的文件 */ 53 54 HideCursor(); /* 隐藏光标 */ 55 InitMap(ss); /* 初始化地图 */ 56 ReadMap(ss, fp, &x, &y, &suc);/* 读取地图 */ 57 DisplyMap(ss); /* 打印地图 */ 58 59 while (1) 60 { 61 order = _getch(); /* 接收指令 */ 62 move = MoveByWasd(order); /* 判断移动方向 */ 63 JudgePlayerMove(move, &x, &y, ss); /* 玩家移动 */ 64 JudgeSuc(&fp, &suc, &level, ss, &x, &y); /* 判断是否通关 */ 65 } 66 67 return 0; 68 } 69 70 /* Function: 打开地图文件*/ 71 void OpenMap(FILE **fp, int map) 72 { 73 switch(map) 74 { 75 case 1: 76 { 77 errno_t err; 78 err = _wfopen_s(fp,_T("m1.txt"), _T("r")); /* 文件打开成功返回0值,否则返回非0值*/ 79 JudgeFopen_s(err); /* 判断文件打开是否成功 */ 80 break; 81 } 82 case 2: 83 { 84 errno_t err; 85 err = _wfopen_s(fp,_T("m2.txt"), _T("r")); 86 JudgeFopen_s(err); 87 break; 88 } 89 case 3: 90 { 91 errno_t err; 92 err = _wfopen_s(fp,_T("m3.txt"), _T("r")); 93 JudgeFopen_s(err); 94 break; 95 } 96 case 4: 97 { 98 errno_t err; 99 err = _wfopen_s(fp,_T("m4.txt"), _T("r")); 100 JudgeFopen_s(err); 101 break; 102 } 103 case 5: 104 { 105 errno_t err; 106 err = _wfopen_s(fp,_T("m5.txt"), _T("r")); 107 JudgeFopen_s(err); 108 break; 109 } 110 case 6: 111 { 112 errno_t err; 113 err = _wfopen_s(fp,_T("m6.txt"), _T("r")); 114 JudgeFopen_s(err); 115 break; 116 } 117 default: 118 { 119 system("cls"); 120 printf(" 没有更多了关卡了,即将退出游戏"); 121 Sleep(3000); 122 exit(0); 123 } 124 } 125 } 126 /* Function: 通关条件计数 */ 127 void SucCount(int move, int *x, int *y, wchar_t(*map)[N],int *suc) 128 { 129 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 130 { 131 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 132 { 133 return; 134 } 135 else /* 箱子移动后的位置是目标点*/ 136 { 137 (*suc)--; 138 return; 139 } 140 } 141 else /* 箱子原位置是目标点 */ 142 { 143 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 144 { 145 (*suc)++; 146 return; 147 } 148 else /* 箱子移动后的位置是目标点*/ 149 { 150 return; 151 } 152 } 153 } 154 155 /* Function: 判断是否通关 */ 156 int JudgeSuc(FILE **fp, int *suc, int *num, wchar_t (*map)[N], int *x, int *y) 157 { 158 if ((*suc) == 0) 159 { 160 (*suc) = 0; /* 关卡通关计数重置 */ 161 (*num)++; /* 关卡数+1 */ 162 163 system("cls"); 164 if ((*num) <= MAP_MAX) 165 { 166 printf(" 通关!即将进入第下一关"); 167 } 168 else 169 { 170 system("cls"); 171 printf(" 没有更多了关卡了,即将退出游戏"); 172 Sleep(3000); 173 exit(0); 174 } 175 176 Sleep(1000); 177 system("cls"); 178 179 OpenMap(fp,*num); /* 打开地图文件 */ 180 InitMap(map); /* 初始化地图 */ 181 ReadMap(map, *fp, x, y, suc);/* 读取地图 */ 182 DisplyMap(map); /* 打印地图 */ 183 184 return YES; /* 通关 */ 185 } 186 else 187 { 188 return NO; 189 } 190 } 191 /* Function: 玩家移动*/ 192 void PlayerMove(int move, int *x, int *y, wchar_t (*map)[N]) 193 { 194 switch(move) 195 { 196 case UP: 197 { 198 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 199 { 200 gotoxy(2*(*x)+NTAB, *y);wprintf(_T(" "));(*y)--;gotoxy(2*(*x)+NTAB, *y);wprintf(_T("♀"));break;/* 玩家移动 */ 201 } 202 else /* 玩家原位置是目标点 */ 203 { 204 gotoxy(2*(*x)+NTAB, *y);wprintf(_T("☆"));(*y)--;gotoxy(2*(*x)+NTAB, *y);wprintf(_T("♀"));break; /* 玩家移动 */ 205 } 206 } 207 case DOWN: 208 { 209 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 210 { 211 gotoxy(2*(*x)+NTAB, *y);wprintf(_T(" "));(*y)++;gotoxy(2*(*x)+NTAB, *y);wprintf(_T("♀"));break;/* 玩家移动 */ 212 } 213 else 214 { 215 gotoxy(2*(*x)+NTAB, *y);wprintf(_T("☆"));(*y)++;gotoxy(2*(*x)+NTAB, *y);wprintf(_T("♀"));break;/* 玩家移动 */ 216 } 217 } 218 case LEFT: 219 { 220 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 221 { 222 gotoxy(2*(*x)+NTAB, *y);wprintf(_T(" "));(*x)--;gotoxy(2*(*x)+NTAB, *y);wprintf(_T("♀"));break; /* 玩家移动 */ 223 } 224 else 225 { 226 gotoxy(2*(*x)+NTAB, *y);wprintf(_T("☆"));(*x)--;gotoxy(2*(*x)+NTAB, *y);wprintf(_T("♀"));break; /* 玩家移动 */ 227 } 228 } 229 case RIGHT: 230 { 231 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 232 { 233 gotoxy(2*(*x)+NTAB, *y);wprintf(_T(" "));(*x)++;gotoxy(2*(*x)+NTAB, *y);wprintf(_T("♀"));break; /* 玩家移动 */ 234 } 235 else 236 { 237 gotoxy(2*(*x)+NTAB, *y);wprintf(_T("☆"));(*x)++;gotoxy(2*(*x)+NTAB, *y);wprintf(_T("♀"));break; /* 玩家移动 */ 238 } 239 } 240 default: break; 241 } 242 } 243 /* Function: 判断玩家移动后的位置是不是目标点 */ 244 int JudgePlayerDes(int move, int *x, int *y, wchar_t(*map)[N]) 245 { 246 switch(move) 247 { 248 case UP: 249 { 250 if (map[(*y)-1][*x] == _T('☆')) /* 移动后的位置是目标点 */ 251 { 252 return YES; 253 } 254 else 255 { 256 return NO; 257 } 258 } 259 case DOWN: 260 { 261 if (map[(*y)+1][*x] == _T('☆')) 262 { 263 return YES; 264 } 265 else 266 { 267 return NO; 268 } 269 } 270 case LEFT: 271 { 272 if (map[*y][(*x)-1] == _T('☆')) 273 { 274 return YES; 275 } 276 else 277 { 278 return NO; 279 } 280 } 281 case RIGHT: 282 { 283 if (map[*y][(*x)+1] == _T('☆')) 284 { 285 return YES; 286 } 287 else 288 { 289 return NO; 290 } 291 } 292 default: return NO; 293 } 294 } 295 296 /* Function: 判断箱子原位置是不是目标点 */ 297 int JudgeBoxOri(int move, int *x, int *y, wchar_t(*map)[N]) 298 { 299 switch(move) 300 { 301 case UP: 302 { 303 if (map[(*y)-1][*x] == _T('★')) /* 箱子原位置是目标点 */ 304 { 305 return NO; 306 } 307 else 308 { 309 return YES; 310 } 311 } 312 case DOWN: 313 { 314 if (map[(*y)+1][*x] == _T('★')) /* 箱子原位置是目标点 */ 315 { 316 return NO; 317 } 318 else 319 { 320 return YES; 321 } 322 } 323 case LEFT: 324 { 325 if (map[*y][(*x)-1] == _T('★')) /* 箱子原位置是目标点 */ 326 { 327 return NO; 328 } 329 else 330 { 331 return YES; 332 } 333 } 334 case RIGHT: 335 { 336 if (map[*y][(*x)+1] == _T('★')) /* 箱子原位置是目标点 */ 337 { 338 return NO; 339 } 340 else 341 { 342 return YES; 343 } 344 } 345 default: return NO; 346 } 347 } 348 /* Function: 判断箱子移动后的位置是不是目标点 */ 349 int JudgeBoxDes(int move, int *x, int *y, wchar_t(*map)[N]) 350 { 351 switch(move) 352 { 353 case UP: 354 { 355 if (map[(*y)-2][*x] == _T('☆')) /* 箱子移动后是目标点 */ 356 { 357 return NO; 358 } 359 else /* 箱子移动后不是目标点 */ 360 { 361 return YES; 362 } 363 } 364 case DOWN: 365 { 366 if (map[(*y)+2][*x] == _T('☆')) 367 { 368 return NO; 369 } 370 else 371 { 372 return YES; 373 } 374 } 375 case LEFT: 376 { 377 if (map[*y][(*x)-2] == _T('☆')) 378 { 379 return NO; 380 } 381 else 382 { 383 return YES; 384 } 385 } 386 case RIGHT: 387 { 388 if (map[*y][(*x)+2] == _T('☆')) 389 { 390 return NO; 391 } 392 else 393 { 394 return YES; 395 } 396 } 397 default: return NO; 398 } 399 } 400 /* Function: 判断障碍物类别 */ 401 int JudgeBarrType(int move, int *x, int *y, wchar_t(*map)[N]) 402 { 403 switch (move) 404 { 405 case UP: 406 { 407 if (map[(*y)-1][*x] == _T('■')) /* 如果目标地点是墙壁 */ 408 { 409 return NO; /* 无法移动 */ 410 } 411 else 412 { 413 return YES;/* 不是墙,需要进一步判断 */ 414 } 415 } 416 case DOWN: 417 { 418 if (map[(*y)+1][*x] == _T('■')) 419 { 420 return NO; 421 } 422 else 423 { 424 return YES; 425 } 426 } 427 case LEFT: 428 { 429 if (map[*y][(*x)-1] == _T('■')) 430 { 431 return NO; 432 } 433 else 434 { 435 return YES; 436 } 437 } 438 case RIGHT: 439 { 440 if (map[*y][(*x)+1] == _T('■')) 441 { 442 return NO; 443 } 444 else 445 { 446 return YES; 447 } 448 } 449 default: return NO; 450 } 451 } 452 453 /* Function: 更新移动后的玩家位置 */ 454 void RefreshPlayer(int move, int *x, int *y, wchar_t(*map)[N]) 455 { 456 switch (move) 457 { 458 case UP: 459 { 460 if (JudgePlayerOri(move, x, y, map) == YES) /* 玩家原位置是空地 */ 461 { 462 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 463 { 464 map[*y][*x] = _T(' ');map[(*y)-1][*x] = _T('☆');break; 465 } 466 else 467 { 468 map[*y][*x] = _T(' ');map[(*y)-1][*x] = _T('♀');break; 469 } 470 } 471 else /* 玩家原位置不是空地 */ 472 { 473 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 474 { 475 map[*y][*x] = _T('☆');map[(*y)-1][*x] = _T('☆');break; 476 } 477 else 478 { 479 map[*y][*x] = _T('☆');map[(*y)-1][*x] = _T('♀');break; 480 } 481 } 482 } 483 case DOWN: 484 { 485 if (JudgePlayerOri(move, x, y, map) == YES) /* 玩家原位置是空地 */ 486 { 487 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 488 { 489 map[*y][*x] = _T(' ');map[(*y)+1][*x] = _T('☆');break; 490 } 491 else 492 { 493 map[*y][*x] = _T(' ');map[(*y)+1][*x] = _T('♀');break; 494 } 495 } 496 else /* 玩家原位置不是空地 */ 497 { 498 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 499 { 500 map[*y][*x] = _T('☆');map[(*y)+1][*x] = _T('☆');break; 501 } 502 else 503 { 504 map[*y][*x] = _T('☆');map[(*y)+1][*x] = _T('♀');break; 505 } 506 } 507 } 508 case LEFT: 509 { 510 if (JudgePlayerOri(move, x, y, map) == YES) /* 玩家原位置是空地 */ 511 { 512 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 513 { 514 map[*y][*x] = _T(' ');map[*y][(*x)-1] = _T('☆');break; 515 } 516 else 517 { 518 map[*y][*x] = _T(' ');map[*y][(*x)-1] = _T('♀');break; 519 } 520 } 521 else /* 玩家原位置不是空地 */ 522 { 523 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 524 { 525 map[*y][*x] = _T('☆');map[*y][(*x)-1] = _T('☆');break; 526 } 527 else 528 { 529 map[*y][*x] = _T('☆');map[*y][(*x)-1] = _T('♀');break; 530 } 531 } 532 } 533 case RIGHT: 534 { 535 if (JudgePlayerOri(move, x, y, map) == YES) /* 玩家原位置是空地 */ 536 { 537 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 538 { 539 map[*y][*x] = _T(' ');map[*y][(*x)+1] = _T('☆');break; 540 } 541 else 542 { 543 map[*y][*x] = _T(' ');map[*y][(*x)+1] = _T('♀');break; 544 } 545 } 546 else /* 玩家原位置不是空地 */ 547 { 548 if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点 */ 549 { 550 map[*y][*x] = _T('☆');map[*y][(*x)+1] = _T('☆');break; 551 } 552 else 553 { 554 map[*y][*x] = _T('☆');map[*y][(*x)+1] = _T('♀');break; 555 } 556 } 557 } 558 } 559 } 560 561 /* Function: 判断玩家原位置是不是空地*/ 562 int JudgePlayerOri(int move, int *x, int *y, wchar_t(*map)[N]) 563 { 564 if (map[*y][*x] == _T('☆')) 565 { 566 return NO; 567 } 568 else 569 { 570 return YES; /* 是空地 */ 571 } 572 } 573 574 575 /* FunctionL 更新移动后的箱子位置 */ 576 void RefreshBox(int move, int *x, int *y, wchar_t(*map)[N]) 577 { 578 switch (move) 579 { 580 case UP: 581 { 582 SucCount(move, x, y, map, &suc); /* 通关条件计数 */ 583 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 584 { 585 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 586 { 587 map[(*y)-1][*x] = _T(' ');map[(*y)-2][*x] = _T('□');break; 588 } 589 else 590 { 591 map[(*y)-1][*x] = _T(' ');map[(*y)-2][*x] = _T('★');break; 592 } 593 } 594 else /* 箱子原位置是目标点 */ 595 { 596 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 597 { 598 map[(*y)-1][*x] = _T('☆');map[(*y)-2][*x] = _T('□');break; 599 } 600 else 601 { 602 map[(*y)-1][*x] = _T('☆');map[(*y)-2][*x] = _T('★');break; 603 } 604 } 605 } 606 case DOWN: 607 { 608 SucCount(move, x, y, map, &suc); /* 通关条件计数 */ 609 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 610 { 611 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 612 { 613 map[(*y)+1][*x] = _T(' ');map[(*y)+2][*x] = _T('□');break; 614 } 615 else 616 { 617 map[(*y)+1][*x] = _T(' ');map[(*y)+2][*x] = _T('★');break; 618 } 619 } 620 else /* 箱子原位置是目标点 */ 621 { 622 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 623 { 624 map[(*y)+1][*x] = _T('☆');map[(*y)+2][*x] = _T('□');break; 625 } 626 else 627 { 628 map[(*y)+1][*x] = _T('☆');map[(*y)+2][*x] = _T('★');break; 629 } 630 } 631 } 632 case LEFT: 633 { 634 SucCount(move, x, y, map, &suc); /* 通关条件计数 */ 635 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 636 { 637 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 638 { 639 map[*y][(*x)-1] = _T(' ');map[*y][(*x)-2] = _T('□');break; 640 } 641 else 642 { 643 map[*y][(*x)-1] = _T(' ');map[*y][(*x)-2] = _T('★');break; 644 } 645 } 646 else /* 箱子原位置是目标点 */ 647 { 648 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 649 { 650 map[*y][(*x)-1] = _T('☆');map[*y][(*x)-2] = _T('□');break; 651 } 652 else 653 { 654 map[*y][(*x)-1] = _T('☆');map[*y][(*x)-2] = _T('★');break; 655 } 656 } 657 } 658 659 case RIGHT: 660 { 661 SucCount(move, x, y, map, &suc); /* 通关条件计数 */ 662 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 663 { 664 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 665 { 666 map[*y][(*x)+1] = _T(' ');map[*y][(*x)+2] = _T('□');break; 667 } 668 else 669 { 670 map[*y][(*x)+1] = _T(' ');map[*y][(*x)+2] = _T('★');break; 671 } 672 } 673 else /* 箱子原位置是目标点 */ 674 { 675 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 676 { 677 map[*y][(*x)+1] = _T('☆');map[*y][(*x)+2] = _T('□');break; 678 } 679 else 680 { 681 map[*y][(*x)+1] = _T('☆');map[*y][(*x)+2] = _T('★');break; 682 } 683 } 684 } 685 } 686 } 687 /* Functioni: 判断箱子能否被推动 */ 688 int JudgeBoxBoun(int move, int *x, int *y, wchar_t(*map)[N]) 689 { 690 switch (move) 691 { 692 case UP: 693 { 694 if (map[(*y)-2][*x] == _T('■') || map[(*y)-2][*x] == _T('□') || map[(*y)-2][*x] == _T('★')) /* 箱子被推动的方向 是墙壁,或者是另一个箱子*/ 695 { 696 return NO; 697 } 698 else 699 { 700 return YES; 701 } 702 } 703 case DOWN: 704 { 705 if (map[(*y)+2][*x] == _T('■') || map[(*y)+2][*x] == _T('□') || map[(*y)+2][*x] == _T('★')) 706 { 707 return NO; 708 } 709 else 710 { 711 return YES; 712 } 713 } 714 case LEFT: 715 { 716 if (map[*y][(*x)-2] == _T('■') || map[*y][(*x)-2] == _T('□') || map[*y][(*x)-2] == _T('★')) 717 { 718 return NO; 719 } 720 else 721 { 722 return YES; 723 } 724 } 725 case RIGHT: 726 { 727 if (map[*y][(*x)+2] == _T('■') || map[*y][(*x)+2] == _T('□') || map[*y][(*x)+2] == _T('★')) 728 { 729 return NO; 730 } 731 else 732 { 733 return YES; 734 } 735 } 736 default: return NO; 737 } 738 } 739 740 /* Function: 判断移动方向上是否有箱子 */ 741 int IsBox(int move, int *x, int *y, wchar_t(*map)[N]) 742 { 743 switch (move) 744 { 745 case UP: 746 { 747 if (map[(*y)-1][*x] ==_T('□') || map[(*y)-1][*x] == _T('★')) /* 如果是在空地上的箱子 或 在目标点上的箱子 */ 748 { 749 return YES; 750 } 751 else 752 { 753 return NO; 754 } 755 } 756 case DOWN: 757 { 758 if (map[(*y)+1][*x] == _T('□') || map[(*y)+1][*x] == _T('★')) 759 { 760 return YES; 761 } 762 else 763 { 764 return NO; 765 } 766 } 767 case LEFT: 768 { 769 if (map[*y][(*x)-1] == _T('□') || map[*y][(*x)-1] == _T('★')) 770 { 771 return YES; 772 } 773 else 774 { 775 return NO; 776 } 777 } 778 case RIGHT: 779 { 780 if (map[*y][(*x)+1] == _T('□') || map[*y][(*x)+1] == _T('★')) 781 { 782 return YES; 783 } 784 else 785 { 786 return NO; 787 } 788 } 789 default: return NO; 790 791 } 792 } 793 794 /* Function: 箱子移动 */ 795 void BoxMove(int move, int *x, int *y, wchar_t(*map)[N]) 796 { 797 switch (move) 798 { 799 case UP: 800 { 801 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 802 { 803 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 804 { 805 gotoxy(2*(*x)+NTAB, (*y)-1);wprintf(_T(" "));gotoxy(2*(*x)+NTAB, (*y)-2);wprintf(_T("□"));break; /* 箱子移动 */ 806 } 807 else /* 箱子移动后的位置是目标点 */ 808 { 809 gotoxy(2*(*x)+NTAB, (*y)-1);wprintf(_T(" "));gotoxy(2*(*x)+NTAB, (*y)-2);wprintf(_T("★"));break; /* 箱子移动 */ 810 } 811 } 812 else /* 箱子原位置是目标点 */ 813 { 814 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 815 { 816 gotoxy(2*(*x)+NTAB, (*y)-1);wprintf(_T("☆"));gotoxy(2*(*x)+NTAB, (*y)-2);wprintf(_T("□"));break; /* 箱子移动 */ 817 } 818 else 819 { 820 gotoxy(2*(*x)+NTAB, (*y)-1);wprintf(_T("☆"));gotoxy(2*(*x)+NTAB, (*y)-2);wprintf(_T("★"));break; /* 箱子移动 */ 821 } 822 } 823 } 824 case DOWN: 825 { 826 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 827 { 828 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 829 { 830 gotoxy(2*(*x)+NTAB, (*y)+1);wprintf(_T(" "));gotoxy(2*(*x)+NTAB, (*y)+2);wprintf(_T("□"));break; /* 箱子移动 */ 831 } 832 else /* 箱子移动后的位置是目标点 */ 833 { 834 gotoxy(2*(*x)+NTAB, (*y)+1);wprintf(_T(" "));gotoxy(2*(*x)+NTAB, (*y)+2);wprintf(_T("★"));break; /* 箱子移动 */ 835 } 836 } 837 else /* 箱子原位置是目标点 */ 838 { 839 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 840 { 841 gotoxy(2*(*x)+NTAB, (*y)+1);wprintf(_T("☆"));gotoxy(2*(*x)+NTAB, (*y)+2);wprintf(_T("□"));break; /* 箱子移动 */ 842 } 843 else 844 { 845 gotoxy(2*(*x)+NTAB, (*y)+1);wprintf(_T("☆"));gotoxy(2*(*x)+NTAB, (*y)+2);wprintf(_T("★"));break; /* 箱子移动 */ 846 } 847 } 848 } 849 case LEFT: 850 { 851 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 852 { 853 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 854 { 855 gotoxy((2*(*x)+NTAB)-2, *y);wprintf(_T(" "));gotoxy((2*(*x)+NTAB)-4, *y);wprintf(_T("□"));break; /* 箱子移动 */ 856 } 857 else /* 箱子移动后的位置是目标点 */ 858 { 859 gotoxy((2*(*x)+NTAB)-2, *y);wprintf(_T(" "));gotoxy((2*(*x)+NTAB)-4, *y);wprintf(_T("★"));break; /* 箱子移动 */ 860 } 861 } 862 else /* 箱子原位置是目标点 */ 863 { 864 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 865 { 866 gotoxy((2*(*x)+NTAB)-2, *y);wprintf(_T("☆"));gotoxy((2*(*x)+NTAB)-4, *y);wprintf(_T("□"));break; /* 箱子移动 */ 867 } 868 else 869 { 870 gotoxy((2*(*x)+NTAB)-2, *y);wprintf(_T("☆"));gotoxy((2*(*x)+NTAB)-4, *y);wprintf(_T("★"));break; /* 箱子移动 */ 871 } 872 } 873 } 874 case RIGHT: 875 { 876 if (JudgeBoxOri(move, x, y, map) == YES) /* 箱子原位置不是目标点 */ 877 { 878 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 879 { 880 gotoxy((2*(*x)+NTAB)+2, *y);wprintf(_T(" "));gotoxy((2*(*x)+NTAB)+4, *y);wprintf(_T("□"));break; /* 箱子移动 */ 881 } 882 else /* 箱子移动后的位置是目标点 */ 883 { 884 gotoxy((2*(*x)+NTAB)+2, *y);wprintf(_T(" "));gotoxy((2*(*x)+NTAB)+4, *y);wprintf(_T("★"));break; /* 箱子移动 */ 885 } 886 } 887 else /* 箱子原位置是目标点 */ 888 { 889 if (JudgeBoxDes(move, x, y, map) == YES) /* 箱子移动后的位置不是目标点 */ 890 { 891 gotoxy((2*(*x)+NTAB)+2, *y);wprintf(_T("☆"));gotoxy((2*(*x)+NTAB)+4, *y);wprintf(_T("□"));break; /* 箱子移动 */ 892 } 893 else 894 { 895 gotoxy((2*(*x)+NTAB)+2, *y);wprintf(_T("☆"));gotoxy((2*(*x)+NTAB)+4, *y);wprintf(_T("★"));break; /* 箱子移动 */ 896 } 897 } 898 } 899 default: break; 900 } 901 } 902 903 /* Function:判断玩家移动方向上是否有障碍物 */ 904 int JudgeBarr(int move, int *x, int *y, wchar_t(*map)[N]) 905 { 906 switch (move) 907 { 908 case UP: 909 { 910 if (map[(*y)-1][*x] == L'■' || map[(*y)-1][*x] == L'□' || map[(*y)-1][*x] == L'☆' || map[(*y)-1][*x] == L'★') /* 如果是墙壁、箱子、目标点 */ 911 { 912 return NO; /* 需要进一步判断 */ 913 } 914 else 915 { 916 return YES; /* 没有障碍物 */ 917 } 918 } 919 case DOWN: 920 { 921 if (map[(*y)+1][*x] == L'■' || map[(*y)+1][*x] == L'□' || map[(*y)+1][*x] == L'☆' || map[(*y)+1][*x] == L'★') 922 { 923 return NO; 924 } 925 else 926 { 927 return YES; 928 } 929 } 930 case LEFT: 931 { 932 if (map[*y][(*x)-1] == L'■' || map[*y][(*x)-1] == L'□' || map[*y][(*x)-1] == L'☆' || map[*y][(*x)-1] == L'★') 933 { 934 return NO; 935 } 936 else 937 { 938 return YES; 939 } 940 } 941 case RIGHT: 942 { 943 if (map[*y][(*x)+1] == L'■' || map[*y][(*x)+1] == L'□' || map[*y][(*x)+1] == L'☆' || map[*y][(*x)+1] == L'★') 944 { 945 return NO; 946 } 947 else 948 { 949 return YES; 950 } 951 } 952 default: return NO; 953 } 954 } 955 956 /* Function:玩家移动 */ 957 void JudgePlayerMove(int move, int *x, int *y, wchar_t (*map)[N]) 958 { 959 switch (move) 960 { 961 case UP: 962 { 963 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 964 { 965 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 966 { /* 如果移动方向上是空地,那么就可以直接移动 */ 967 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 968 PlayerMove(move, x, y, map); /* 玩家移动 */ 969 break; 970 } 971 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 972 { 973 break; /* 无法移动 */ 974 } 975 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 976 { 977 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 978 { 979 BoxMove(move, x, y, map); 980 RefreshBox(move, x, y, map); 981 RefreshPlayer(move, x, y, map); 982 PlayerMove(move, x, y, map); 983 break; 984 } 985 else /* 箱子不能被推动 */ 986 { 987 break; 988 } 989 } 990 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 991 { 992 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 993 PlayerMove(move, x, y, map);/* 玩家移动 */ 994 break; 995 } 996 } 997 else /* 玩家原位置为目标点 */ 998 { 999 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 1000 { /* 如果移动方向上是空地,那么就可以直接移动 */ 1001 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 1002 PlayerMove(move, x, y, map); /* 玩家移动 */ 1003 break; 1004 } 1005 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 1006 { 1007 break; /* 无法移动 */ 1008 } 1009 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1010 { 1011 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1012 { 1013 BoxMove(move, x, y, map); 1014 RefreshBox(move, x, y, map); 1015 RefreshPlayer(move, x, y, map); 1016 PlayerMove(move, x, y, map); 1017 break; 1018 } 1019 else /* 箱子不能被推动 */ 1020 { 1021 break; 1022 } 1023 } 1024 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1025 { 1026 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1027 PlayerMove(move, x, y, map);/* 玩家移动 */ 1028 break; 1029 } 1030 } 1031 } 1032 1033 case DOWN: 1034 { 1035 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 1036 { 1037 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 1038 { /* 如果移动方向上是空地,那么就可以直接移动 */ 1039 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 1040 PlayerMove(move, x, y, map); /* 玩家移动 */ 1041 break; 1042 } 1043 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 1044 { 1045 break; /* 无法移动 */ 1046 } 1047 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1048 { 1049 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1050 { 1051 BoxMove(move, x, y, map); 1052 RefreshBox(move, x, y, map); 1053 RefreshPlayer(move, x, y, map); 1054 PlayerMove(move, x, y, map); 1055 break; 1056 } 1057 else /* 箱子不能被推动 */ 1058 { 1059 break; 1060 } 1061 } 1062 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1063 { 1064 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1065 PlayerMove(move, x, y, map); /* 玩家移动 */ 1066 break; 1067 } 1068 } 1069 else 1070 { 1071 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 1072 { /* 如果移动方向上是空地,那么就可以直接移动 */ 1073 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 1074 PlayerMove(move, x, y, map); /* 玩家移动 */ 1075 break; 1076 } 1077 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 1078 { 1079 break; /* 无法移动 */ 1080 } 1081 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1082 { 1083 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1084 { 1085 BoxMove(move, x, y, map); 1086 RefreshBox(move, x, y, map); 1087 RefreshPlayer(move, x, y, map); 1088 PlayerMove(move, x, y, map); 1089 break; 1090 } 1091 else /* 箱子不能被推动 */ 1092 { 1093 break; 1094 } 1095 } 1096 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1097 { 1098 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1099 PlayerMove(move, x, y, map);/* 玩家移动 */ 1100 break; 1101 } 1102 } 1103 1104 case LEFT: 1105 { 1106 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 1107 { 1108 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 1109 { /* 如果移动方向上是空地,那么就可以直接移动 */ 1110 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 1111 PlayerMove(move, x, y, map); /* 玩家移动 */ 1112 break; 1113 } 1114 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 1115 { 1116 break; /* 无法移动 */ 1117 } 1118 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1119 { 1120 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1121 { 1122 BoxMove(move, x, y, map); 1123 RefreshBox(move, x, y, map); 1124 RefreshPlayer(move, x, y, map); 1125 PlayerMove(move, x, y, map); 1126 break; 1127 } 1128 else /* 箱子不能被推动 */ 1129 { 1130 break; 1131 } 1132 } 1133 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1134 { 1135 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1136 PlayerMove(move, x, y, map);/* 玩家移动 */ 1137 break; 1138 } 1139 } 1140 else 1141 { 1142 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 1143 { /* 如果移动方向上是空地,那么就可以直接移动 */ 1144 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 1145 PlayerMove(move, x, y, map); /* 玩家移动 */ 1146 break; 1147 } 1148 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 1149 { 1150 break; /* 无法移动 */ 1151 } 1152 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1153 { 1154 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1155 { 1156 BoxMove(move, x, y, map); 1157 RefreshBox(move, x, y, map); 1158 RefreshPlayer(move, x, y, map); 1159 PlayerMove(move, x, y, map); 1160 break; 1161 } 1162 else /* 箱子不能被推动 */ 1163 { 1164 break; 1165 } 1166 } 1167 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1168 { 1169 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1170 PlayerMove(move, x, y, map);/* 玩家移动 */ 1171 break; 1172 } 1173 } 1174 } 1175 case RIGHT: 1176 { 1177 if (JudgePlayerOri(move, x, y, map) == YES) /* 如果玩家原位置是空地 */ 1178 { 1179 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 1180 { /* 如果移动方向上是空地,那么就可以直接移动 */ 1181 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 1182 PlayerMove(move, x, y, map); /* 玩家移动 */ 1183 break; 1184 } 1185 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 1186 { 1187 break; /* 无法移动 */ 1188 } 1189 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1190 { 1191 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1192 { 1193 BoxMove(move, x, y, map); 1194 RefreshBox(move, x, y, map); 1195 RefreshPlayer(move, x, y, map); 1196 PlayerMove(move, x, y, map); 1197 break; 1198 } 1199 else /* 箱子不能被推动 */ 1200 { 1201 break; 1202 } 1203 } 1204 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1205 { 1206 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1207 PlayerMove(move, x, y, map);/* 玩家移动 */ 1208 break; 1209 } 1210 } 1211 else 1212 { 1213 if (JudgeBarr(move, x, y, map) == YES) /* 玩家移动方向上是空地 */ 1214 { /* 如果移动方向上是空地,那么就可以直接移动 */ 1215 RefreshPlayer(move, x, y, map);/* 更新移动后的玩家位置 */ 1216 PlayerMove(move, x, y, map); /* 玩家移动 */ 1217 break; 1218 } 1219 else if (JudgeBarrType(move, x, y, map) == NO) /* 如果是墙壁 */ 1220 { 1221 break; /* 无法移动 */ 1222 } 1223 else if (IsBox(move, x, y, map) == YES) /* 移动方向上是箱子 */ 1224 { 1225 if (JudgeBoxBoun(move, x, y, map) == YES) /* 箱子能被推动 */ 1226 { 1227 BoxMove(move, x, y, map); 1228 RefreshBox(move, x, y, map); 1229 RefreshPlayer(move, x, y, map); 1230 PlayerMove(move, x, y, map); 1231 break; 1232 } 1233 else /* 箱子不能被推动 */ 1234 { 1235 break; 1236 } 1237 } 1238 else if (JudgePlayerDes(move, x, y, map) == YES) /* 玩家移动后的位置是目标点*/ 1239 { 1240 RefreshPlayer(move, x, y, map); /* 更新移动后的玩家位置 */ 1241 PlayerMove(move, x, y, map);/* 玩家移动 */ 1242 break; 1243 } 1244 } 1245 } 1246 default: break; 1247 } 1248 } 1249 } 1250 1251 /* Function: 打印地图 */ 1252 void DisplyMap(wchar_t (*map)[N]) 1253 { 1254 int i, j; 1255 1256 for (i = 0; i < N ;i++) 1257 { 1258 printf(" "); 1259 for (j = 0; j < N; j++) 1260 { 1261 if (map[i][j] == EOF+1) 1262 { 1263 break; 1264 } 1265 if (map[i][j] != _T(' ')) 1266 { 1267 wprintf(_T("%lc"), map[i][j]); 1268 } 1269 else if (map[i][j] == _T(' ')) 1270 { 1271 wprintf(_T("%lc"), map[i][j]); 1272 break; 1273 } 1274 1275 } 1276 if (map[i][j] == EOF+1) 1277 { 1278 break; 1279 } 1280 } 1281 } 1282 1283 /* Function: 读取地图 */ 1284 void ReadMap(wchar_t (*map)[N], FILE *fp, int *x, int *y,int *suc) 1285 { 1286 int i, j; 1287 int n; 1288 1289 i = j = 0; 1290 while(!feof(fp)) /* 未读到文件末尾 */ 1291 { 1292 fwscanf_s(fp, _T("%lc"), &map[i][j], sizeof(wchar_t)); 1293 if (map[i][j] == _T('☆')) 1294 { 1295 (*suc)++; /* suc的值为当前关卡目标点的个数 */ 1296 } 1297 if (map[i][j] == _T('♀')) /* 读取到玩家图标 */ 1298 { 1299 *x = j; 1300 *y = i; 1301 } 1302 n = j; /* 存储j自增之前的值,方便判断是不是换行符*/ 1303 j++; 1304 if (map[i][n] == ' ') 1305 { 1306 i++; 1307 j = 0; 1308 } 1309 1310 } 1311 /*这里+1是因为wchar_t是无符号数,最小为0*/ 1312 map[i][j-1] = EOF+1;/* 作为文件结束标志的EOF不会被读取存储到二维数组中,需要手动添加 */ 1313 } 1314 1315 /* Function: 初始化地图 */ 1316 void InitMap(wchar_t (*map)[N]) 1317 { 1318 int i, j; 1319 1320 for (i = 0;i < N; i++) 1321 { 1322 for (j = 0; j < N; j++) 1323 { 1324 map[i][j] = _T(' '); 1325 } 1326 } 1327 } 1328 1329 /* Function: 判断文件打开是否成功 */ 1330 void JudgeFopen_s(errno_t err) 1331 { 1332 if (err != 0) 1333 { 1334 printf("地图文件打开失败,请检查地图文件 "); 1335 system("pause"); 1336 exit(0); 1337 } 1338 }
运行效果:
基本上就是对文件操作函数进行修改,使用fwscanf_s、wprintf、等宽字符对应的函数,并将半角空格用全角空格代替,墙壁、箱子、目标点、玩家等用相应的宽字符符号代替
有一点需要特别注意的是,因为wchar_t是无符号数,所以无法使用EOF(-1)作为打印地图时的结束标志,我是使用EOF+1来解决的
推箱子文件链接: https://pan.baidu.com/s/1i_VvuOU2gGI4XVWzKnc0HA 提取码: pc7a