推箱子(简易版)

游戏简介

经典的推箱子是一个来自日本的古老游戏,目的是在训练你的逻辑思考能力。箱子只可以推, 不可以拉, 而且一次只能推动一个,胜利条件就是把所有的箱子都推到目的地。

思路

模拟题。难点在于推箱子的动作,如果箱子前方是箱子或者墙壁都不能被推动,是目的地或空地可以。撤回操作是通过一个三维数组记录每一步来实现的,貌似使用起来非常玄学,我都懒得调了。

代码

main.cpp

 1 #include"main.h"
 2 #include"GoBack.h"
 3 #include"Intruduce.h"
 4 #include"PlayGame.h"
 5 
 6 int map1[ROW][COL] = {
 7     { 0,0,1,1,1,0,0,0}, //0代表空白
 8     { 0,0,1,2,1,0,0,0},  //1代表墙
 9     { 0,0,1,0,1,1,1,1},  //3代表箱子
10     { 1,1,1,3,3,0,2,1},
11     { 1,2,0,3,6,1,1,1},
12     { 1,1,1,1,3,1,0,0},
13     { 0,0,0,1,2,1,0,0},
14     { 0,0,0,1,1,1,0,0} };
15 int map2[ROW][COL] = {
16     { 0,1,1,1,1,1,1,0 }, //0代表空白
17 { 0,1,0,0,0,0,1,1 }, //1代表墙
18 { 1,1,2,1,1,3,0,1 },  //2代表目的地
19 { 1,0,2,2,3,0,0,1 },  //3代表箱子
20 { 1,0,0,1,3,0,0,1 },  //6代表人
21 { 1,0,0,6,0,1,1,1 },
22 { 1,1,1,1,1,1,0,0 } };
23 int map3[ROW][COL] = {
24     { 1,1,1,1,1,1,1,1}, //0代表空白
25     { 1,1,0,6,0,1,1,1}, //1代表墙
26     { 1,1,3,1,3,0,0,1},  //2代表目的地
27     { 1,0,0,0,0,1,0,1},  //3代表箱子
28     { 1,1,2,2,3,3,2,1},  //6代表人
29 
30     { 1,1,0,2,0,1,1,1},
31     { 1,1,1,0,0,1,1,1},
32     { 1,1,1,1,1,1,1,1} };
33 
34 int lastmap1[STEP][ROW][COL];
35 int lastmap2[STEP][ROW][COL];
36 int lastmap3[STEP][ROW][COL];
37 int stepNumber = 0;  //步数
38 int flag = 0;  //是否按ESC退出
39 
40 
41 int main()
42 {
43     int select;
44 
45     intruduce();
46     scanf_s("%d", &select);
47     system("cls");
48     switch (select)
49     {
50     case 1:
51         gotoxy(0, 0);
52         playGame(map1, lastmap1);
53         break;
54     case 2:
55         gotoxy(0, 0);
56         playGame(map2, lastmap2);
57         break;
58     case 3:
59         gotoxy(0, 0);
60         playGame(map3, lastmap3);
61         break;
62     default:
63         break;
64     }
65 
66     getchar();
67     return 0;
68 }
View Code

PlayGame.cpp

  1 #include"main.h"
  2 #include"PlayGame.h"
  3 #include"GoBack.h"
  4 #include"Intruduce.h"
  5 
  6 //打印当前地图
  7 void DrawMap(int map[][COL])
  8 {
  9     for (int i = 0; i < ROW; i++)
 10     {
 11         for (int j = 0; j < COL; j++)
 12         {
 13             switch (map[i][j])
 14             {
 15             case 0:
 16                 printf("  ");
 17                 break;
 18             case 1:
 19                 printf("");
 20                 break;
 21             case 2:
 22                 printf("");
 23                 break;
 24             case 3:
 25             case 5:
 26                 printf("");
 27                 break;
 28             case 6:
 29             case 8:
 30                 printf("");
 31                 break;
 32             }
 33         }
 34         printf("\n");
 35     }
 36 }
 37 
 38 //得到人的当前位置
 39 void position(int *pRow, int *pCol, int map[][COL])  
 40 {
 41     for (int i = 0; i < ROW; i++)
 42     {
 43         for (int j = 0; j < COL; j++)
 44         {
 45             if (map[i][j] == 6 || map[i][j] == 8)
 46             {
 47                 *pRow = i;
 48                 *pCol = j;
 49                 break; //由于最多只有一个,所以找到一个即可以跳出循环
 50             }
 51         }
 52     }
 53 }
 54 
 55 //控制人的移动
 56 void move(int *pRow, int *pCol, int map[][COL], int lastmap[][ROW][COL])
 57 {
 58     int r = *pRow, c = *pCol;
 59     char ch = _getch();
 60 
 61     reserveMap(map, lastmap);
 62     switch (ch)
 63     {
 64     case 'W':
 65     case 'w':
 66         if ((r > 0) && (map[r - 1][c] == 0 || map[r - 1][c] == 2))  //上面第一个为空地或目的地,人上移
 67         {
 68             map[r - 1][c] += 6;
 69             map[r][c] -= 6;
 70         }
 71         else if ((r > 0) && (map[r - 1][c] == 3 || map[r - 1][c] == 5))   //上面一个是箱子,要先判断箱子上方的情况
 72         {
 73             if ((r > 1) && (map[r - 2][c] == 0 || map[r - 2][c] == 2))  //如果箱子箱子上方是空的或目的地
 74             {
 75                 map[r - 2][c] += 3;  //箱子移来标值加3
 76                 map[r - 1][c] += 3;  //箱子移走-3,人以来+6
 77                 map[r][c] -= 6;
 78             }
 79         }
 80         system("cls");
 81         DrawMap(map);
 82         stepNumber++;
 83         break;
 84     case 'S':
 85     case 's':
 86         if ((r < ROW - 1) && (map[r + 1][c] == 0 || map[r + 1][c] == 2))  //上面第一个为空地或目的地,人上移
 87         {
 88             map[r + 1][c] += 6;
 89             map[r][c] -= 6;
 90         }
 91         else if ((r < ROW - 1) && (map[r + 1][c] == 3 || map[r + 1][c] == 5))   //上面一个是箱子,要先判断箱子上方的情况
 92         {
 93             if ((r < ROW - 2) && (map[r + 2][c] == 0 || map[r + 2][c] == 2))  //如果箱子箱子上方是空的或目的地
 94             {
 95                 map[r + 2][c] += 3;  //箱子移来标值加3
 96                 map[r + 1][c] += 3;  //箱子移走-3,人以来+6
 97                 map[r][c] -= 6;
 98             }
 99         }
100         system("cls");
101         DrawMap(map);
102         stepNumber++;
103         break;
104     case 'A':
105     case 'a':
106         if ((c > 0) && (map[r][c - 1] == 0 || map[r][c - 1] == 2))  //上面第一个为空地或目的地,人上移
107         {
108             map[r][c - 1] += 6;
109             map[r][c] -= 6;
110         }
111         else if ((c > 0) && (map[r][c - 1] == 3 || map[r][c - 1] == 5))   //上面一个是箱子,要先判断箱子上方的情况
112         {
113             if ((c > 1) && (map[r][c - 2] == 0 || map[r][c - 2] == 2))  //如果箱子箱子上方是空的或目的地
114             {
115                 map[r][c - 2] += 3;  //箱子移来标值加3
116                 map[r][c - 1] += 3;  //箱子移走-3,人以来+6
117                 map[r][c] -= 6;
118             }
119         }
120         system("cls");
121         DrawMap(map);
122         stepNumber++;
123         break;
124     case 'D':
125     case 'd':
126         if ((c < COL - 1) && (map[r][c + 1] == 0 || map[r][c + 1] == 2))  //上面第一个为空地或目的地,人上移
127         {
128             map[r][c + 1] += 6;
129             map[r][c] -= 6;
130         }
131         else if ((c < COL - 1) && (map[r][c + 1] == 3 || map[r][c + 1] == 5))   //上面一个是箱子,要先判断箱子上方的情况
132         {
133             if ((c < COL - 2) && (map[r][c + 2] == 0 || map[r][c + 2] == 2))  //如果箱子箱子上方是空的或目的地
134             {
135                 map[r][c + 2] += 3;  //箱子移来标值加3
136                 map[r][c + 1] += 3;  //箱子移走-3,人以来+6
137                 map[r][c] -= 6;
138             }
139         }
140         system("cls");
141         DrawMap(map);
142         stepNumber++;
143         break;
144     case 'K':
145     case 'k':
146         stepNumber--;
147         if (stepNumber < 0)        //处理第一步就撤回的情况
148         {
149             printf("Can not back!");
150             stepNumber++;
151             break;
152         }
153         goBack(map, lastmap);
154         system("cls");
155         DrawMap(map);
156         if (stepNumber == 0)
157         {
158             gotoxy(20, 20);
159             printf("Can not back!");
160             stepNumber++;
161         }
162         break;
163     case 'Q':
164     case 'q':
165         flag = 1;
166         break;
167     default:
168         break;
169     }
170 }
171 
172 //判断是否已获胜
173 bool testWin(int *pRow, int *pCol, int map[][COL])
174 {
175     int i, j, count = 0;  //count表示未填目的地的数量
176     int r = *pRow, c = *pCol;
177     for (i = 0; i < ROW; i++)
178         for (j = 0; j < COL; j++)
179             if (map[i][j] == 2)
180                 count++;
181     if ((!count) && (map[r][c] != 8))  //
182         return true;  //目的地被填满,返回true
183     else
184         return false;  //还未被填满,放回flase
185 }
186 
187 //玩游戏
188 void playGame(int map[][COL], int lastmap[][ROW][COL])
189 {
190     int pRow, pCol;
191 
192     DrawMap(map);
193     position(&pRow, &pCol, map);
194     do
195     {
196         move(&pRow, &pCol, map, lastmap);
197         position(&pRow, &pCol, map);
198     } while (!testWin(&pRow, &pCol, map) && (flag == 0));
199     if (testWin(&pRow, &pCol, map) == 1)
200     {
201         printf("You win!\n");
202         getchar();
203     }
204 }
View Code

Intruduce.cpp

 1 #include"main.h"
 2 #include"Intruduce.h"
 3 
 4 void gotoxy(int x, int y)//函数gotoxy:定义光标位置
 5 {
 6     COORD coord;//坐标系coord 
 7     HANDLE handle;
 8 
 9     coord.X = x;//横坐标X 
10     coord.Y = y;//纵坐标 y
11     handle = GetStdHandle(STD_OUTPUT_HANDLE);
12     SetConsoleCursorPosition(handle, coord);
13 }
14 
15 void hidecursor()//函数hidecursor:隐藏光标
16 {
17     CONSOLE_CURSOR_INFO curinfo;
18     HANDLE Out;
19 
20     Out = GetStdHandle(STD_OUTPUT_HANDLE);
21     curinfo.dwSize = 1;//光标百分比厚度:1~100
22     curinfo.bVisible = 0;//是否可见
23     SetConsoleCursorInfo(Out, &curinfo);
24 } 
25 
26 void intruduce()
27 {
28     int i;
29     system("cls");
30     HANDLE consolehwnd;//创建句柄
31     consolehwnd = GetStdHandle(STD_OUTPUT_HANDLE);
32     SetConsoleTextAttribute(consolehwnd, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
33     //设置为亮白色 
34 
35     hidecursor();
36     for (i = 14; i < 39; i++)
37     {
38         gotoxy(i * 2, 4);
39         printf("");
40     }
41 
42     for (i = 5; i < 20; i++)
43     {
44         gotoxy(28, i);
45         printf("");
46         gotoxy(76, i);
47         printf("");
48     }
49 
50     gotoxy(47, 5);
51     printf("推箱子1.0");
52 
53     for (i = 15; i < 38; i++)
54     {
55         gotoxy(i * 2, 6);
56         printf("");
57     }
58     gotoxy(47, 7);
59     printf("规则说明");
60 
61     gotoxy(30, 9);
62     printf("1.共有三个关卡");
63     gotoxy(30, 10);
64     printf("2.按1选择关卡,按2选择关卡二,按3选择关卡三");
65     gotoxy(30, 11);
66     printf("3.WSAD控制上下左右,K撤回,Q退出");
67     gotoxy(30, 12);
68     printf("4.进入游戏前请关闭中文输入法");
69 
70 
71 
72     for (i = 15; i < 38; i++)
73     {
74         gotoxy(i * 2, 17);
75         printf("");
76     }
77 
78     for (i = 14; i < 39; i++)
79     {
80         gotoxy(i * 2, 20);
81         printf("");
82     }
83 
84     gotoxy(49, 18);
85     printf("关卡:");
86 }
View Code

GoBack.cpp

 1 #include"main.h"
 2 #include"GoBack.h"
 3 
 4 //将map保存到lastmap
 5 void reserveMap(int map[][COL], int lastmap[][ROW][COL])
 6 {
 7     for (int i = 0; i < ROW; i++)
 8         for (int j = 0; j < COL; j++)
 9             lastmap[stepNumber][i][j] = map[i][j];
10 }
11 
12 //将lastmap还原到map
13 void goBack(int map[][COL], int lastmap[][ROW][COL])
14 {
15     //reserveMap(map, lastmap1, stepNumber);
16     for (int i = 0; i < ROW; i++)
17         for (int j = 0; j < COL; j++)
18             map[i][j] = lastmap[stepNumber][i][j];
19 }
View Code

main.h

 1 #include<stdio.h>
 2 #include<Windows.h>
 3 #include<conio.h>
 4 #define KIND 3
 5 #define STEP 20
 6 #define ROW 20
 7 #define COL 20
 8 
 9 extern int map1[ROW][COL], map2[ROW][COL], map3[ROW][COL];        //记录初始地图
10 extern int lastmap1[STEP][ROW][COL],lastmap2[STEP][ROW][COL],lastmap3[STEP][ROW][COL];    //记录当前地图的前一幅
11 extern int stepNumber;        //步数
12 extern int flag;            //是否按ESC退出
View Code

PlayGame.h

1 void DrawMap(int map[][COL]);
2 void position(int *pRow, int *pCol, int map[][COL]);
3 void move(int *pRow, int *pCol, int map[][COL], int lastmap[][ROW][COL]);
4 bool testWin(int *pRow, int *pCol, int map[][COL]);
5 void playGame(int map[][COL], int lastmap[][ROW][COL]);
View Code

Intruduce.h

1 void gotoxy(int x, int y);
2 void hidecursor();
3 void intruduce();
View Code

GoBack.h

1 #include"main.h"
2 void reserveMap(int map[][COL], int lastmap[][ROW][COL]);
3 void goBack(int map[][COL], int lastmap[][ROW][COL]);
View Code

在VS2017里新建项目,添加上面的每一项,复制粘贴,实测能够运行。

参考链接:百度百科  推箱子

posted @ 2018-11-01 13:39  Rogn  阅读(890)  评论(0编辑  收藏  举报