Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Рациональный подход / 16 сообщений из 16, страница 1 из 1
26.04.2005, 20:52
    #33037065
Stalcer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
Пишу игру SeaWar. Как упростить вот такую вот проверку (проверяет все клетки вокруг однопалубного корабля, ищет совпадения по всему полю)? Нужен рациональный подход. Представь, что получится, если я стану проверять таким макаром четырех палубник :-)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
for(int row= 0 ; row< 10 ; row++){ 
        for(int cell= 0 ; cell< 10 ; cell++){ 
            if((str[row][cell]==ship)&& 
            (str[row+ 1 ][cell] !=ship)&& 
            (str[row- 1 ][cell+ 1 ] != ship)&& 
            (str[row+ 1 ][cell+ 1 ] != ship)&& 
            (str[row- 1 ][cell- 1 ] != ship)&& 
            (str[row][cell- 1 ] != ship)&& 
            (str[row+ 1 ][cell- 1 ] != ship)&& 
            (str[row][cell+ 1 ] != ship)&& 
            (str[row- 1 ][cell] != ship)){ 
                if(j!= 4 ){ 
                 one++; 
                 j++; 
                } 
            }         
        }     
    }
...
Рейтинг: 0 / 0
26.04.2005, 20:57
    #33037069
Анатолий Широков
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
Так проверяй не на ship, а на ship1, то есть измени классификацию ячейки. Введи ship1, ship2, ship3, ship4 и будет счастье.
...
Рейтинг: 0 / 0
26.04.2005, 21:07
    #33037081
Stalcer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
Анатолий ШироковТак проверяй не на ship, а на ship1, то есть измени классификацию ячейки. Введи ship1, ship2, ship3, ship4 и будет счастье.
Я только начинаю программировать, мне иногда трудно понять некоторые моменты. Будь добр разъясни на примере . Что значит классификация ячейки?
У меня корабли расставляются случайно, мне нужно проверять, чтоб не получилась "куча".
...
Рейтинг: 0 / 0
27.04.2005, 11:15
    #33037674
redskin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
Stalcer Анатолий ШироковТак проверяй не на ship, а на ship1, то есть измени классификацию ячейки. Введи ship1, ship2, ship3, ship4 и будет счастье.
Я только начинаю программировать, мне иногда трудно понять некоторые моменты. Будь добр разъясни на примере . Что значит классификация ячейки?
У меня корабли расставляются случайно, мне нужно проверять, чтоб не получилась "куча".

Проверку на наличие однопалубных кораблей можно сделать примерно так:
(это только идея, набросок, код сырой, так что ногами не пинать :))

Код: plaintext
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.
int str[ 10 ][ 10 ];
const int ship =  1 ;
const int empty =  0 ;

bool check_1(int i, int j)
{
	bool bResult = true;
	if(str[i][j] == ship)
	{
		for(int dx = i - 1 ; dx <= (i +  1 ); dx++)
			if((dx >  0 ) &&  (dx <  10 ) && (dx != i))
				for(int dy = j - 1 ; dy <= (j +  1 ); dy++)
					if((dy >  0 ) &&  (dy <  10 ) && (dy != j))
						if(str[dx][dy] != empty)
							bResult = false;
			
	}
	else 
		bResult = false;

	return bResult;
}

int main( int argc, char *argv[] )
{
	for(int i =  0 ; i <  10 ; i++)
		for(int j =  0 ; j <  10 ; j++)
			str[i][j] = empty;

	str[ 1 ][ 1 ] = ship;
	str[ 1 ][ 5 ] = ship;
	str[ 4 ][ 8 ] = ship;
	str[ 9 ][ 2 ] = ship;

	for(int i =  0 ; i <  10 ; i++)
		for(int j =  0 ; j <  10 ; j++)
			if(check_1(i, j))
				cout << i << " " << j << endl;
			
	return  0 ;
}

Алгоритм можно докрутить для 1,2 и более палубных кораблей. Когда сам писал морской бой. то делал примерно так.
...
Рейтинг: 0 / 0
27.04.2005, 13:08
    #33038025
Stalcer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
Спасибо, сейчас буду разбираться :-)
...
Рейтинг: 0 / 0
27.04.2005, 14:08
    #33038248
Stalcer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
Я либо чего-то не понял, но ф-ция у меня не работает :-( (иногда лепит два корабля вместе).
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
	int t, res;//t-кол-во кораблей, res - кол-во совпадений
	do{	
		res= 0 ;
		t= 0 ;
		Map(str);	//отчистка поля
		for(int i= 0 ; i< 10 ; i++){
			for(int j= 0 ; j< 10 ; j++){
				if(str[i][j]!=ship){
					t++;
					if(t<= 4 ){
						AutoShip(str,  1 );	//случайное построение 1 труб. корабля
					}				
				}
				if(check_1(i, j)){
				  res++;
				}
			}
		}		
	}while(res!= 4 );
Покажи, плз., как переделать ф-цию для кораблей >1 палубы .
...
Рейтинг: 0 / 0
27.04.2005, 14:27
    #33038323
redskin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
StalcerЯ либо чего-то не понял, но ф-ция у меня не работает :-( (иногда лепит два корабля вместе).
Покажи, плз., как переделать ф-цию для кораблей >1 палубы .

1) в моем коде есть небольшая ошибка, вместо ((dx > 0) надо поставить ((dx >= 0), для dy соответственно.

2) все, что делает эта функция, проверяет - есть ли в данной клетке однопалубный корабль - т.е. клетка заполнена, и вокруг нее нет других заполненных клеток. Эту функцию можно использовать, например, для поиска всех кораблей (что у меня и приведено в тесте). Но это не готовое решение для твоего случая, я же честно принался, что это только набросок :)

Алгоритм поиска кораблей длины (n) - пройтись по полю и для каждой точки определить является ли она началом корбаля длины n - т.е. надо проверить отрезок - (по горизонтали или по вертикали) размером n клеток.

Алгоритм поиска свободного места для установки корабля размером n - пройтись по полю и для клетки определить может ли она быть началом корабля размером n, т.е. проверить есть ли слева (внизу) от нее свободная линия, плюс свободная граница вокруг нее размером в 1 клетку (чтобы корабли не склеиваились).

Мне кажется ничего сложного... 2-3 цикла, плюс столько же проверок :-\

3) не знаю как рабоатет AutoShip, но подозреваю в чем глюк и почему корабли лепятся вместе - ты же сначала ставишь корабль в клетку, и только потом проверяешь стоило ли это делать :)

4) если нужен готовый код, то могу и написать, но только поздно вечером из дома, ибо сейчас на работе и так есть чем заняться
...
Рейтинг: 0 / 0
27.04.2005, 15:12
    #33038506
Stalcer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
Спасибо за активную помощь.
AutoShip случайно выбирает координаты (ориент., если >1) и ставит корабль.
Я ставлю 4 корабля и проверяю если все четыре вокруг себя не имеют кораблей, значит можно показать на экран...
Если тебя это не сильно затруднит и будет время, помоги студенту с проверкой на корабли >1 плз.. :-)
...
Рейтинг: 0 / 0
27.04.2005, 15:13
    #33038510
Stalcer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
после исправлений все равно лепит :-)
...
Рейтинг: 0 / 0
27.04.2005, 16:12
    #33038709
Анатолий Широков
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
Как я уже говорил, у тебя плохая классификация ячеек. После постановки очередного корабля на игоровое поле, помимо установки признака "корабль" той ячейке, в который он установлен необходимо так же как-то "метить" окружающие корабль ячейки, которые уже не могут содержать другие корабли. Что это означает:

Например, мы случайным образом установили, что однопалубный корабль имеет координаты (2, 2). Так вот, после постановки корабля на игровое поле мы метим не только ячейку (2,2) (пусть 2), но и все 8-связные с ней ячейки (пусть 1). 0 отметим не занятые ячейки:

11100000
12100000
11100000
00000000

Теперь вернемся к твоей задаче, которая состоит в том, чтобы разместить n-палубный корабль. Что есть n-палубный корабль (пусть пока горизонтально ориентированный) - это прямоугольник (x-1, y-1) - (x + n, y + 1). Поэтому, чтобы определить можно ли разместить n-палубный корабль в точку (x, y) достаточно подсчитать сумму ячеек покрываемую этим прямоугольником и если она будет равна нулю, то (x,y) и есть искомая точка:

Код: plaintext
1.
2.
3.
4.
5.
6.
int sum =  0 ;
for(size_t r = y- 1 ; i <= y+ 1  )
   for(size_t c = x- 1 ; i <= x+n )
      sum += map[r][c];
if( sum ==  0 )
    // в позицию (x, y) можно установить n палубный корабль

Неприятность составляет проверка на граничные условия, но их можно легко избежать, если увеличить размерность игрового поля N на 2 - то есть по 1 с каждой стороны. В этом случае координаты игрового поля будут в точности принадлежать множеству [1, N] x [1, N].

Вот и все идеи. Теперь ты легко все реализуешь. Удачи.
...
Рейтинг: 0 / 0
27.04.2005, 16:44
    #33038797
Stalcer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
Ответ разумный, конечно, за что и спасибо. Принцип понял, а вот синтаксис мне пока тяжело понять :-)
Приведи пример плз., если мне нужно поставить 3 двух трубных корабля, в случайные координаты x и y, поле 10x10.
...
Рейтинг: 0 / 0
27.04.2005, 17:30
    #33038942
Анатолий Широков
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
2 Stalcer

Извини, но пример ты как-нибудь сам.
...
Рейтинг: 0 / 0
27.04.2005, 22:28
    #33039433
Stalcer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
Что такое size_t?
...
Рейтинг: 0 / 0
28.04.2005, 01:00
    #33039541
redskin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
Stalcer...
Я ставлю 4 корабля и проверяю если все четыре вокруг себя не имеют кораблей, значит можно показать на экран...
Если тебя это не сильно затруднит и будет время, помоги студенту с проверкой на корабли >1 плз.. :-)

Меня то не затруднит, только сдавать ДЗ тебе все равно самому придецца :)

Код: plaintext
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.
#include <iostream>
#include <time.h>

const int N =  10 ;   // размер поля 
const int H =  4 ;    // макс. размер корабля
int str[N][N];      // игровое поле поле

#define RAND10 rand()/(RAND_MAX /  10 )
#define RAND2 rand()/(RAND_MAX /  2 )

// проверка свободна ли клетка и свободно ли пространство вокруг нее
bool Check(int x, int y)
{
	for(int i = x- 1 ; i <= (x+ 1 ); i++)
		for(int j = y- 1 ; j <= (y+ 1 ); j++)
			if((i >=  0 ) && (j >=  0 ) && (i < N) && (j < N))
				if (str[i][j] !=  0 ) 
					return false;
	return true;
}

// проверка доступности линии
// параметры:
// x, y  координаты верхнего левого угла
// L     длина линии 
// Dir   направление 
bool CheckLine(int x, int y, int L, int Dir /* 0 - горизонтальное, 1 - вертикальное*/)
{
	int dx = Dir ?  0  :  1 ;
	int dy = Dir ?  1  :  0 ;
	int x1 = x + L*dx;
	int y1 = y + L*dy;

	bool r = false;
	if( (x >=  0 ) && (y >=  0 ) && (x < N) && (y < N) && (x1 < N) && (y1 < N) )
	{
		r = true;
		for(int i =  0 ; i < L; i++)
			r = Check(x + i*dx, y + i*dy) && r;
	}
	return r;
}

// установка корабля
// x, y  координаты верхнего левого угла
// L     длина линии (кол-во палуб корабля)
// Dir   направление 
// возвращает true, если удалось поставить корабль, иначе false
bool SetLine(int x, int y, int L, int Dir)
{
	int dx = Dir ?  0  :  1 ;
	int dy = Dir ?  1  :  0 ;
	bool r = false;
	if(CheckLine(x, y, L, Dir))
	{
		for(int i =  0 ; i < L; i++)
			str[x + i*dx][y + i*dy] =  1 ;		 
		r = true;
	}
	return r;
}

// иницализаця игрового поля
// заполенение поля стандартным набором кораблей 
// 1 4хпалубный, 2 3хпалубных, 3 2хпалобных, 4 однопалубных
// вывод заполненного поля на экран
int main(int argc, char* argv[])
{
	srand(time( 0 ));

	for(int i =  0  ; i < N; i++)
		for(int j =  0 ; j < N; j++)
			str[i][j] =  0 ;

	for(int k = H; k >  0 ; k--)
		for(int i =  0 ; i < (H-k+ 1 ); i++)
			while(!SetLine(RAND10, RAND10, k, RAND2)) 0 ;

	for(int i =  0  ; i < N; i++)
	{
		for(int j =  0 ; j < N; j++)
			std::cout << str[i][j] << " ";
		std::cout << std::endl;
	}

	return  0 ;
}


Вот, примерно так.
Остальное сам :))
...
Рейтинг: 0 / 0
28.04.2005, 15:29
    #33040772
Stalcer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
Спасибки!!!
Сейчас попробуем поюзать :-)
...
Рейтинг: 0 / 0
28.04.2005, 15:32
    #33040785
Stalcer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Рациональный подход
Супер!, есть же добрые люди то!
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Рациональный подход / 16 сообщений из 16, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]