Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Проверка расстановки кораблей в Морском бое
 
 автор: pazha   (24.07.2012 в 18:16)   письмо автору
 
 

Здравствуйте, уважаемые пользователи форума! Пишу игру "Морской бой", и у меня такой вопрос.

У меня есть двумерный массив состоящий из 0 и 1, где 0 - пустая ячейка, 1 - кораблик (или его часть). Мне необходимо реализовать проверку на PHP которая выявит хорошо ли расставлены корабли или нет по следующим критерием:
1. По количеству кораблей всего: 4 - однопалубных, 3 - двухпалубных, 2 - трёхпалубных, 1 - четырёх палубные.
2. Корабли могут находится только в вертикальном либо горизонтальном положении.
3. Корабли не должны соприкасаться друг с другом.

Я без проблемно реализовал что бы считало количество однопалубных кораблей и к ним все эти проверки выполнялись. Но не могу понять как мне обойти этот массив что бы выяснить про остальные корабли данные. Помогите пожалуйста, я в этом новичек.

  Ответить  
 
 автор: Valick   (25.07.2012 в 00:36)   письмо автору
 
   для: pazha   (24.07.2012 в 18:16)
 

0 - пустая ячейка
1 - кораблик
2 - раненый кораблик
3 - убитый кораблик
4 - недоступная ячейка

  Ответить  
 
 автор: Zezst   (25.07.2012 в 01:13)   письмо автору
 
   для: pazha   (24.07.2012 в 18:16)
 

Осмелюсь предположить, что потому же принципу вы могли бы сделать и для остальных кораблей.
нашли палубу -> однопалубник?
    нет? -> ишем вторую палубу
           нашли? -> ишем третью
                нашли? -> нет
                        значит двухпалубник

Ха! Еще как вариант:
Использовать битовые операции
2 бита говорят о том какой это корабль:
00 – однопалубник
01 – двухпалубник
10 – трехпалубник
11 – четырехпалубник
1 бит указывает на ранение
Еще 2 бита говорят в каком направлении искать оставшиеся палубы
Итого всего пять бит, осталось еще три бита
1 бит говорит пустая ячейка или нет
1 бит говорит был сюда выстрел или нет
Еще бит куда то можно использовать.
А проверку делать , что б тормозить поменьше, по маске.
УПС. на направление придется использовать 3 бита, а вот бит про ранение можно совместить с битом "стреляли или нет". И последний бит говорит "убит или нет".

  Ответить  
 
 автор: Zezst   (25.07.2012 в 02:15)   письмо автору
 
   для: Zezst   (25.07.2012 в 01:13)
 

$b = 2; // 01-двупалубный
$a = 80; // 001-пусть будет направо
         // 0-не ранен(соответсвенно сюда не пуляли)
         // 1-не пусто
         // 0-не убит
$ba = $b + $a;
$korabl = 3; // 11 000000 - для того что бы выделить биты отвечаюшие за какой корабль
$pusto = 64; // 000000 1 00 - для проверки пусто или нет

if($ba //взяли ячейку
    & $pusto) //выделили бит отвечающий за пусто
{ // если не пусто
    $k = $ba // снова взяли ячейку
    & $korabl; // выделили биты отвечающие за корабль
    if($k === 0)
        echo "одна палуба";
    if($k === 2)
        echo "две палубы";
    if($k === 1)
        echo "три палубы";
    if($k === 3)
        echo "четыре палубы";
}

  Ответить  
 
 автор: pazha   (25.07.2012 в 07:54)   письмо автору
 
   для: Zezst   (25.07.2012 в 02:15)
 

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

Таким образом мы проверили на то что бы кораблики были только по вертикали и горизонтале а так же что бы не были слипшиеся два корабля.

  Ответить  
 
 автор: pazha   (25.07.2012 в 08:07)   письмо автору
 
   для: pazha   (25.07.2012 в 07:54)
 

Всем спасибо. Успешно реализовал всё что хотел. Вот код, может кому понадобиться:

class NavalBattle {
    
    # Метод: проверка правильности расстановки кораблей.
    # Принимает: игровое поле в виде двумерного массива.
    # Возвращает: true либо номер ошибки.
    public static function CheckPlacement( &$aField ) {
        
        # Проверка количества строк :
        if( count( $aField ) != 10 )
            return -1;

        # Счетчик кораблей на поле :
        $iShipCounter = 0;
        $iSingleDeckCounter = 0;
        $iDoubleDeckCounter = 0;
        $iThreeDeckCounter = 0;
        $iFourDeckCounter = 0;

        # Перебор по строкам :
        for( $iY = 0; $iY < 10; $iY++ ) {

            # Проверка количества столбцов :
            if( count( $aField[$iY] ) != 10 )
                return -2;

            # Подсчет количества кораблей по палубно :
            $sTmp = str_replace( array( '[', ']' ), array( '0,', ',0' ), json_encode( $aField[$iY] ) );
            $iDoubleDeckCounter += substr_count( $sTmp, '0,1,1,0' );
            $iThreeDeckCounter += substr_count( $sTmp, '0,1,1,1,0' );
            $iFourDeckCounter += substr_count( $sTmp, '0,1,1,1,1,0' );

            # Перебор по столбцам :
            for( $iX = 0; $iX < 10; $iX++ ) {
                
                # Фильтрация значения ячейки :
                $aField[$iY][$iX] = intval( $aField[$iY][$iX] );

                # Проверка значения ячейки :
                if( $aField[$iY][$iX] != 0 && $aField[$iY][$iX] != 1 )
                    return -3;

                # Если это корабль :
                if( $aField[$iY][$iX] == 1 ) {
                    
                    # Проверяем что бы угловые ячейки содержали 0 :
                    if( (isset( $aField[$iY-1] ) && isset( $aField[$iY-1][$iX-1] ) && $aField[$iY-1][$iX-1] != 0) || (isset( $aField[$iY-1] ) && isset( $aField[$iY-1][$iX+1] ) && $aField[$iY-1][$iX+1] != 0) || (isset( $aField[$iY+1] ) && isset( $aField[$iY+1][$iX-1] ) && $aField[$iY+1][$iX-1] != 0) || (isset( $aField[$iY+1] ) && isset( $aField[$iY+1][$iX+1] ) && $aField[$iY+1][$iX+1] != 0) )
                        return -4;
                    
                    # Проверяем, однопалубный ли это корабль :
                    if( (!isset( $aField[$iY-1] ) || $aField[$iY-1][$iX] == 0) && (!isset( $aField[$iY+1] ) || $aField[$iY+1][$iX] == 0) && (!isset( $aField[$iY][$iX-1] ) || $aField[$iY][$iX-1] == 0) && (!isset( $aField[$iY][$iX+1] ) || $aField[$iY][$iX+1] == 0) )
                        $iSingleDeckCounter++;
                        
                    # Увеличиваем счетчик палуб кораблей :
                    $iShipCounter++;
                }
            }
        }

        # Проверка количества палуб на поле :
        if( $iShipCounter != 20 )
            return -5;
        if( $iSingleDeckCounter != 4 )
            return -6;
        
        # Подсчет количества кораблей по вертикали :
        for( $iX = 0; $iX < 10; $iX++ ) {
            $aTmp = array();
            for( $iY = 0; $iY < 10; $iY++ )
                $aTmp[] = $aField[$iY][$iX];
            $sTmp = str_replace( array( '[', ']' ), array( '0,', ',0' ), json_encode( $aTmp ) );
            $iDoubleDeckCounter += substr_count( $sTmp, '0,1,1,0' );
            $iThreeDeckCounter += substr_count( $sTmp, '0,1,1,1,0' );
            $iFourDeckCounter += substr_count( $sTmp, '0,1,1,1,1,0' );
        }
        
        # Проверка количества кораблей на поле :
        if( $iDoubleDeckCounter != 3 || $iThreeDeckCounter != 2 || $iFourDeckCounter != 1 )
            return -6;

        return true;
    }
}

  Ответить  
 
 автор: iMozgoloMchik   (25.07.2012 в 17:18)   письмо автору
 
   для: pazha   (25.07.2012 в 08:07)
 

ух-ты , интересно,
надо будет поскорее закончить мои сегодняшние проекты и попробовать написать морской бой тоже))
спасибо за идею))
ток я сам попробую

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования