Pull to refresh

Comments 11

Все здорово, но черт-побери зачем было использовать кривой сторонний класс-интерпретатор? Он (интерпретатор) очень простой внутри — нужно разобраться в языке один раз и все — легко напишете. Если интересно, могу выложить свою реализацию BF на javascript.
Кстати, нашел проблему в ихнем интерпретаторе:
Сорри, случайно отправилось… Во время перехода на другую ячейку (оператор '>' или '<') нужно проверять, инициализирована ячейка или нет. Если не инициализирована — нужно присваивать ей нулевое значение. В том итерпретаторе такого нет, отсюда и глюки (прибваление к/отнимание от неинициализированной переменной).
Да я тоже заметил ошибку в классе
Этот класс выдавал warning, поэтому рекомендую на 79 строчке поставить подавление ошибок @

Нашел этот класс на гитхабе. Там вышло два класса в поиске, но второй поддерживал другие языки (например Ook) и выглядел монструозно для такой простой статьи.
Я не говорю что написать интерпретатор для brainfuck проблемно, просто зачастую не стоит делать велосипеды — в этой статье разбирался именно перевод brainloller в brainfuck код и получившийся класс вполне сносно выполняет свою задачу.
осталось добавить что выбрал brainloller для песочницы потому, что для него не видел интерпретаторов вообще, но тема показалась интересной и алгоритм относительно прост для новичка.
Первое что бросилось в глаза — это бесконечный цикл for(;;) и ниже условие для выхода из цикла. Потом бессмысленный перевод индекса цвета в массив, потом использование простыней из switch. Короче, захотелось переписать.

class BrainLoller2 {

    const DIRECTION_UP = 0;
    const DIRECTION_RIGHT = 1;
    const DIRECTION_DOWN = 2;
    const DIRECTION_LEFT = 3;
    
    protected $directions = array(array( 0,-1),
                                  array( 1, 0),
                                  array( 0, 1),
                                  array(-1, 0));
    protected $commands = array(0x00FF00 => '+', 
                                0x008000 => '-', 
                                0xFF0000 => '>',
                                0x800000 => '<',
                                0xFFFF00 => '[',
                                0x808000 => ']',
                                0x0000FF => '.',
                                0x000080 => ',');
    
    protected $picture; // Картинка BrainLoller
    protected $size = array(0,0);

    function __construct($picture){
        // Открываем собственно изображение
        $this->picture = imagecreatefrompng($picture);
        // Получаем размер изображения
        $this->size = getimagesize($picture);
    }

    public function getCode(){
        $current_pixel = array(0, 0); // Текущий пиксель (x, y)
        $pointer = self::DIRECTION_RIGHT;
        $code = '';
        
        while(!($current_pixel[0] > $this->size[0] or $current_pixel[1] > $this->size[1] or 
                $current_pixel[0] < 0 or $current_pixel[1] < 0)){
            $pixel_color = imagecolorat($this->picture, $current_pixel[0], $current_pixel[1]); // Берем цвет пикселя
            $pixel_color &= 0xFFFFFF;
            
            // Проверяем какой команде сопоставлен данный цвет, если поворот то поворачиваем, если команда то добавляем к $code
            if (isset($this->commands[$pixel_color]))
                    $code .= $this->commands[$pixel_color];
            elseif ($pixel_color == 0x00FFFF)
                $pointer = ($pointer + 1) % 4;
            elseif ($pixel_color == 0x008080)
                $pointer = ($pointer - 1 + 4) % 4;
            
            $current_pixel[0] += $this->directions[$pointer][0];
            $current_pixel[1] += $this->directions[$pointer][1];
        }
        return $code;
    }

    function __destruct(){
        imagedestroy($this->picture); // Высвобождаем занятые ресурсы
    }
}


P.S. Что-то мне подсказывает, что нельзя попасть в бесконечный цикл.
Благодарю за поправки! код писался ночью, получилось много не оптимизированного кода…
Заюзать новую фишку php 5.3 сделав статический метод который будет возвращать код без создания класса (например BrainLoller::getCode('picture_url'))

Если я не ошибаюсь, то вызов статичного метода появился ранее чем в php 5.3. Поправьте меня, если я ошибаюсь.
Sign up to leave a comment.

Articles