Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> прорисовка двумерного массива 
:(
    Опции темы
lenarano
Дата 1.11.2015, 12:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



На данный момент нужна помощь в том, что я не могу вывести levelsMap в поле класса, возникают ошибки. Если кто то покажет, как это будет-буду рада, может опять что-то упускаю. Если оставить как есть, то тогда естественно моя функция прорисовки void Map::display_maze( int level) его не видит. Подскажите пути исправления


Код

#ifndef MAP_H
#define MAP_H
#include <SFML\Graphics.hpp>
class Map{
private:
int m_level;
 
public: 
   enum { HEIGHT_MAP=25, WIDTH_MAP=28 };
   sf::String TileMap[HEIGHT_MAP];
 
 Map();
 
 int getLevel();
 
 void setLevel(int level);
 
 void display_maze( int level);
};
 
 
 
#include "map.h"
 
#include <iostream>
 
 
 
Map::Map()
{
    setLevel(0);
    
}
 
int Map:: getLevel() { return m_level; }
 
void Map:: setLevel(int level)
{
    static const char* levelsMap[][HEIGHT_MAP] = {
        { 
                "0000000000000000000000000000",/* Инициализация 0-го уровня */
                "0   S                      0",
                "0                          0",
                "0  0 s0   0      0   0s 0 G0",
                "0  0000   0mmmmmm0   0000  0",
                "0  0mm0   00000000   0mm0  0",
                "0                          0",
                "0                          0",
                "0  0mm0   000  000   0mm0  0",
                "0  0000   0      0   0000  0",
                "0  0mm0   0      0   0mm0  0",
                "t         000  000         T",
                "t                          T",
                "t                          T",
                "0  0mm0   00000000   0mm0  0",
                "0  0000              0000  0",
                "0  0mm0              0mm0  0",
                "0         00000000         0",
                "0                          0",
                "0  0mm0              0mm0  0",
                "0  0000   00000000   0000  0",
                "0  0 s0              0s 0  0",
                "0                          0",
                "0                          0",
                "0000000000000000000000000000", },
            {"0000000000000000000000000000", /* Инициализация 1-го уровня */ 
            "0                          0",
            "0                          0",
            "0  0                    0  0",
            "0  0000              0000  0",
            "0  0      000  000      0  0",
            "0         0      0         0",
            "0         0      0         0",
            "0  0mm    000  000    mm0  0",
            "0  0000              0000  0",
            "0  0                    0  0",
            "t         00000000         T",
            "t           m00m           T",
            "t           m00m           T",
            "0  0      00000000      0  0",
            "0  0000              0000  0",
            "0  0                    0  0",
            "0                          0",
            "0      0000      0000      0",
            "0  0      0s    s0      0  0",
            "0  0  0   00000000   0  0  0",
            "0  0  0   0mmmmmm0   0  0  0",
            "0                          0",
            "0                          0",
            "0000000000000000000000000000", },
            { /* Инициализация 2-го уровня */ },
    };
    int levelsCount = sizeof(levelsMap) / sizeof(levelsMap[0]);
    if (level < 0 || level >= levelsCount)
        level = 0;
    m_level = level;
    for(int i=0; i < HEIGHT_MAP; i++)
    {TileMap[i] = levelsMap[level][i];
    std::cout<<levelsMap[level][i];
    printf("\n");
    }
}
 
 
void Map::display_maze( int level)
{
    int i;
    printf("MAZE:\n");
    for(int i=0; i < Map::HEIGHT_MAP; i++)
    {TileMap[i] = levelsMap[level][i];
    std::cout<<levelsMap[level][i];
    printf("\n");
    }
 
    return;
}

PM MAIL   Вверх
feodorv
Дата 1.11.2015, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Не понял, что Вы хотите, и что за ошибки возникают. Может, так:
Цитата(lenarano @  1.11.2015,  12:07 Найти цитируемый пост)
void Map::display_maze( int level)
{
    std::cout << "MAZE:" << std::endl;
    for( int i=0; i < Map::HEIGHT_MAP; i++)
    {
       TileMap[i] = levelsMap[level][i];
       std::cout << TileMap[i] << std::endl;
    }
}




--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
volatile
Дата 1.11.2015, 17:28 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(lenarano @  1.11.2015,  12:07 Найти цитируемый пост)
   static const char* levelsMap[][HEIGHT_MAP] = {
это нужно вынести из функции, иначе не видно снаружи.
в классе написать декларацию:
Код

static const char* levelsMap[][HEIGHT_MAP];

а где-то в спп-шнике определение:
Код

const char* Map::levelsMap[][HEIGHT_MAP] = {
    { 
            "0000000000000000000000000000",/* Инициализация 0-го уровня */
            "0   S                      0",
            "0                          0",
            ...

PM MAIL   Вверх
lenarano
Дата 2.11.2015, 00:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



Спасибо всем, проблема была в том, что я пробовала иницилизировать его в конструкторе в срр файле, хотя до этого объявила его в заголовочном. Почему нельзя было?
Хотела еще спросить. Я эту прорисовку хотела использовать для того, чтобы видеть мой алгоритм кратчайшего пути. Т.е. по идее я должна была вызвать прорисовку карты,затем преобразование карты, и затем ту же прорисовку, но на ней должны были отобразиться изменения- + там где есть путь.
Сама прорисовка рабочая,т.е когда я запускаю игру с одной функцией преобразования, то мои тайлики выстраивают путь и я его вижу, но когда я делаю так:
Код

map->display_maze(0);
            
            if (map-> find_path(11, 15) == TRUE )
                printf("Success!\n");
        else
                printf("Failed\n");
             
    map->display_maze(0);

У меня в моей консольке видно, что массив не преобразуется и карта пути тайликами не прорисовывается. Я подумала,что у нас значения переменной константное,ничего не помогло.
 static  char* levelsMap[][HEIGHT_MAP];
Почему так?
PM MAIL   Вверх
lenarano
Дата 2.11.2015, 09:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



В вложениях показала как отрисовывается путь, когда работает только алгоритм поиска пути и когда сначала рисую массив, потом прорабатываю алгоритм и опять рисую ничего не вижу. Путь на массиве должен быть выложен "+",  а получается, что и не прорисовывается не в массиве и не на карте.

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  Безымянный.png 193,92 Kb
PM MAIL   Вверх
lenarano
Дата 2.11.2015, 09:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



вот как с функцией прорисовки
Код

map->display_maze(0);
            
            if (map-> find_path(11, 15) == TRUE )
                printf("Success!\n");
        else
                printf("Failed\n");
             
    map->display_maze(0);


Присоединённый файл ( Кол-во скачиваний: 4 )
Присоединённый файл  Безымянный2.png 152,77 Kb
PM MAIL   Вверх
math64
Дата 2.11.2015, 09:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



displayMaze() инициализирует массив TileMap из levelsMap:
Код

    std::cout << "MAZE:" << std::endl;
    for( int i=0; i < Map::HEIGHT_MAP; i++)
    {
       TileMap[i] = levelsMap[level][i];
       std::cout << TileMap[i] << std::endl;
    }

Естественно, если какой-то путь был посчитан, здесь он затирается.
PM   Вверх
lenarano
Дата 2.11.2015, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



А как это изменить? Я планирую эту функцию использовать для того, что бы видеть прорисовку моего пути, т.е. нужно, чтобы массив мог видоизменяться?

Добавлено через 11 минут и 59 секунд
Еще хотела спросить. У меня сейчас видно, что я просто обозначила на карте где буднт прорисовываться 'G' и 'S' и я по этому алгоритму прорисовываю свой путь. Вот кусочек кода с прорисовкой и реализацией алгоритма поиска пути
Код

void Map::display_maze( int level)
{
    int i;
    printf("MAZE:\n");
    for(int i=0; i < Map::HEIGHT_MAP; i++)
    {TileMap[i] = levelsMap[level][i];
    std::cout<<levelsMap[level][i];
    std::cout << std::endl;
    }
 
    return;
}


int Map::find_path(int x, int y)
{
        // Если x,y находится за пределами лабиринта, вернуть false.
        if ( x < 0 || x > WIDTH_MAP - 1 || y < 0 || y > HEIGHT_MAP - 1 ) return FALSE;

        // Если x,y-это цель, возвратите True.
        if ( TileMap[y][x] == 'G' ) return TRUE;

        // Если x,y не открыть, вернуть false.
        if ( TileMap[y][x] != ' ' && TileMap[y][x] != 'S' ) return FALSE;

        // + часть решения, пути.
        TileMap[y][x] = '+';

        // If find_path North of x,y is true, return true.
        if ( find_path(x, y - 1) == TRUE ) return TRUE;

        // If find_path East of x,y is true, return true.
        if ( find_path(x + 1, y) == TRUE ) return TRUE;

        // If find_path South of x,y is true, return true.
        if ( find_path(x, y + 1) == TRUE ) return TRUE;

        // If find_path West of x,y is true, return true.
        if ( find_path(x - 1, y) == TRUE ) return TRUE;

        // Снять х,Y как часть решения, пути.
        TileMap[y][x] = 'x';

        return FALSE;
}





Теперь я хочу перейти к следующему этапу, когда 
Этaп построения мaршрутa перемещения. Присвaивaем переменным Х и Y знaчения координaт стaртовой позиции. 
Т.е. я хочу передать координаты врага и пакмана и нарисовать на их месте на карте 'S'и 'G' , а не прорисовывать их на карте. Все эти изменения сейчас пытаюсь сделать.
Вот мой класс героя
Код

#ifndef PLAYER_H
#define PLAYER_H



#include "Entity.h"
#include "View.h"
//#include "map.h"


class Player:public Entity{
private:
int m_health;
int m_counter;
int m_createObjectForMapTimer;
int m_counterBonus;
int m_counterGoldIngot;
float m_currentFrame;
bool m_killer;
bool m_bonus;
std::shared_ptr<sf::View> m_view;
Map* m_map;

public:
        
    Player(Map* map,std::shared_ptr<sf::View> view, sf::Image &image,sf::String Name,float X, float Y, float W, float H);

    int getHealth (Player &p) const;
    void setHealth(Player &p, int a);
    int getCounterBonus (Player &p) const;
    void multiplyCounterBonus(Player &p, int a);
    int getCounterGoldIngot(Player &p) const;
    int getKiller(Player &p) const;
    void control();
    void update(float time);
    void interactionWithMap();
    void randomMapGenerate();
    //float GetPlayercoordinateX(){return x;}
    //float GetPlayercoordinateY(){return y;}

    
};



#endif PLAYER_H

#include "Player.h"
#include "map.h"
#include <SFML/Graphics.hpp>





Player::Player(Map* map,std::shared_ptr<sf::View> view, sf::Image &image,sf::String Name,float X, float Y, float W, float H):Entity(image, Name, X,Y,W,H){
    m_view = view;    
    m_map=map;
    m_health=3,
        m_counter=0,
        m_createObjectForMapTimer=0,
        m_counterBonus=0,
        m_counterGoldIngot=3,
        m_currentFrame=3;
    m_killer=false;
    m_bonus=false;
    state=stay;//инициализировали
    if (name == "Player1"){sprite.setTextureRect(sf::IntRect(99,224,w,h));}//если герои от уровня к уровню будут разные    
}

int Player::getHealth (Player &p) const {return p.m_health;}

void Player::setHealth(Player &p, int a){p.m_health += a;}

int Player::getCounterBonus (Player &p) const {return p.m_counterBonus;}

void Player::multiplyCounterBonus(Player &p, int a){p.m_counterBonus *= a;}

int Player::getCounterGoldIngot(Player &p) const {return p.m_counterGoldIngot;}

int Player::getKiller(Player &p) const {return p.m_killer;}

void Player::control()
{
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){state=left; speed=0.1;}
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){state=right;speed=0.1;}
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){state=up; speed=0.1;}
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){state=down;speed=0.1;}
}


void Player::interactionWithMap()
{
    for (int i = y / 32; i < (y + h) / 32; i++)
        for (int j = x / 32; j<(x + w) / 32; j++)
        {
            if (m_map->TileMap[i][j] == '0')
            {
                if (dy>0){y = i * 32 - h;}
                if (dy<0){y = i * 32 + 32;}
                if (dx>0){x = j * 32 - w;}
                if (dx < 0){x = j * 32 + 32;}
            }

            if (m_map->TileMap[i][j] == 't')
            {
                x=830; y=390;
            }

            if (m_map->TileMap[i][j] == 'T')
            {
                x=50; y=390;
            }

            if (m_map->TileMap[i][j] == 'm')
            {
                m_counterGoldIngot--;
                m_map->TileMap[i][j] = ' ';

            }

            if (m_map->TileMap[i][j] == 's')
            {
                m_killer=true;
                m_map->TileMap[i][j] = ' ';
            }

            if (m_map->TileMap[i][j] == 'f')
            {
                m_bonus=false;
                m_counterBonus+=100;
                m_map->TileMap[i][j] = ' ';
            }
        }

}    

void Player::randomMapGenerate(){//рандомно расставляем камни

    int randomElementX = 0;//случайный элемент по горизонтали
    int randomElementY = 0;//случ эл-т по вертикали
    srand(time(0));//рандом    
    int countStone = 1;//количество камней

    while (countStone>0){
        randomElementX = 1 + rand() % (m_map->WIDTH_MAP - 1);//рандомное по иксу от 1 до ширина карты-1, чтобы не получать числа бордюра карты
        randomElementY = 1 + rand() % (m_map->HEIGHT_MAP - 1);//по игреку так же

        if (m_map->TileMap[randomElementY][randomElementX] == ' ')   {//если встретили символ пробел, 
            m_map->TileMap[randomElementY][randomElementX] = 'f'; //то ставим туда яблоко
            countStone--;
            m_bonus=true;
        }
    }    
}


void Player::update(float time)
{
    control();
    switch (state)
    {
    case right: dx=speed; dy=0; break;
    case left: dx=-speed;dy=0; break;
    case down: dx=0; dy=speed; break;
    case up: dx=0; dy=-speed; break;
    default: dx=0; dy=0;//case stay:break;
    }
    x+=dx*time;
    y+=dy*time;
    speed=0;
    sprite.setPosition(x+w/2,y+h/2);
    interactionWithMap();
    //////////анимация
    m_currentFrame+=0.005*time;
    if (m_currentFrame>6) m_currentFrame-=3;
    if (dx > 0) sprite.setTextureRect(sf::IntRect(31.2*int (m_currentFrame),192,32,32));
    if (dx < 0) sprite.setTextureRect(sf::IntRect(33*int (m_currentFrame),160,32,32));
    if (dy > 0) sprite.setTextureRect(sf::IntRect(32 *int(m_currentFrame),128,32,32));
    if (dy < 0) sprite.setTextureRect(sf::IntRect(32.9*int (m_currentFrame),224,32,32));
    if(m_counterGoldIngot<=0){m_map->setLevel(+1);m_counterGoldIngot=3;x=460;y=720;}
    if(m_killer==true)
    {   sprite.setColor(sf::Color::Red);
    m_counter += time;
    if(m_counter>10000){m_killer=false;m_counter=0; sprite.setColor(sf::Color::White);}
    }
    if(m_counterBonus>=1000){ m_health ++;m_counterBonus=0;}

    if (m_bonus==false){
        m_createObjectForMapTimer += time;//наращиваем таймер
        if (m_createObjectForMapTimer>10000)
        {
            randomMapGenerate();//генерация случ камн
            m_createObjectForMapTimer = 0;//обнуляем таймер
        }
    }
    if (life) 
    {
        GetPlayerCoordinateForView(m_view, sprite.getPosition().x,sprite.getPosition().y);
    }

}






и Врага
Код

#ifndef ENEMY_H
#define ENEMY_H

#include "Entity.h"




class Enemy:public Entity{
private:
        Map* m_map;
public:
    int zq,timer;
    float CurrentFrame;
    
    Enemy (Map* map,sf::Image &image,sf::String Name,float X, float Y, float W, float H): Entity(image,Name,X,Y,W,H){
        m_map=map;
        zq=1;state=left;timer=0;CurrentFrame=0;
        if(name=="EasyEnemy"){
            sprite.setTextureRect(sf::IntRect(0,0,w,h));
        }

    }

    void checkCollisionWithMap()//ф ция проверки столкновений с картой
    {
        for (int i = y / 32; i < (y + h) / 32; i++)
            for (int j = x / 32; j<(x + w) / 32; j++)
            {
                if (m_map->TileMap[i][j] == '0')
                {
                    if (dy>0){y = i * 32 - h;}
                    if (dy<0){y = i * 32 + 32;}
                    if (dx>0){x = j * 32 - w;}
                    if (dx < 0){x = j * 32 + 32;}
                }
            }
    }


    void update(float time)
    {
        if (name == "EasyEnemy"){//для персонажа с таким именем логика будет такой
            //timer+=time;
            //if (timer+1000>1000) {zq=rand()%3;}
            //if (timer>500) {if (zq==0)  {if (x>px) {speed=0.1,state=left; timer=0;} {if (y>py) {speed=0.1,state=up; timer=0;} }}}
            //if (timer>500) {if (zq==1)  {if (x<px) {speed=0.1,state=right; timer=0;} {if (y<py) {speed=0.1,state=down; timer=0;} }}}
            
            switch(state)
            {
            case right: dx=speed; dy=0;  break;
            case left: dx=-speed; dy=0;  break;
            case down: dx=0; dy=speed; break;
            case up: dx=0; dy=-speed;   break;
            case stay:break;
            }

            x += dx*time;
            y += dy*time;
            checkCollisionWithMap();
           /* m_map->display_maze(0);
            
             if ( m_map->find_path(11, 15) == TRUE )
                printf("Success!\n");
        else
                printf("Failed\n");
            ;    
        //    m_map->display_maze(0);*/
            
     
            sprite.setPosition(x + w / 2, y + h / 2); //задаем позицию спрайта в место его центра
            //////////анимация
    CurrentFrame+=0.005*time;
    if (CurrentFrame>3) CurrentFrame-=3;
    if (dx > 0) sprite.setTextureRect(sf::IntRect(32*int (CurrentFrame),64,32,32));
    if (dx < 0) sprite.setTextureRect(sf::IntRect(32*int (CurrentFrame),32,32,32));
    if (dy > 0) sprite.setTextureRect(sf::IntRect(32*int(CurrentFrame),0,32,32));
    if (dy < 0) sprite.setTextureRect(sf::IntRect(32*int (CurrentFrame),97,32,32));
        }
    }



};




#endif ENTITY_H






В main в обработчике событий я хочу в обработчике событий передать эти координаты

Код

Player pacman(map,view, heroimage,"Player1",460,730,32.0,32.0);//передаем координаты прямоугольника player из карты в координаты нашего игрока

    std::list<Entity*> entities;//список,куда будем бросать объекты
    std::list <Entity*>::iterator it;//итератор, чтобы проходить по элементам списка
    std::list <Entity*>::iterator it2;//враг-враг
    
    
    entities.push_back(new Enemy(map,easyEnemyImage,"EasyEnemy",410,290,32.0,32.0));
    //entities.push_back(new Enemy(map,easyEnemyImage,"EasyEnemy",425,290,32.0,32.0));
    //entities.push_back(new Enemy(map,easyEnemyImage,"EasyEnemy",440,190,32.0,32.0));

..........

for (it = entities.begin(); it != entities.end(); it++)//проходимся по эл-там списка
        {   
            if ((*it)->name=="EasyEnemy")
            { 
                //  int i=int(pacman.x);
               // int j=int(pacman.y);
                (*it)->getPlayerCoord(pacman.x,pacman.y);
                //  map->TileMap[i][j] = 'G';
                //  map->TileMap[int((*it)->x)][int((*it)->y)] = 'S';
                if (((*it)->x-pacman.x<55)&&((*it)->y>pacman.y))  {(*it)->dy=-0.5,(*it)->dx=0;} 
                if (((*it)->x-pacman.x<54)&&((*it)->y<pacman.y)) {(*it)->dy=0.5,(*it)->dx=0;}
                if ((pacman.y-(*it)->y<53)&&((*it)->x<pacman.x)) {(*it)->dx=0.5,(*it)->dy=0;}
                if (((*it)->y-pacman.y<56)&&((*it)->x>pacman.x)) {(*it)->dx=-0.5,(*it)->dy=0;}
            }







Что я тут делаю не так? Почему выдается ошибка, программа не запускается. Хочу добиться прорисовки дорожки от девочки к дракону. 

PM MAIL   Вверх
math64
Дата 2.11.2015, 11:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



Ну, я бы не стал портить карту во время поиска пути.
Код

struct Point { int x, int y};
std::list<Point> find_path(const Point& start);
std::list<Point> find_path(int x, int y) { Point start = { x, y }; return find_path(start); }

find_path() возвращает пустой список если путь не найден.
Если путь будет найден - его можно будет отобразить на карте.
При рекурсивном поиске пути нужно помечать, где уже были, чтобы не возвращаться. Делаем это на временной карте:
Код

enum flag {
  free, // свободно
  wall, // стенка
  startpoint, // начало пути
  endpoint, // конец пути
  inpath, // в пробном пути
  noway, // проверено, что ведет в тупик
  ...
};
std::list<Point> find_path(const Point& start) {
  flag tempMap[HEIGHT_MAP][WIDTH_MAP];
  for(int y =0; y < HEIGHT_MAP; y++)
    for(int x =0; x < WIDTH_MAP; x++)
        tempMap[y][x] = free; // или wall - см. оригинальную карту
  tempMap[start.y][start.x] = startpoint;
  return find_path(const Point& start, tempMap); // Вызываем рекурсивную функцию
}

PM   Вверх
math64
Дата 2.11.2015, 12:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



PS: значения flag лучше задавить степенями двойки:
Код

enum flag {
  free = 0, // свободно
  wall = 1, // стенка
  gold = 2, // золото
  enemy = 4, // враг
  startpoint = 8, // начало пути
  endpoint = 16, // конец пути
  inpath = 32, // в пробном пути
  noway = 64, // проверено, что ведет в тупик
  ...
};

Тогда можно задавать комбинации значений:
Код

gold | enemy; // золото, охраняемое врагом
gold | inpath; // путь через клетку с золотом

PM   Вверх
lenarano
Дата 2.11.2015, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



Не поняла((
У нас есть
 struct Point { int x, int y};
std::list<Point> find_path(int x, int y) { Point start = { x, y }; return find_path(start); }
Я должна это добавить в класс врага?
Я в листе информация о передвижении моего врага, т.е. где он находится?

А потом в классе карта я работаю уже
std::list<Point> find_path(const Point& start); передаю координаты врага 
enum flag {
  free, // свободно
  wall, // стенка
  startpoint, // начало пути
  endpoint, // конец пути
  inpath, // в пробном пути
  noway, // проверено, что ведет в тупик
  ...
};

и реализация в cpp/ файле?
std::list<Point> find_path(const Point& start) {
  flag tempMap[HEIGHT_MAP][WIDTH_MAP];
  for(int y =0; y < HEIGHT_MAP; y++)
    for(int x =0; x < WIDTH_MAP; x++)
        tempMap[y][x] = free; // или wall - см. оригинальную карту
  tempMap[start.y][start.x] = startpoint;
  return find_path(const Point& start, tempMap); // Вызываем рекурсивную функцию
}
PM MAIL   Вверх
lenarano
Дата 2.11.2015, 14:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



Ребята, вы меня конечно извините, что туплю. У меня уже с этим курсовым скоро крыша поедет. Варюсь в собственном соку-так получилось. Деваться некуда -стараюсь делать, а знаний и умений мало. Вот как мне оживить моих врагов. 
math64, вот вы мне показали, а я не могу понять куда, что всунуть и до конца, что где обозначает. 
Вот мои основные классы , которые тут нужны. Карта, враг, герой. Что мне добавить куда и как вставить, чтобы мои враги поумнели и карту  я увидела.
Код

#ifndef MAP_H
#define MAP_H


#define FALSE 0
#define TRUE 1

#include <SFML\Graphics.hpp>



class Map{
private:
int m_level;

public: 
   enum { HEIGHT_MAP=25, WIDTH_MAP=28 };
   sf::String TileMap[HEIGHT_MAP];
   static const char* levelsMap[][HEIGHT_MAP];
  

 Map();
 
 int getLevel();

 void setLevel(int level);

 void display_maze( int level);

 int find_path(int x, int y);

};

 
#endif

#include "map.h"

#include <iostream>

const char * Map::levelsMap[][Map::HEIGHT_MAP] = {
        { 
                "0000000000000000000000000000",/* Инициализация 0-го уровня */
                "0   S                      0",
                "0                          0",
                "0  0 s0   0      0   0s 0 G0",
                "0  0000   0mmmmmm0   0000  0",
                "0  0mm0   00000000   0mm0  0",
                "0                          0",
                "0                          0",
                "0  0mm0   000  000   0mm0  0",
                "0  0000   0      0   0000  0",
                "0  0mm0   0      0   0mm0  0",
                "t         000  000         T",
                "t                          T",
                "t                          T",
                "0  0mm0   00000000   0mm0  0",
                "0  0000              0000  0",
                "0  0mm0              0mm0  0",
                "0         00000000         0",
                "0                          0",
                "0  0mm0              0mm0  0",
                "0  0000   00000000   0000  0",
                "0  0 s0              0s 0  0",
                "0                          0",
                "0                          0",
                "0000000000000000000000000000"},
            {"0000000000000000000000000000", /* Инициализация 1-го уровня */ 
            "0                          0",
            "0                          0",
            "0  0                    0  0",
            "0  0000              0000  0",
            "0  0      000  000      0  0",
            "0         0      0         0",
            "0         0      0         0",
            "0  0mm    000  000    mm0  0",
            "0  0000              0000  0",
            "0  0                    0  0",
            "t         00000000         T",
            "t           m00m           T",
            "t           m00m           T",
            "0  0      00000000      0  0",
            "0  0000              0000  0",
            "0  0                    0  0",
            "0                          0",
            "0      0000      0000      0",
            "0  0      0s    s0      0  0",
            "0  0  0   00000000   0  0  0",
            "0  0  0   0mmmmmm0   0  0  0",
            "0                          0",
            "0                          0",
            "0000000000000000000000000000"}
    };

Map::Map()
{
        setLevel(0);
    
}

int Map:: getLevel() { return m_level; }

void Map:: setLevel(int level)
{
    
    int levelsCount = sizeof(levelsMap) / (Map::HEIGHT_MAP * sizeof(char *));

    if (level < 0 || level >= levelsCount)
        level = 0;
    m_level = level;
    for(int i=0; i < HEIGHT_MAP; i++)
    {TileMap[i] = levelsMap[level][i];}
}



/*void Map::display_maze( int level)
{
    int i;
    printf("MAZE:\n");
    for(int i=0; i < Map::HEIGHT_MAP; i++)
    {TileMap[i] = levelsMap[level][i];
    std::cout<<levelsMap[level][i];
    printf("\n");
    }
 
    return;
}*/


int Map::find_path(int x, int y)
{
        // Если x,y находится за пределами лабиринта, вернуть false.
        if ( x < 0 || x > WIDTH_MAP - 1 || y < 0 || y > HEIGHT_MAP - 1 ) return FALSE;

        // Если x,y-это цель, возвратите True.
        if ( TileMap[y][x] == 'G' ) return TRUE;

        // Если x,y не открыть, вернуть false.
        if ( TileMap[y][x] != ' ' && TileMap[y][x] != 'S' ) return FALSE;

        // + часть решения, пути.
        TileMap[y][x] = '+';

        // If find_path North of x,y is true, return true.
        if ( find_path(x, y - 1) == TRUE ) return TRUE;

        // If find_path East of x,y is true, return true.
        if ( find_path(x + 1, y) == TRUE ) return TRUE;

        // If find_path South of x,y is true, return true.
        if ( find_path(x, y + 1) == TRUE ) return TRUE;

        // If find_path West of x,y is true, return true.
        if ( find_path(x - 1, y) == TRUE ) return TRUE;

        // Снять х,Y как часть решения, пути.
        TileMap[y][x] = 'x';

        return FALSE;
}






Класс героя и врага в предыдущем посте.
PM MAIL   Вверх
math64
Дата 2.11.2015, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



Главная идея - при поиске пути использовать временную карту.
Куда запихнуть? Можно в класс карты, можно в класс игрока (если путь ищется для игрока), можно в класс врага (если путь ищется для врага), можно в базовый класс Entity для игрока и врага (путь ищется для того и другого, в производных классах можно переоределить специфику)
показывыть путь лучше не в консоли, а в игровом окне - так нагляднее, но я не знаю возможностей вашего движка.
Реализовать можно примерно так (могут быть ошибки):
Код

std::list<Point> Map::find_path(int start_x, start_y) {
  if ( start_x < 0 || start_x > WIDTH_MAP - 1 || start_y < 0 || start_y > HEIGHT_MAP - 1 )
   return std::list<Point>(); // Empty list
  flag tempMap[HEIGHT_MAP][WIDTH_MAP];
  for(int y =0; y < HEIGHT_MAP; y++)
    for(int x =0; x < WIDTH_MAP; x++) {
       flag f;
       switch (TileMap[y][x]) {
         case ' ': f = free; break;
         case 'O': f = wall; break;
         case 'G': f = endpoint;
       }
       tempMap[y][x] = f;
    }
  tempMap[start_y][start_x] |= startpoint;
  std::list<Point> path;
  return find_path(x, y, tempMap, path); // Вызываем рекурсивную функцию
}
std::list<Point> Map::find_path(int start_x, start_y,
       flag tempMap[HEIGHT_MAP][WIDTH_MAP],
       std::list<Point> path) {
  if ( x < 0 || x > WIDTH_MAP - 1 || y < 0 || y > HEIGHT_MAP - 1 )
   return std::list<Point>(); // Empty list
  Point point = { x, y };
  path.push_back(point);
  // Если x,y-это цель, возвратите True.
  if ( (tempMap[y][x] & endpoint) != 0) return path;
  // Если x,y не открыть, вернуть false.
  if ( (tempMap[y][x] & wall) != 0)
    return std::list<Point>();
  // Мы сдесь уже были
  if ( (tempMap[y][x] & (inpath|noway)) != 0)
    return std::list<Point>();
  tempMap[y][x] |= inpath; // + часть решения, пути.
  // If find_path North of x,y is true, return true.
  std::list<Point> ret_path;
  if ( !(ret_path = find_path(x, y - 1, tempMap, path)).empty() ) return ret_path;
  if ( !(ret_path = find_path(x + 1, y, tempMap, path)).empty() ) return ret_path;
  if ( !(ret_path = find_path(x, y + 1, tempMap, path)).empty() ) return ret_path;
  if ( !(ret_path = find_path(x - 1, y, tempMap, path)).empty() ) return ret_path;
  // Снять х,Y как часть решения, пути.
  tempMap[y][x] &= ~inpath;
  tempMap[y][x] |= noway;
  return std::list<Point>();
}


Это сообщение отредактировал(а) math64 - 2.11.2015, 15:35
PM   Вверх
lenarano
Дата 2.11.2015, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 62
Регистрация: 17.4.2014

Репутация: нет
Всего: нет



Оставила в классе Map только прорисовку карты. Решила реализовать в классе Врага, т.к. он преследует героя.
Код

#ifndef ENEMY_H
#define ENEMY_H

#include "Entity.h"




class Enemy:public Entity{
private:
    Map* m_map;
public:
    float CurrentFrame;
    struct Point { int x; int y;};
    enum flag {
        free = 0, // свободно
        wall = 1, // стенка
        gold = 2, // золото
        enemy = 4, // враг
        startpoint = 8, // начало пути
        endpoint = 16, // конец пути
        inpath = 32, // в пробном пути
        noway = 64, // проверено, что ведет в тупик
    };
    Enemy (Map* map,sf::Image &image,sf::String Name,float X, float Y, float W, float H): Entity(image,Name,X,Y,W,H){
        m_map=map;
        state=left;CurrentFrame=0;
        //zq=1;timer=0;
        if(name=="EasyEnemy"){
            sprite.setTextureRect(sf::IntRect(0,0,w,h));
        }

    }

    void checkCollisionWithMap()//ф ция проверки столкновений с картой
    {
        for (int i = y / 32; i < (y + h) / 32; i++)
            for (int j = x / 32; j<(x + w) / 32; j++)
            {
                if (m_map->TileMap[i][j] == '0')
                {
                    if (dy>0){y = i * 32 - h;}
                    if (dy<0){y = i * 32 + 32;}
                    if (dx>0){x = j * 32 - w;}
                    if (dx < 0){x = j * 32 + 32;}
                }
            }
    }


    void update(float time)
    {
        if (name == "EasyEnemy"){//для персонажа с таким именем логика будет такой

            switch(state)
            {
            case right: dx=speed; dy=0;  break;
            case left: dx=-speed; dy=0;  break;
            case down: dx=0; dy=speed; break;
            case up: dx=0; dy=-speed;   break;
            case stay:break;
            }

            x += dx*time;
            y += dy*time;
            checkCollisionWithMap();

            sprite.setPosition(x + w / 2, y + h / 2); //задаем позицию спрайта в место его центра
            //////////анимация
            CurrentFrame+=0.005*time;
            if (CurrentFrame>3) CurrentFrame-=3;
            if (dx > 0) sprite.setTextureRect(sf::IntRect(32*int (CurrentFrame),64,32,32));
            if (dx < 0) sprite.setTextureRect(sf::IntRect(32*int (CurrentFrame),32,32,32));
            if (dy > 0) sprite.setTextureRect(sf::IntRect(32*int(CurrentFrame),0,32,32));
            if (dy < 0) sprite.setTextureRect(sf::IntRect(32*int (CurrentFrame),97,32,32));
        }
    }


    std::list<Point> find_path(int start_x, int start_y) {//идентификатор start_y не определен
        if ( start_x < 0 || start_x > m_map->WIDTH_MAP - 1 || start_y < 0 || start_y >  m_map->HEIGHT_MAP - 1 )//идентификатор start_y не определен
            return std::list<Point>(); // Empty list
        flag tempMap[m_map->HEIGHT_MAP][m_map->WIDTH_MAP];
        for(int y =0; y < m_map->HEIGHT_MAP; y++)
            for(int x =0; x < m_map->WIDTH_MAP; x++) {
                flag f;
                switch (m_map->TileMap[y][x]) {
                case ' ': f = free; break;
                case 'O': f = wall; break;
                case 'G': f = endpoint;
                }
                tempMap[y][x] = f;
            }
            tempMap[start_y][start_x] = startpoint;
            std::list<Point> path;
            return find_path(x, y, tempMap, path); // Вызываем рекурсивную функцию
    }

    std::list<Point> find_path(int start_x, int start_y,flag tempMap[Map::HEIGHT_MAP][Map::WIDTH_MAP],std::list<Point> path) {
            if ( x < 0 || x > m_map->WIDTH_MAP - 1 || y < 0 || y > m_map->HEIGHT_MAP - 1 )
                return std::list<Point>(); // Empty list
            Point point = { x, y };
            path.push_back(point);
            // Если x,y-это цель, возвратите True.
            if ( (tempMap[y][x] & endpoint) != 0) return path;
            // Если x,y не открыть, вернуть false.
            if ( (tempMap[y][x] & wall) != 0)
                return std::list<Point>();
            // Мы здесь уже были
            if ( (tempMap[y][x] & (inpath|noway)) != 0)
                return std::list<Point>();
            tempMap[y][x] |= inpath; // + часть решения, пути.
            // If find_path North of x,y is true, return true.
            std::list<Point> ret_path;
            if ( !(ret_path = find_path(x, y - 1, tempMap, path)).empty() ) return ret_path;
            if ( !(ret_path = find_path(x + 1, y, tempMap, path)).empty() ) return ret_path;
            if ( !(ret_path = find_path(x, y + 1, tempMap, path)).empty() ) return ret_path;
            if ( !(ret_path = find_path(x - 1, y, tempMap, path)).empty() ) return ret_path;
            // Снять х,Y как часть решения, пути.
            tempMap[y][x] &= ~inpath;
            tempMap[y][x] |= noway;
            return std::list<Point>();
    }


};

#endif ENTITY_H








Компилятор ругается на эти строки, подчеркивая переменную y.(в последней функции)
if ( (tempMap[y][x] & endpoint) != 0) return path;
if ( (tempMap[y][x] & wall) != 0)
if ( (tempMap[y][x] & (inpath|noway)) != 0)
и т.д.
Пишет:
 выражение должно относиться к целочисленному типу или типу перечисления без области видимости    
индекс имеет нецелый тип    




Посмотрите правильно ли я все остальное указала. Но вроде больше ошибок нет.

Это сообщение отредактировал(а) lenarano - 2.11.2015, 18:13
PM MAIL   Вверх
math64
Дата 3.11.2015, 08:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 12
Всего: 72



Ну, можно было заметить мою ошибку (предупреждал, что могут быть). Параметры функции - start_x и start_y, а внутри функции - x и y.
Если будет ругаться на tempMap[y][x] &= ~inpath;
придется писать tempMap[y][x] = (flag)(tempMap[y][x]&~inpath); или объявить int tempMap[HEIGHT_MAP][WIDTH_MAP].

Относительно того как показывать результат поиска пути.
В подобных библиотеках обычно имеется возможность работать со слоями (Layer)
Карту нужно разбить на слои:
1. собственно карта - стены и проходы
2. неподвижные объекты - золото
3. подвижные объекты - спрайты - игрок и враги
4. слой отладки - в нем и выводить найденный путь.
5. Слой надписей (GAME OVER)

PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1113 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.