C++游戏开发基础课6

1.回顾

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
#include <iostream>
#include <conio.h>
#include <cstring>
#include <windows.h>
using namespace std;
string map1[10] = {"####################",
"#Y #",
"# #",
"# #",
"# #",
"# #",
"# #",
"# #",
"# X#",
"####################"};
string map2[13] = {"##################################",
"#Y#X #",
"# ############################## #",
"# # #",
"############################## # #",
"# # # #",
"# # ############### #",
"# # V# #",
"# # ############### #",
"# V# #",
"# ############################## #",
"# #",
"##################################"};
void setpos(int x, int y) {//x为横坐标,y为纵坐标
COORD pos;
pos.X = x,pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
return;
}
void print(string maps[], int size, int x, int y) {
setpos(0, 0);//移动光标到窗口左上角
//system("cls");
for(int i = 0; i < size; i++) {
for(int j = 0; j < maps[i].size(); j++) {
if(i == y && j == x) {
cout << "Y";
} else {
if(maps[i][j] == 'V') {
cout << "Y";//假装这是出口
} else {
cout << maps[i][j];
}
}
}
cout << endl;
}
return;
}
void move(string maps[], int size) {
system("cls");//主动刷新屏幕,防止上一关的地图还在窗口中
int x, y, old_x, old_y;//old_x与old_y记录入口
for(int i = 0; i < size; i++) {
for(int j = 0; j < maps[i].size(); j++) {
if(maps[i][j] == 'Y') {
y = i;
x = j;
old_x = i;
old_y = j;
maps[i][j] = ' ';
break;
}
}
}
while(true) {
print(maps, size, x, y);
char a = getch();
if(a == 'w' || a == 'W') {
if(maps[y - 1][x] != '#') {
y--;
}
} else if(a == 's' || a == 'S') {
if(maps[y + 1][x] != '#') {
y++;
}
} else if(a == 'a' || a == 'A') {
if(maps[y][x - 1] != '#') {
x--;
}
} else if(a == 'd' || a == 'D') {
if(maps[y][x + 1] != '#') {
x++;
}
}
if(maps[y][x] == 'X') {
system("cls");
cout << "你赢了!" << endl;
system("pause");
return;
}
if(maps[y][x] == 'V') {
system("cls");
cout << "你死了!" << endl;
cout << "呃,这个出口可能是陷阱……" << endl;
system("pause");
x = old_x;
y = old_y;//回到入口
}
}
return;
}
int main() {
CONSOLE_CURSOR_INFO cursor_info = {1, 0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
move(map1, 10);
move(map2, 13);//第二关
return 0;
}

2.本地地图读入

读入文件

读取文件的函数是freopen,他在库()

1
freopen(<文件名称>,<读/写>,<标准读写流>);

解析:

<文件名称>的类型是char,string要使用.c_str()

<读/写>中读为“r”,写为“w”

<标准读写流>中读为stdin,写为stdout

比如,读入”map1.map”,那么语句应该写为:

1
freopen("map1.map", "r", stdin);

取消stdin与stdout标准头读写文件:

1
fclose(<标准读写流>);

注意:freopen改写了标准读写流后是无法再次向窗口进行读写(cin与cout无法再次在窗口中使用)(比如cout无法在窗口中输出)

stdin覆盖后继续输入的解决办法: freopen(“CON”, “r”, stdin);

判断文件是否存

access在头文件

1
access(<文件名称>, F_OK);//返回值为0表示存在,返回-1表示不存在

<文件名称>的类型为char,string要使用.c_str()

getchar函数

是读入各种字符的(包括空格与回车),读入类型为char

读入一整行字符(回车结束):

1
2
3
4
5
6
7
8
9
10
11
12
string cin_space() {
string re = "";
char a;
while(true) {
a = getchar();
if(a == '\n') {
break;
}
re += a;
}
return re;
}
抹去字符后多余的空格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
string del_space(string n) {//n为待抹去的字符
string ans = "";
int size = n.size();
for(int i = n.size() - 1; i >= 0; i--) {
if(n[i] != ' ' && n[i] != '\n') {
break;
}
size--;
}
for(int i = 0; i < size; i++) {
ans += n[i];
}
return ans;
}
将int类型转换为string
1
2
3
4
5
6
7
8
9
10
11
string int_string(int n) {//n为待转换的数字
string re;
while(n) {//转换为字符串
re += n % 10 + '0';
n /= 10;
}
for(int i = 0; i < re.size() / 2; i++) {//将re的字符颠倒(字符串re是颠倒的,要颠倒回来)
swap(re[i], re[re.size() - 1 - i]);
}
return re;
}
读入map

将原来的map1与map2删除,改为结构体

1
2
3
4
struct Maps{
string map[2005];
int size;
} maps[2005];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void get_map() {
if(access("maps", F_OK) == -1) {//未找到maps文件夹(没有地图)
exit(0);//结束程序
}
int n = 0;
int maxn;//最长地图长度(用于补全地图,将地图末尾的空格补上,防止输出地图发生错误)
string s;//读入辅助变量
while(access((".\\maps\\" + int_string(++n) + ".map").c_str(), F_OK) == 0) {//判断maps文件夹中的(n).map是否存在(不存在则结束搜索地图)
maps[n].size = 0;//第n个地图的大小设置未空
freopen((".\\maps\\" + int_string(n) + ".map").c_str(), "r", stdin);//读取(n).map
while(true) {
s = del_space(cin_space());
if(s == "") {//若s为空字符
break;//结束读入
}
maxn = max(maxn, int(s.size()));
maps[n].map[maps[n].size++] = s;//保存s到maps[n]的第size[n]的下一项
}
fclose(stdin);
freopen("CON", "r", stdin);//恢复原读入流
move(maps[n].map, maps[n].size);//启动游戏
}
return;
}

3.代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <iostream>
#include <conio.h>
#include <cstring>
#include <windows.h>
#include <unistd.h>
using namespace std;
struct Maps{
string map[2005];
int size;
} maps[2005];
string int_string(int n) {//n为待转换的数字
string re;
while(n) {//转换为字符串
re += n % 10 + '0';
n /= 10;
}
for(int i = 0; i < re.size() / 2; i++) {//将re的字符颠倒(字符串re是颠倒的,要颠倒回来)
swap(re[i], re[re.size() - 1 - i]);
}
return re;
}
string del_space(string n) {//n为待抹去的字符
string ans = "";
int size = n.size();
for(int i = n.size() - 1; i >= 0; i--) {
if(n[i] != ' ' && n[i] != '\n') {
break;
}
size--;
}
for(int i = 0; i < size; i++) {
ans += n[i];
}
return ans;
}
string cin_space() {
string re = "";
char a;
while(true) {
a = getchar();
if(a == '\n') {
break;
}
re += a;
}
return re;
}
void setpos(int x, int y) {//x为横坐标,y为纵坐标
COORD pos;
pos.X = x,pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
return;
}
void print(string maps[], int size, int x, int y) {
setpos(0, 0);//移动光标到窗口左上角
//system("cls");
for(int i = 0; i < size; i++) {
for(int j = 0; j < maps[i].size(); j++) {
if(i == y && j == x) {
cout << "Y";
} else {
if(maps[i][j] == 'V') {
cout << "Y";//假装这是出口
} else {
cout << maps[i][j];
}
}
}
cout << endl;
}
return;
}
void move(string maps[], int size) {
system("cls");//主动刷新屏幕,防止上一关的地图还在窗口中
int x, y, old_x, old_y;//old_x与old_y记录入口
for(int i = 0; i < size; i++) {
for(int j = 0; j < maps[i].size(); j++) {
if(maps[i][j] == 'Y') {
y = i;
x = j;
old_x = i;
old_y = j;
maps[i][j] = ' ';
break;
}
}
}
while(true) {
print(maps, size, x, y);
char a = getch();
if(a == 'w' || a == 'W') {
if(maps[y - 1][x] != '#') {
y--;
}
} else if(a == 's' || a == 'S') {
if(maps[y + 1][x] != '#') {
y++;
}
} else if(a == 'a' || a == 'A') {
if(maps[y][x - 1] != '#') {
x--;
}
} else if(a == 'd' || a == 'D') {
if(maps[y][x + 1] != '#') {
x++;
}
}
if(maps[y][x] == 'X') {
system("cls");
cout << "你赢了!" << endl;
system("pause");
return;
}
if(maps[y][x] == 'V') {
system("cls");
cout << "你死了!" << endl;
cout << "呃,这个出口可能是陷阱……" << endl;
system("pause");
x = old_x;
y = old_y;//回到入口
}
}
return;
}
void get_map() {
if(access("maps", F_OK) == -1) {//未找到maps文件夹(没有地图)
exit(0);//结束程序
}
int n = 0;
int maxn;//最长地图长度(用于补全地图,将地图末尾的空格补上,防止输出地图发生错误)
string s;//读入辅助变量
while(access((".\\maps\\" + int_string(++n) + ".map").c_str(), F_OK) == 0) {//判断maps文件夹中的(n).map是否存在(不存在则结束搜索地图)
maps[n].size = 0;//第n个地图的大小设置未空
freopen((".\\maps\\" + int_string(n) + ".map").c_str(), "r", stdin);//读取(n).map
while(true) {
s = del_space(cin_space());
if(s == "") {//若s为空字符
break;//结束读入
}
maxn = max(maxn, int(s.size()));
maps[n].map[maps[n].size++] = s;//保存s到maps[n]的第size[n]的下一项
}
fclose(stdin);
freopen("CON", "r", stdin);//恢复原读入流
move(maps[n].map, maps[n].size);//启动游戏
}
return;
}
int main() {
CONSOLE_CURSOR_INFO cursor_info = {1, 0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
get_map();
return 0;
}