WedX - журнал о программировании и компьютерных науках

Указатель на указатель для суммирования уровней в программе BattleShip c++

Всем хорошего воскресенья!

Я пытаюсь научить себя С++, поэтому я делаю программу Battleship.

Эта версия достаточно стандартна. Игрок вводит координаты ячейки, чтобы попытаться поразить корабль. Программа, сообщающая о попадании в корабль. Если все ячейки, занятые кораблем, поражены, программа выводит сообщение о том, что этот корабль потоплен. После каждой попытки программа выводит текущее состояние, показывая доску со всеми успешными попытками, отмеченными "*" или "x" соответственно.

У меня возникли проблемы с написанием функции уровня в моем классе Board, которая суммирует все уровни кораблей на доске.

Итак, у меня есть такая доска для линкоров.

   a b c d e f g h i j
  +-------------------+
 0|                   |
 1|                   |
 2|                   |
 3|                   |
 4|                   |
 5|                   |
 6|                   |
 7|                   |
 8|                   |
 9|                   |
  +-------------------+

Это мой файл заголовка доски для контекста:

#ifndef BOARD_H
#define BOARD_H
#include "Ship.h"
#include <vector>
class Board
{
  public:
    Board(void);
    void addShip(char type, int x1, int y1, int x2, int y2);
    void print(void);
    void hit(char c, int i);
    int level(void);
  private:
    std::vector<Ship *> shipList;
    char score[10][10];
    Ship *shipAt(int x, int y);
};
#endif

У меня также есть класс корабля для хранения координат корабля

Вот мой заголовок корабля (возможно, нет необходимости читать все, просто посмотрите на функцию уровня):

//
// Ship.h
//

#ifndef SHIP_H
#define SHIP_H
class Ship
{
  public:
    virtual ~Ship(void) {}
    virtual const char *name(void) const = 0;
    virtual int size(void) const = 0;
    int getX(int i) const;
    int getY(int i) const;
    void print(void) const;
    bool includes(int x, int y);
    int level(void) const;
    void decreaseLevel(void);
    static Ship *makeShip(char ch, int x1, int y1, int x2, int y2);
  protected:
    void setPos(int a1, int b1, int a2, int b2);
    int lev;
  private:
    bool checkConfig(int x1, int y1, int x2, int y2);
    int x1,y1,x2,y2;
};

class AircraftCarrier : public Ship
{
  public:
    AircraftCarrier(int x1, int y1, int x2, int y2);
    virtual const char *name(void) const;
    virtual int size(void) const;
};

class BattleShip: public Ship
{
  public:
    BattleShip(int x1, int y1, int x2, int y2);
    virtual const char *name(void) const;
    virtual int size(void) const;
};

class Cruiser: public Ship
{
  public:
    Cruiser(int x1, int y1, int x2, int y2);
    virtual const char *name(void) const;
    virtual int size(void) const;
};

class Destroyer: public Ship
{
  public:
    Destroyer(int x1, int y1, int x2, int y2);
    virtual const char *name(void) const;
    virtual int size(void) const;
};
#endif

Вот мой класс корабля (возможно, нет необходимости читать все, поэтому я просто поставил функцию уровня)

#include "Ship.h"
#include <iostream>
#include <stdexcept>
using namespace std;

//LOTS OF CODE I OMITTED FOR BREVITY


int Ship::level (void) const
{
    return lev;
}





    }

В моем классе кораблей

int level(void)

функция возвращает текущее значение защищенной переменной lev

Вот что у меня есть для моего Board.cpp (извините за длинные куски кода, но необходимо предоставить контекст для этого вопроса):

#include "Board.h"
#include "Ship.h"
#include <iostream>
using namespace std;
#include <vector>
#include <string.h>
#include <stdexcept>


//member function definitions


Board::Board(void)
{
    //char score[10][10] = "                                                                                                    ";  
    char score[10][10] = {{' '}};
}

void Board::addShip(char type, int x1, int y1, int x2, int y2) 
{
    if(shipList.size()<=9)
        {
            shipList.push_back(Ship::makeShip(type ,x1 , y1,  x2,  y2)) ;
        }
}

void Board::print(void){

cout<< "   a b c d e f g h i j"<< endl;
cout <<"  +-------------------+"<< endl;
    for (int i = 0; i < 10; i++) {
        cout<<" "<< i <<"|" ;
        for (int j = 0; j < 10; j++) {
           cout << score[i][j];
        }
            if(i == 0){
                cout << "                  |";

            }
            else{
                cout << "                   |";
                }
        cout<< endl;

    }
    cout <<"  +-------------------+"<< endl;
}

void Board::hit(char c, int i){

    if (c<'a' || c>'j' || i > 9 || i<0){
        throw invalid_argument("invalid input");
    }

    Ship* ship = shipAt(i, c-'a');


    if (ship) {
        score[i][c-'a']= '*';
    }
    else{
        score[i][c-'a']= 'x';
    }


}

Ship* Board::shipAt(int x, int y){
    Ship* ship = shipAt(x, y);

    if (ship){
            return ship;   }
    else{
        return NULL;
         }


}
int Board::level(void)
{

}

В int level(void) функция должна возвращать сумму уровней всех кораблей на доске.

По сути, я не знаю, как бы я реализовал int level(void)в своем классе платы. Я пытаюсь вызвать уровень каждого указателя корабля и добавить к сумме, указывая указатель shipList на уровень в каждой итерации цикла. Но я изо всех сил пытаюсь это сделать.

25.05.2014

  • Я думаю, вы упустили суть, пожалуйста, прочитайте stackoverflow.com/help/how-to-ask. А в C++ это не int level(void), а int level() 26.05.2014
  • Извиняюсь. Мне пришлось поставить эту длину, потому что это требовалось, чтобы четко сообщить о проблеме. 26.05.2014
  • Хорошо, я ценю ваш вклад. Я сделаю все возможное, чтобы сократить свой вопрос для вас, ребята. 26.05.2014
  • level(void) эквивалентен level() в C++. Таким образом, level(void) не является недопустимым, но избыточным. 26.05.2014
  • Мне вбили в голову, что функция с единственным ключевым словом void в списке объявлений аргументов не принимает аргументов, поэтому я до сих пор не понимаю, почему это плохая практика... 26.05.2014
  • Это не совсем плохая практика, это просто... необычно. Вы можете ознакомиться с некоторыми проектами C++ среднего размера, чтобы узнать о текущих тенденциях C++. 26.05.2014

Ответы:


1

Я предлагаю цикл for (C++11) на основе диапазона (C++11) через ShipList для получения каждого указателя Ship и накопления уровня:

int Board::level() {
  int level = 0;
  for(Ship* ship : shipList)
    level += ship->level();
  return level;
}

Я думаю, что это выглядит чище, чем итератор или цикл for на основе индекса, особенно когда элементы являются указателями.

25.05.2014
  • Внимание, для этого требуется компилятор C++11 (ключевое слово auto) 26.05.2014
  • @kebs Да. И из-за цикла for на основе диапазона. 26.05.2014
  • Auto на самом деле не требуется в циклах range-for. Можно просто написать Корабль * корабль 26.05.2014
  • @Veritas: я думаю, что это делает код менее тесно связанный и более общий, гибкий, многоразовый и перспективный, но я не хочу ввязываться в auto войну, поэтому я его изменю. 26.05.2014
  • Я с вами, я как автос просто говорю, что это не особо требуется в данном случае. Теперь, когда я снова вижу комментарии, я думаю, что вчера неправильно их прочитал. 26.05.2014

  • 2

    Перебрать список Ship и накопить уровни каждого Ship. Вернуть накопленное значение.

    int Board::level(void)
    {
        int lev = 0;
        std::vector<Ship *>::iterator iter = shipList.begin();
        std::vector<Ship *>::iterator end = shipList.end();
        for ( ; iter != end; ++iter )
        {
           lev += (*iter)->level();
        }
    
        return lev;
    }
    
    25.05.2014
    Новые материалы

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..


    Для любых предложений по сайту: [email protected]