11 / 11 / 0
Регистрация: 16.02.2011
Сообщений: 17
1

Морской бой. Ф-ция автоматической рассатновки кораблей.

21.02.2011, 17:58. Показов 12989. Ответов 3
Метки нет (Все метки)

Добрый день, ув. форумчане! Есть задание написать консольный морской бой. Есть задача расстановки кораблей компьютера случайным образом. Массив [10][10], заполненный '0' - игровое поле. 'X' - корабль.
В ф-ции расстановки кораблей перед заполнением 'Х' идет проверка на наличие кораблей в случайно выбранном элементе и вокруг него(чтобы корабли не соприкасались). Мною написана ф-ция:
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
void AutoSet(char field[10][10], int  m, int n)
{
    //Расстановка однопалубных кораблей
    srand(time(NULL));
    for(int i=0; i<4; i++){
        m=rand()%10;
        n=rand()%10;
        while (field[m][n]=='X' || field[m][n+1]=='X' || field[m][n-1]=='X' || field[m+1][n]=='X' || field[m-1][n]=='X'
            || field[m+1][n+1]=='X' || field[m+1][n-1]=='X' || field[m-1][n+1]=='X' || field[m-1][n-1]=='X'){
            m=rand()%10;
            n=rand()%10;
        }
        field[m][n]='X';
    }
 
    //Расстановка двохпалубных кораблей
    for(int i=0; i<3; i++){
        int k=rand()%2;
        switch(k){
        case 0://вертикальное расположение корабля
            m=rand()%9;
            n=rand()%10;
            while(field[m][n]=='X' || field[m-1][n-1]=='X' || field[m-1][n]=='X' || field[m-1][n+1]=='X' ||
                  field[m][n-1]=='X' || field[m][n+1]=='X' || field[m+1][n-1]=='X' || field[m+1][n]=='X' ||
                  field[m+1][n+1]=='X' || field[m+2][n-1]=='X' || field[m+2][n]=='X' || field[m+2][n+1]=='X'){
                  m=rand()%9;
                  n=rand()%10;
            }
            field[m][n]='X';
            field[m+1][n]='X';
            break;
        case 1://горизонтальное расположение корабля
            m=rand()%10;
            n=rand()%9;
            while(field[m][n]=='X' || field[m][n+1]=='X' || field[m-1][n-1]=='X' || field[m-1][n]=='X' ||
                field[m-1][n+1]=='X' || field[m-1][n+2]=='X' || field[m][n-1]=='X' || field[m][n+2]=='X' ||
                field[m+1][n-1]=='X' || field[m+1][n]=='X' || field[m+1][n+1]=='X' || field[m+1][n+2]=='X'){
                m=rand()%10;
                n=rand()%9;
            }
            field[m][n]='X';
            field[m][n+1]='X';
            break;
        }   
    }
 
    //Расстановка трехпалубных кораблей
    for (int i=0; i<2; i++){
        int n=rand()%2;
        switch(n){
        case 0://вертикальное положение корабля
            m=rand()%8;
            n=rand()%10;
            while(field[m][n]=='X' || field[m+1][n]=='X' || field[m+2][n]=='X' || field[m-1][n-1]=='X' ||
                field[m-1][n]=='X' || field[m-1][n+1]=='X' || field[m][n-1]=='X' || field[m][n+1]=='X' ||
                field[m+1][n-1]=='X' || field[m+1][n+1]=='X' || field[m+2][n-1]=='X' || field[m+2][n+1]=='X' ||
                field[m+3][n-1]=='X' || field[m+3][n]=='X' || field[m+3][n+1]=='X'){
                m=rand()%8;
                n=rand()%10;
            }
            field[m][n]='X';
            field[m+1][n]='X';
            field[m+2][n]='X';
            break;
        case 1:
            m=rand()%10;
            n=rand()%8;
            while(field[m][n]=='X' || field[m][n+1]=='X' || field[m][n+2]=='X' || field[m-1][n-1]=='X' ||
                field[m-1][n]=='X' || field[m-1][n+1]=='X' || field[m-1][n+2]=='X' || field[m-1][n+3]=='X' ||
                field[m][n-1]=='X' || field[m][n+3]=='X' || field[m+1][n-1]=='X' || field[m+1][n]=='X' ||
                field[m+1][n+1]=='X' || field[m+1][n+2]=='X' || field[m+1][n+3]=='X'){
                m=rand()%10;
                n=rand()%8;
            }
            field[m][n]='X';
            field[m][n+1]='X';
            field[m][n+2]='X';
            break;
        }//switch
    }//for
 
    //Расстановка четырехпалубного корабля
    int l=rand()%2;
    switch(l){
    case 0://вертикальное положение
        m=rand()%7;
        n=rand()%10;
        while(field[m][n]=='X' || field[m+1][n]=='X' || field[m+2][n]=='X' || field[m+3][n]=='X' ||
            field[m-1][n-1]=='X' || field[m-1][n]=='X' || field[m-1][n+1]=='X' || field[m][n-1]=='X' ||
            field[m][n+1]=='X' || field[m+1][n-1]=='X' || field[m+1][n+1]=='X' || field[m+2][n-1]=='X' ||
            field[m+2][n+1]=='X' || field[m+3][n-1]=='X' || field[m+3][n+1]=='X' || field[m+4][n-1]=='X' ||
            field[m+4][n]=='X' || field[m+4][n+1]=='X'){
            m=rand()%7;
            n=rand()%10;
        }
        field[m][n]='X';
        field[m+1][n]='X';
        field[m+2][n]='X';
        field[m+3][n]='X';
        break;
    case 1://горизонтальное положение
        m=rand()%10;
        n=rand()%7;
        while(field[m][n]=='X' || field[m][n+1]=='X' || field[m][n+2]=='X' || field[m][n+3]=='X' ||
            field[m-1][n-1]=='X' || field[m-1][n]=='X' || field[m-1][n+1]=='X' || field[m-1][n+2]=='X' ||
            field[m-1][n+3]=='X' || field[m-1][n+4]=='X' || field[m][n-1]=='X' || field[m][n+4]=='X' ||
            field[m+1][n-1]=='X' || field[m+1][n]=='X' || field[m+1][n+1]=='X' || field[m+1][n+2]=='X' ||
            field[m+1][n+3]=='X' || field[m+1][n+4]=='X'){
            m=rand()%10;
            n=rand()%7;
        }
        field[m][n]='X';
        field[m][n+1]='X';
        field[m][n+2]='X';
        field[m][n+3]='X';
        break;
    }//switch
}
Проблема в расстановке четырехпалубного корабля - иногда консоль появляеться пустой(я так понял безконечный цыкл появляется) и ничего не происходит. Проблема сугубо в коде расстановки четырехпалубного корабля, без него все работает на ура.
Вот код программы, выводящей заполненное поле на экран:
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
#include<iostream>
#include<time.h>
#include<stdlib.h>
using namespace std;
 
void AutoSet(char field[10][10], int m, int n);
 
void main()
{
    setlocale(LC_ALL, "rus");
    const int m=10, n=10;
    char pfield[m][n], efield[m][n], nazv[m]={'A','B','C','D','E','F','G','H','I','J'};
    
    for (int i=0; i<m; i++)     //Заполнение
        for(int j=0; j<n; j++)  //поля игрока
            pfield[i][j]=0;     //нолями
    for (int i=0; i<m; i++)     //Заполнение
        for(int j=0; j<n; j++)  //поля компьютера
            efield[i][j]='0';   //нолями
    
    AutoSet(efield,m,n);
    cout<<"   ";
    for (int i=0; i<10; i++)
        cout<<nazv[i]<<" ";
    cout<<"\n";
    for (int i=0; i<10; i++)
        cout<<" ";
    cout<<"\n";
    for (int i=0; i<m; i++){    
        if (i== 9)
            cout<<(i+1)<<" ";
        else
        cout<<(i+1)<<"  ";
        for(int j=0; j<n; j++){
            cout<<efield[i][j]<<" ";
        }
        cout<<"\n";
    }
    
}
Просьба к коллегам - посмотрите свежей головой где я начудил, а то уже мозги кипят. Проблема 99% что в расстановке четырехпалубного корабля. Заранее благодарен.
1
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.02.2011, 17:58
Ответы с готовыми решениями:

Расстановка кораблей (морской бой)
Доброго времени суток, при расстановке 2х палубных кораблей возникает проблема... При выборе точки...

Консольный морской бой. Расстановка кораблей
Добрый вечер, уважаемые форумчане. Хочу написать консольный морской бой. Начал с функции...

Проверить правильность расстановки кораблей. Морской бой
Есть матрица NxM, где расставлены корабли. Корабли не стоят на краю матрицы, кол-во 4-х клеточных...

Морской бой - программа зацикливается на расстановке кораблей
Нужно написать курсовую(игру). Решила написать морской бой(пока что консольно). Написала программу...

3
Эксперт С++
3220 / 1747 / 435
Регистрация: 03.05.2010
Сообщений: 3,867
22.02.2011, 01:06 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
/////////////////////////////////////////////////////////////////////////////////////////
//Есть задача расстановки кораблей компьютера случайным образом. Массив [10][10], 
//заполненный '0' - игровое поле. 'X' - корабль.
//В ф-ции расстановки кораблей перед заполнением 'Х' идет проверка на наличие кораблей 
//в случайно выбранном элементе и вокруг него(чтобы корабли не соприкасались). 
/////////////////////////////////////////////////////////////////////////////////////////
#include <algorithm>
#include <ctime>
#include <iostream>
#include <cstdlib>
/////////////////////////////////////////////////////////////////////////////////////////
const int  FIELD_DIM   = 10;
const char WATER_SYMB  = ' ';
const char SHIP_SYMB   = 'X';
/////////////////////////////////////////////////////////////////////////////////////////
bool  ship_is_good
    (
        int         size, 
        bool        is_horiz, 
        int         row_top, 
        int         col_left, 
        const char  field[][FIELD_DIM]
    )
{
    if(is_horiz)
    {
        for(int i =   std::max(0,              row_top - 1); 
                i <=  std::min(FIELD_DIM - 1,  row_top + 1); 
                ++i)
        {
            for(int j =   std::max(0,              col_left - 1); 
                    j <=  std::min(FIELD_DIM - 1,  col_left + size); 
                    ++j)
            {
                if(field[i][j] == SHIP_SYMB) return false;
            }        
        }
        return  true;
    }
    else//вертикальный
    {
        for(int i =   std::max(0,             row_top - 1); 
                i <=  std::min(FIELD_DIM - 1, row_top + size); 
                ++i)
        {
            for(int j =   std::max(0,             col_left - 1); 
                    j <=  std::min(FIELD_DIM - 1, col_left + 1); 
                    ++j)
            {
                if(field[i][j] == SHIP_SYMB) return false;
            }        
        }
        return  true;
    }
}
/////////////////////////////////////////////////////////////////////////////////////////
void  set_ship_with_size(int  size, char  field[][FIELD_DIM])
{
    bool  is_horiz  = rand() % 2 == 0;
    int   row_top   = 0;
    int   col_left  = 0;
 
    do
    {
        do
        {
            row_top = rand() % FIELD_DIM;
        }while(   !is_horiz 
               && row_top > FIELD_DIM - size);
 
        do
        {
            col_left = rand() % FIELD_DIM;
        }while(   is_horiz 
               && col_left > FIELD_DIM - size);        
    }while(!ship_is_good(size, is_horiz, row_top, col_left, field)); 
 
    if(is_horiz)
    {
        for(int j = col_left; j < col_left + size; ++j)
        {
            field[row_top][j] = SHIP_SYMB;
        }
    }
    else//вертикальный
    {
        for(int i = row_top; i < row_top + size; ++i)
        {
            field[i][col_left] = SHIP_SYMB;
        }    
    }
}
/////////////////////////////////////////////////////////////////////////////////////////
void  set_ships(char  field[][FIELD_DIM])
{
    for(int i = 0; i < 1; ++i)
    {
        set_ship_with_size(4, field);
    }
 
    for(int i = 0; i < 2; ++i)
    {
        set_ship_with_size(3, field);
    }
 
    for(int i = 0; i < 3; ++i)
    {
        set_ship_with_size(2, field);
    }
 
    for(int i = 0; i < 4; ++i)
    {
        set_ship_with_size(1, field);
    }
}
/////////////////////////////////////////////////////////////////////////////////////////
void  print_field(const char  field[][FIELD_DIM])
{
    for(int  i = 0; i < FIELD_DIM; ++i)
    {
        for(int  j = 0; j < FIELD_DIM; ++j)
        {
            std::cout << field[i][j]
                      << ' ';
        }    
        std::cout << std::endl;
    }
}
/////////////////////////////////////////////////////////////////////////////////////////
void  set_water(char  field[][FIELD_DIM])
{
    for(int  i = 0; i < FIELD_DIM; ++i)
    {
        for(int  j = 0; j < FIELD_DIM; ++j)
        {
            field[i][j] = WATER_SYMB;
        }            
    }
}
/////////////////////////////////////////////////////////////////////////////////////////
int main()
{
    srand(static_cast<unsigned>(time(0)));
    
    char  field[FIELD_DIM][FIELD_DIM];  
    set_water    (field);
    set_ships    (field);
    print_field  (field);
}
1
11 / 11 / 0
Регистрация: 16.02.2011
Сообщений: 17
26.02.2011, 19:09  [ТС] 3
Mr.X, действительно ваш вариант реализации намного проще и компактней чем моя лабуда) Спасибо. Но позвольте еще поинтересоваться, что делает след. кусок кода:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(is_horiz)
    {
        for(int i =   std::max(0,              row_top - 1); 
                i <=  std::min(FIELD_DIM - 1,  row_top + 1); 
                ++i)
        {
            for(int j =   std::max(0,              col_left - 1); 
                    j <=  std::min(FIELD_DIM - 1,  col_left + size); 
                    ++j)
            {
                if(field[i][j] == SHIP_SYMB) return false;
            }        
        }
        return  true;
а именно
std::max(0, row_top - 1)
std::min(FIELD_DIM - 1, row_top + 1)
Находит мин и макс значение в диапазоне (а, b)? И если да, то какая библиотека за это отвечает. Еще раз спасибо.

Добавлено через 57 минут
И можно ли реализовать цыкл без min/max?

Добавлено через 3 часа 40 минут
Разобрался, переделал и доделал) Спасибо Mr.X, за помощь! Тему можно закрывать.
0
1 / 1 / 0
Регистрация: 12.12.2010
Сообщений: 49
23.04.2011, 11:58 4
Можт я не совсем вовремя и не в тему, прост я щас тоже пишу морской бой...в твоем первоначальном коде была небольшая "недодумка")) над было сначало 4х палубник поставить, потом3х ну и т.д.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.04.2011, 11:58
Помогаю со студенческими работами здесь

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

Морской бой: расставляется кораблей больше, чем положено
Здравствуйте! Пишу игру &quot;Морской бой&quot; в консоли, и попалась одна неприятная ситуация. Есть функция...

Создать класс, реализующий хранилище кораблей для игрока в «Морской бой»
Всем привет. Это задача по теме контейнерные классы. Не бейте только за глупый вопрос. Но в данной...

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


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru