Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
0 / 0 / 1
Регистрация: 28.03.2014
Сообщений: 15
1

"Морской бой": массив указателей на объекты vs контейнер stl. Что лучше?

25.07.2015, 01:07. Просмотров 1037. Ответов 4
Метки нет (Все метки)

Задание такое:
Задача№2
Разработать программу «Морской бой», где пользователь будет видеть свои 2 игровых поля и вводить соответствующие значения и видеть результат операции (попал/убил/промазал). В отчете необходимо будет обосновать использование соответствующих контейнеров и алгоритмов.


C++
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
#include "headers.h"
#include "kletka.cpp"
#include "basek.cpp"
#include "potomok.cpp"
#include <windows.h>
#include <iterator.h>      
#include <vector>
 
void New_Korabl(Korpotomok *ship[10], Kletka *letka[10][10]);//Прототип
int shoting(Kletka *letka[10][10], Korpotomok *ship[10], int &xn, int &yn, int &kol_raneniy, int &a, int m);//Прототип
int cli_read_cordinats(int *value, const char *prompt);
 
int main() //Начало Мэин.
{
textbackground(BLACK);    //
textcolor(WHITE);       //
clrscr();
    const csdvX = 14, csdvY = 2;
for (int i = 1; i <= 10; i++) //Этот цикл для того, что бы выставить координаты сетки, для компьютера
{
gotoxy(3*csdvX + 3*i + 1, 2*csdvY + 1); cout<<i;//По горизонтали
gotoxy(3*csdvX + 1, 2*csdvY + 2*i + 1); cout<<i;//По вертикали
}
 
 
 
    Kletka * letka[10][10];//Предположительно тут происходит случайное заполнение
    for (int i = 0; i < 10; i++)//сеток в данном фрагменте идет заполнение клеток
    for (int j = 0; j < 10; j++) letka[i][j] = new Kletka(i+1, j+1);//компьютера//!!!!!!!!!!!!!!!!!!!!
    
    const msdvX = 1, msdvY = 2;
    for (int i = 1; i <= 10; i++)//Этот для вывода сетки игрока
    {
        gotoxy(3*msdvX + 3*i + 1, 2*msdvY + 1); cout<<i;//По горизонтали
        gotoxy(3*msdvX + 1, 2*msdvY + 2*i + 1); cout<<i;//По вертикали
    }
 
        Kletka * mkletka[10][10];//Клетки пользователя
        for ( int i = 0; i < 10; i++)
        for (int j = 0; j < 10; j++) mkletka[i][j] = new Kletka(i+1, j+1);
        randomize();//Думаю нах не надо
 
          Korpotomok *mship[10], *BaseKorabl[10];//Корабли юзера и компа
          New_Korabl(BaseKorabl, letka);//Передаем корабли компа
          New_Korabl(mship, mkletka);//Свои корабли
 
           int ckol = 10, cxn, cyn, cr = 0, ma, ca;//Координаты и кол-во кораблей компа
           int mkol = 10, px = 0, py= 0;//Наши корабли
           for (int i = 0; i < 10; i++) for (int j = 0; j < 10; j++)//Цикл отвечающий за прорисовку кораблей
           letka[i][j]->Prorisovka(csdvX, csdvY);//  компа
           for (int i = 0; i < 10; i++) for (int j = 0; j < 10; j++)//Прорисовка наших
          mkletka[i][j]->Prorisovka(msdvX, msdvY);// кораблей
 
 
            do
            {
              int sh;
              do
              { // Выстрел игрока
              window(53, 1, 80, 1);
               textbackground(BLACK);//
               clrscr();
              cout<<"The computer ships: "<<ckol;//Вот это не должно быть здесь
 
                window(53, 3, 80, 3);
                   textbackground(BLACK);
               clrscr();
                   cout<<"The player   ships: "<<mkol;
 
               if (!ckol) break;//Здесь происходит прекращение хода игрока.
               sh = shoting(letka, BaseKorabl, px, py, csdvX, csdvY, 1);
               for (int i = 0; i < 10; i++) for (int j = 0; j < 10; j++) letka[i][j]->Prorisovka(csdvX, csdvY);//Перемещение прицела происходит тут
               if (!sh) ckol--;
               if (sh == 2) break;//Если произошел промах, то игрок перестает ходить.
              } while (1);
                if (!ckol) break;
 
                do
                { // Выстрел компьютера. В принципе все то же самое.
                  window(53, 3, 80, 3);
                  textbackground(BLACK);
              clrscr();
                  cout<<"The player   ships: "<<mkol;
 
                  if (!mkol) break;
                  sh = shoting(mkletka, mship, cxn, cyn, cr, ca, 0);
                  for (int i = 0; i < 10; i++) for (int j = 0; j < 10; j++) mkletka[i][j]->Prorisovka(msdvX, msdvY);
                  if (!sh) mkol--;
                  if (sh == 2) break;
                  sleep(1);
                } while (1);
            } while (ckol == mkol);/
 
                window(18, 12, 62, 16);//Выводим Финальную Табличку
                textbackground(GREEN);
                clrscr();
                (mkol)? cout<<"WIN." : cout<<"LOSE.";
                getch();
                //delete letka;//Удаляем объекты.
              //    delete mkletka;
                return 0;
}//Конец мэйна.
 
 
/* Создает корабли и размещает их на поле */
void New_Korabl(Korpotomok *ship[10], Kletka *letka[10][10])
{
    for (int k = 0; k < 10; k++) //Цикл определяющий виды кораблей.
  {
    int Razmer, x, y, Polojenie, b;
    if (0 == k) Razmer = 4;//Размеры палуб кораблей, сначала инициализируем 4 палубник
    else if ((1 == k) || (2 == k)) Razmer = 3;//3 палубы
    else if ((3 <= k) && (5 >= k)) Razmer = 2;//2
    else Razmer = 1;//5 однопалубников
do
 {
   x = random(10) + 1; y = random(10) + 1; Polojenie = random(2); .
   int xm, ym; b = 0;
   if (Polojenie) {xm = x + Razmer; ym = y;} 
    else {xm = x; ym = y + Razmer;}
    for (int i = x; i <= xm; i++)
     {
    for (int j = y; j <= ym; j++)
     {
         if ((i > 10) || (j > 10)) {b = 1; break;}//Выход за пределы сетки поля
         if (!((i < 1) || (i > 10) || (j < 1) || (j > 10))) //Здесь происходит поиск места для корабля, 
        if (b = letka[i-1][j-1]->Pustaya_ili_net()) break; //
          }
     }
    if (b) break;
     }
 }
  while (b);
    ship[k] = new Korpotomok(Razmer, x, y, Polojenie);//Создается новый объект класса корабль, где в зависимости от палубы присваиваеются нач.кординаты
    ship[k]->Rasstanovka(letka);// и потом происходит его отрисовка
  }
 
      // for (int j = 0; j <= 9; j++) letka[j][j]->Korabl_v_kletku(0);/
      // return;//Не понятно для чего это!
}
 
 
 
        /* функция обстрела кораблей(матрица обетов поле,
        последнего выстрела, количество ранений)
        возвращает 0 - убит, 1 - ранен, 2 - мимо
        */
 
    int shoting(Kletka *letka[10][10], Korpotomok *ship[10], int &x, int &y, int &csdvX, int &csdvY, int m)
    {
        int xn, yn;
        if (m) // Выстрел игрока
        do
        { // пока не введено небитое поле
 
 
            window(3*(csdvX+x+1), 2*(csdvY+y+1), 3*(csdvX+x+1)+2, 2*(csdvY+y+1)+1);
            textbackground(WHITE);
            clrscr();
           csdvY=33;
           csdvX=33;
 
 
              int status = 0;
         window(1, 1, 35, 3);
         textbackground(RED);
         clrscr();
          do {
            status = cli_read_cordinats(&x, "Enter X value: ");
            if (status != 0) {
               //sleep(1000);
            clrscr();
            }
         } while (status != 0);
 
           //    clrscr();
             do {
                status = cli_read_cordinats(&y, "Enter Y value: ");
                if (status != 0) {
                sleep(1);
                clrscr();
                }
            } while (status != 0);
         clrscr();
 
              x--;
           y--;
               // cout << x << " " << y;
 
 
 
 
        xn = x; yn = y;
        if (!letka[x][y]->Vistrel_ili_net()) break;
          } while (1);//Конец 1ого ду
 
     switch (csdvX)
    { // Выстрел компьютера
        case 0:
         do
         { //корабль не был ранен
            x = random(10);
            y = random(10);
            if (!letka[x][y]->Vistrel_ili_net()) break;
         } while (1);
        break;
        case 1: // корабль был ранен один раз
        xn = x; yn = y;
        if ((x < 9) && (!letka[x+1][y]->Vistrel_ili_net())) {csdvY = 0; x++;}
        else if ((x > 0) && (!letka[x-1][y]->Vistrel_ili_net())) {csdvY = 1; x--;}
        else if ((y < 9) && (!letka[x][y+1]->Vistrel_ili_net())) {csdvY = 2; y++;}
        else if ((y > 0) && (!letka[x][y-1]->Vistrel_ili_net())) {csdvY = 3; y--;}
        break;
        default:
        xn = x; yn = y;
        switch (csdvY)
        { //коробль был ранен более одного раза
            case 0: if ((x < 9) && (!letka[x+1][y]->Vistrel_ili_net())) x++;
            else {x = x - csdvX; csdvY = 1;} break;
            case 1: if ((x > 0) && (!letka[x-1][y]->Vistrel_ili_net())) x--;
            else {x = x + csdvX; csdvY = 0;} break;
            case 2: if ((y < 9) && (!letka[x][y+1]->Vistrel_ili_net())) y++;
            else {y = y - csdvX; csdvY = 3;} break;
            case 3: if ((y > 0) && (!letka[x][y-1]->Vistrel_ili_net())) y--;
            else {y = y + csdvX; csdvY = 2;} break;
        }
    }
 
        letka[x][y]->Vistrel_v_kletku(1);
        for (int i = 0; i < 10; i++)
      if (ship[i]->Vistrel(x+1, y+1))//!!!!!
        {
          if (ship[i]->Ranenie())
         { // убит
           ship[i]->Rasstanovka(letka);
           ship[i]->Vistrel_v_kletkus(letka);
           csdvX = 0;
           window(18, 1, 35, 3);
           textbackground(BLACK);
           clrscr();
           if(m==1) {
           cout << "   KILL ";
           } else cout << "   DIE  ";
           sleep(1);
           clrscr();
           return 0;
         }
          else {
          letka[x][y]->Korabl_v_kletku(2);
          csdvX++;
          window(18, 1, 35, 3);
          textbackground(BLACK);
          clrscr();
          if (m == 1) {
          cout << "   RANEL  ";
          } else cout << "  VAS RANELI ";
          sleep(1);
          clrscr();
          return 1;
          } // ранен
        }
           if (csdvX) {x = xn; y = yn;}
           return 2; // мимо
    }
 
       //--------------------------Function wich check coordinats--------------------//
       int cli_read_cordinats(int *value, const char *prompt)
{
    size_t length = 0;
    char *end = NULL;
    char buf[CLI_BUFFER_SIZE] = "";
 
 
    assert(value);
    assert(prompt);
 
 
    printf("%s: ", prompt);
    fflush(stdout);
 
 
    if (!fgets(buf, sizeof(buf), stdin)) {
    return 1;
    }
 
 
    length = strlen(buf);
    if (buf[length - 1] == '\n') {
    buf[--length] = '\0';
 
 
    errno = 0;
       *value = strtod(buf, &end);
       if(*value < 0 || *value > 10)
       {
       fprintf(stderr, "Out of range cordinats! ");
      sleep(1);
       return 1;
       }
 
    if (length == 0) {
        fprintf(stderr, "Empty string!");
       sleep(1);
        return 1;
    }
    if (errno != 0 || *end != '\0') {
        fprintf(stderr, "The char was incorrect.");
        //fprintf(stderr, "\t%s\n" , buf);
        //fprintf(stderr, "\t%*c\n", (int)(end - buf) + 1, '^');
       sleep(1);
       return 1;
    }
    }
    else {
 
 
    scanf("%*[^\n]");
    scanf("%*c");
    fprintf(stderr, "Error! Need only 2 namber.", CLI_BUFFER_SIZE - 2);
     // clrscr();
    return 1;
    }
  //  clrscr();
    return 0;
}
 //////////////////----------------------------------------///////////////////////
Реализовано сначало в borland c++ 3/ потом переписано в borland c++ 5.02 Но обязательно нужна была поддержка dos.
Программа работает. Нужен совет как поступить в такой ситуации: программа написана и теперь вроде нужно куда то прилепить stl контейнеры и алгоритмы, я думал в векторе хранить координаты, но потом подумал что у меня получше, а именно координаты клеток и кораблей хранятся в массиве указателей и если я это буду переписывать все под вектор, мне кажется что это будет глупо из-за того, что выделено памяти будет больше чем при нынешней реализации, да и потом переписывать достаточно много.
Я решил использовать vector для хранения истории ходов, т.е. координат за партию, потом алгоритмом for each выводить эти координаты в консоли или в файл + к этому использовать random shufle куда нибудь прилепить.

Еще раз: вопрос в том логично ли переписать программу, заменив массив указателей на объекты, на контейнер из stl. Для себя я уже решил. Мне интересно как правильно должно быть.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
25.07.2015, 01:07
Ответы с готовыми решениями:

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

Есть у кого-нибудь исходник игры "Морской Бой"?
Ребят, может у кого завалялся исходник &quot;Морского Боя&quot;?

"Морской Бой": найти причины возникновения ошибок в коде
Доброго добра Всем тем, кто сейчас зашёл на эту страницу. Помогите понять, почему arr1 и arr2 в...

Написать алгоритмы реализации игры "Морской бой"
Здравствуйте. На форуме в первый раз, если что то куда то не туда написал, прошу не пинайте. Вот...

4
2655 / 1831 / 548
Регистрация: 05.06.2014
Сообщений: 5,297
25.07.2015, 02:23 2
Еще раз: вопрос в том логично ли переписать программу, заменив массив указателей на объекты, на контейнер из stl.
Логично, так как контейнер сам за собой динамическую память чистит. И вообще, классы надо активней использовать.
C++
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
//абстрактная клетка
class abstract_cell
{
public:
    virtual void shooting(int shoot_x,int shoot_y)=0;
};
 
//пустая клетка
class empty_cell:public abstract_cell
{
public:
    void shooting(int shoot_x,int shoot_y){cout<<"промазал!"<<endl;}
};
 
//подстреленная клетка
class already_used_cell:public abstract_cell
{
public:
    void shooting(int shoot_x,int shoot_y){cout<<"сюда уже стреляли!"<<endl;}
};
 
//клетка с кораблем
class ship:public abstract_cell
{
public:
    void shooting(int shoot_x,int shoot_y){cout<<"попали!"<<endl;}
};
 
empty_cell empty;
already_used_cell already_used;
const int width=10,height=10;
class game_field
{
public:
    game_field():field(width*height,&empty){}
    abstract_cell*&cell(int x,int y){return field[x+y*width];}
    void shooting(int x,int y){
        cell(x,y)->shooting(x,y);//стреляем по клетке
        cell(x,y)=&already_used;//отмечаем как уже использованную
    }
private:
    vector<abstract_cell*>field;
};
1
0 / 0 / 1
Регистрация: 28.03.2014
Сообщений: 15
25.07.2015, 11:51  [ТС] 3
Большое спасибо
0
Эксперт С++
3204 / 1731 / 435
Регистрация: 03.05.2010
Сообщений: 3,867
25.07.2015, 13:47 4
Ну, программа написана на таком примитивном Си, что первый вопрос - не ошиблись ли вы разделом? Может вам к сишникам? Но если вы говорите о контейнерах и алгоритмах, то наверно все же С++ имели в виду. Тогда выбросьте свою программу немедленно и пишите уже на С++. Кстати, указатели в С++ используются обычно только для полиморфного поведения, а массивы не используются вообще. Вместо них как раз контейнеры.
Клетку можно объявить как пару целых чисел. Корабль логично сделать классом. Позиция корабля задается парой клеток (его концами). В классе-корабле сделать функцию-член, принимающую координату выстрела и возвращающую его результат (убил, ранил, промазал).
Позицию игрока, то бишь эскадру, логично сделать вектором объектов кораблей. Убитый или раненый данным выстрелом корабль находить с помощью алгоритма std::find_if. Т.е. эскадру тоже можно сделать классом, который будет обрабатывать выстрел с помощью этого алгоритма.
Это сишная программа пишется в терминах чисел, указателей, битов и байтов. Программа на С++ - это модель решаемой задачи, поэтому и должна писаться в терминах этой задачи. Если у вас в задаче корабли и эскадры, то и в программе должны быть корабли и эскадры, а не какие-то занюханные указатели.
0
Эксперт С++
8164 / 3766 / 809
Регистрация: 15.11.2014
Сообщений: 8,549
25.07.2015, 14:02 5
тему не читал.

STL-контейнеры лучше
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.07.2015, 14:02

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Найти и исправить ошибки (игра "Морской бой")
Ребят. На с++ пишу недавно. Решил сделать простенькую игру: &quot;Морской бой&quot;. Игра будет происходит...

Проблемы с реализацией игры "Морской бой": найти и исправить ошибки в коде
Доброго времени суток. У меня вопрос по игре &quot;Морской бой&quot;. Я вывел поле с написанными координатами...

Как реализовать AI в игре "Морской бой"
Подскажите пожалуйста как лучше реализовать умную игру компьютера

Нужно узнать алгоритм в "морской бой"
Мне нужно понять алгаритм хода ИИ и его расстановки кораблей , может кто-нибудь помочь


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.