1. 基本任务介绍
算法目的:炸弹放在哪里可以最大杀伤?
编程难点:
- 数组作为形参是深(是)?如果深,有必要应用?
答:形参是实参的一份拷贝,是局部变量。但是数组是个例外,因为数组的数据太多了,将其一一赋值既麻烦又浪费空间,所以数组作为参数传递给函数的只是数组首元素的地址,数据还是在内存里的,函数在需要用到后面元素时再按照这个地址和数组下标去内存查找。也就是说后面的元素根本没到函数里来。因为数组的复制将导致连续的内存读与内存写,其时间开销取决于数组长度,有可能会变得非常大。为了避免复制数组的开销,才用指针代替数组。因此C语言使得当数组作为实参传递给函数的时候,将退化为同类型的指针,再传递指针的值。
因此,在函数中修改数组值时,修改的是真的值。
- 由于是通过指针传递,因此无法得到数组的长度。(在通过指针传递时,需要另外传入参数来传递数组的大小)
- 传递引用时,同时将数组长度也传递进去了,所以传入时必须为相应长度的数组。并且,在传递引用时,需要注意用()将&aa括起来,否则编译器报错。
- 二维数组形参和一维不太一样
- (Type (&str_)[size], char map_[][13]) 后面的13好像不能少
- 不能纯统计每行列的敌人,有墙的
代码
// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
# include <string>
#include<iostream>
using namespace std;
char map_[13][13] = {0
};
std::string map2[] = {
"#############",
"#GG.GGG#GGG.#",
"###.#G#G#G#G#",
"#.......#..G#",
"#G#.###.#G#G#",
"#GG.GGG.#.GG#",
"#G#.#G#.#.#.#",
"##G...G.....#",
"#G#.#G###.#G#",
"#...G#GGG.GG#",
"#G#.#G#G#.#G#",
"#GG.GGG#G.GG#",
"#############",
};
int lines = sizeof(map_) / sizeof(map_[0][0]); //总共多长
int col = sizeof(map_[0])/ sizeof(map_[0][0]);
int row = lines / col;
template <typename Type, int size>
void string2char(Type (&str_)[size], char map_[][13]) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < str_[i].size(); j++) {
map_[i][j] = str_[i][j];
}
}
}
int get_range1(int i, int j) {
int num = 0;
for (int i_ = 0; i_ < row; i_++) {
if (map_[i_][j] == 'G') num += 1;
//num += map_[i_][j];
}
for (int i_ = 0; i_ < col; i_++) {
if (map_[i][i_] == 'G') num += 1;
//num += map_[i][i_];
}
return num;
}
int get_direction(int currenti, int currentj, int direction[2]) {
int num = 0;
while ((currenti >= 0 && currenti <= row)&&((currentj >= 0 && currentj <= col) )) {
currenti += direction[0];
currentj += direction[1];
if (map_[currenti][currentj] == 'G')
num += 1;
if (map_[currenti][currentj] == '#')
break;
}
return num;
}
int get_range(int i, int j) {
int num = 0;
int currenti=i, currentj=j;
int direction[][2] = {
{1,0},
{0,1},
{-1,0},
{0,-1}
};
for (auto d : direction) {
num += get_direction(i, j, d);
}
return num;
}
void main() {
string2char(map2, map_);
int i = 0;
// 遍历所有 map_ 的点位
int num_ = 0;
int maxi = 0;
int maxj = 0;
int max_num = 0;
for (int i = 0; i < row;i++) {
for (int j = 0; j < col; j++) {
if (map_[i][j] == '.') {
num_ = get_range(i, j);
if (num_ > max_num) {
maxi = i;
maxj = j;
max_num = num_;
}
}
}
}
cout << maxi << "," << maxj << endl;
return;
}
2. 基于广度搜索的炸弹人算法
// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
# include <string>
#include<iostream>
using namespace std;
char map_[13][13] = {0
};
std::string map2[] = {
"#############",
"#GG.GGG#GGG.#",
"###.#G#G#G#G#",
"#.......#..G#",
"#G#.###.#G#G#",
"#GG.GGG.#.GG#",
"#G#.#G#.#.#.#",
"##G...G.....#",
"#G#.#G###.#G#",
"#...G#GGG.GG#",
"#G#.#G#G#.#G#",
"#GG.GGG#G.GG#",
"#############",
};
int lines = sizeof(map_) / sizeof(map_[0][0]); //总共多长
int col = sizeof(map_[0])/ sizeof(map_[0][0]);
int row = lines / col;
template <typename Type, int size>
void string2char(Type (&str_)[size], char map_[][13]) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < str_[i].size(); j++) {
map_[i][j] = str_[i][j];
}
}
}
int get_direction(int currenti, int currentj, int direction[2]) {
int num = 0;
while ((currenti >= 0 && currenti <= row)&&((currentj >= 0 && currentj <= col) )) {
currenti += direction[0];
currentj += direction[1];
if (map_[currenti][currentj] == 'G')
num += 1;
if (map_[currenti][currentj] == '#')
break;
}
return num;
}
int get_range(int i, int j) {
int num = 0;
int currenti=i, currentj=j;
int direction[][2] = {
{1,0},
{0,1},
{-1,0},
{0,-1}
};
for (auto d : direction) {
num += get_direction(i, j, d);
}
return num;
}
// ---------------
// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <queue>
#include<vector>
#include<string>
using namespace std;
struct Point {
//行与列
int row;
int col;
int step = 0;
int range = -1;
//默认构造函数
Point() {
row = col = -1;
}
Point(int x, int y, int step_ = 0) {
this->row = x;
this->col = y;
step = step_;
}
bool operator==(const Point& rhs) const {
if (this->row == rhs.row && this->col == rhs.col)
return true;
return false;
}
};
class Pos_find {
public:
int maze[13][13];
int passed[13][13];
int neighbour[4][2] = {
{1,0},
{0,1},
{-1,0},
{0,-1}
};
int row = sizeof(maze) / sizeof(maze[0]);
int col = sizeof(maze[0]) / sizeof(maze[0][0]);
int range_map[13][13] = { 0 }; //[]TODO: int range_map[row][col] = { 0 }; 为什么报错
int obstacles = -1, blank = 0, enemy=-2;
queue<Point> vecPath;
Point ** mark = 0;
template <class T1, class T2>
bool valid_point(Point point, T1 obstacles = -1, T2 blank = 0) {
//判断点是否可以作为下一 1 障碍物 2 边界 3 未走过
int row = sizeof(maze) / sizeof(maze[0]);
int col = sizeof(maze[0]) / sizeof(maze[0][0]);
// 判断障碍物
if (maze[point.row][point.col] == obstacles) {
return false;
}
if (enemy != -2 && (maze[point.row][point.col] == enemy)) {
return false;
}
// 判断边界
if ((point.row < 0 || point.row > row - 1) || (point.col < 0 || point.col > col - 1))
return false;
else
// 未走过
if (passed[point.row][point.col] == 0)
return true;
else {
cout << "wrong in valid" << endl;
return false;
}
}
int get_range(int i, int j) {
int num = 0;
//int currenti = i, currentj = j;
int direction[][2] = {
{1,0},
{0,1},
{-1,0},
{0,-1}
};
for (auto d : direction) {
num += get_direction(i, j, d);
}
return num;
}
int get_direction(int currenti, int currentj, int direction[2]) {
int num = 0;
while ((currenti >= 0 && currenti <= row) && ((currentj >= 0 && currentj <= col))) {
currenti += direction[0];
currentj += direction[1];
if (maze[currenti][currentj] == 'G')
num += 1;
if (maze[currenti][currentj] == '#')
break;
}
return num;
}
// 修改地图
template <typename Type, int size>
void string2char(Type(&str_)[size]) {
for (int i = 0; i < size; i++) {
for (int j = 0; j < str_[i].size(); j++) {
maze[i][j] = str_[i][j];
}
}
obstacles = '#';
blank = '.';
enemy = 'G';
}
void mazePath( Point& start_pos, Point& target_pos) {
vecPath = queue<Point>();// build a empty queue
vecPath.push(start_pos);
maze[start_pos.row][start_pos.col] = 1;
int flag = 0;
int row = sizeof(maze) / sizeof(maze[0]);
int col = sizeof(maze[0]) / sizeof(maze[0][0]);
Point temp_point, new_point;
int i = 1;
// 建立一个二维数组,每个数组里面是Point
Point** mark = new Point * [row];//[TODO] 这里不需要释放吗?
//for (auto ) // ?auto 吗?[TODO]
for (int i = 0; i < row; i++) {
mark[i] = new Point[col];
}
// 开始的格子指向自己
mark[0][0] = start_pos;
// 指向数组的指针
while (vecPath.empty() == false) {
// 取
temp_point = vecPath.front();
// 获取相邻值
for (auto deta : neighbour) {
new_point = Point(temp_point.row + deta[0], temp_point.col + deta[1], temp_point.step + 1);
if (valid_point(new_point, obstacles, blank)) { // 如果点可以加入
maze[new_point.row][new_point.col] = temp_point.step + 1;
mark[new_point.row][new_point.col] = temp_point;// 放入父节点
vecPath.push(new_point);
}
if (new_point == target_pos) {
flag = 1;
break;
}
}
vecPath.pop();
if (flag == 1) break;
i++;
}
if (vecPath.empty() == false) {
// 获取最后一个格子的数值
temp_point = vecPath.back();
// 依据最后一个获取前一个
while ((temp_point.row == start_pos.row && temp_point.col == start_pos.col) == false) {
cout << " <" << temp_point.row << "," << temp_point.col << "> ";
temp_point = mark[temp_point.row][temp_point.col];
}
}
return;
}
void mazePath(Point& start_pos) {
int num_ = 0;
int maxi = 0;
int maxj = 0;
int max_num = 0;
vecPath = queue<Point>();// build a empty queue
vecPath.push(start_pos);
//maze[start_pos.row][start_pos.col] = 1; []TODO:记录步伐应该放在一起,这种容易漏掉。
max_num = get_range(start_pos.row, start_pos.col);
range_map[start_pos.row][start_pos.col] = max_num;
passed[start_pos.row][start_pos.col] = 1;
int flag = 0;
Point temp_point, new_point;
int i = 1;
// 建立一个二维数组,每个数组里面是Point
Point** mark = new Point * [row];//[TODO] 这里不需要释放吗?
//for (auto ) // ?auto 吗?[TODO]
for (int i = 0; i < row; i++) {
mark[i] = new Point[col];
}
// 开始的格子指向自己
mark[0][0] = start_pos;
// 指向数组的指针
while (vecPath.empty() == false) {
// 取
temp_point = vecPath.front();
// 获取相邻值
for (auto deta : neighbour) {
new_point = Point(temp_point.row + deta[0], temp_point.col + deta[1], temp_point.step + 1);
if (valid_point(new_point, obstacles, blank)) { // 如果点可以加入
//maze[new_point.row][new_point.col] = temp_point.step + 1; //[x]TODO: 随意修改成员变量不是好习惯 - > 新编量记录走过的地方
num_ = get_range(new_point.row, new_point.col);
range_map[new_point.row][new_point.col] = num_;
mark[new_point.row][new_point.col] = temp_point;// 放入父节点
passed[new_point.row][new_point.col] = temp_point.step + 1;
vecPath.push(new_point);
if (num_ > max_num) {
maxi = new_point.row;
maxj = new_point.col;
max_num = num_;
}
}
}
vecPath.pop();
//if (flag == 1) break;
i++;
}
// 找到最大的点
cout << max_num << endl;
return;
}
}; //[TODO] warning :警告 C26495 未初始化变量 Pos_find::mark。始终初始化成员变量(type.6)。 238 解决加 Point ** mark = 0;
int main()
{
//
Pos_find map_;
Point start_pt = Point(1, 3), end_pt = Point(4,4);
//map_.mazePath(start_pt, end_pt);
// 任务二
// 修改地图
map_.string2char(map2);
map_.mazePath(start_pt);
}