Поместить плитку Каркассон


23

Настольная игра

В настольной игре « Каркассон » игроки размещают плитки, сопоставляя их края, и получают самые высокие баллы, создавая большие непрерывные участки местности. Ниже приведены (примерно) типы и количество плиток, включенных в игру:

#01 x4 введите описание изображения здесь #02 x5 введите описание изображения здесь #03 x8 введите описание изображения здесь #04 x2 введите описание изображения здесь

#05 x9 введите описание изображения здесь #06 x4 введите описание изображения здесь #07 x1 введите описание изображения здесь #08 x3 введите описание изображения здесь

#09 x3 введите описание изображения здесь #10 x3 введите описание изображения здесь #11 x4 введите описание изображения здесь #12 x5 введите описание изображения здесь

#13 x3 введите описание изображения здесь #14 x3 введите описание изображения здесь #15 x2 введите описание изображения здесь #16 x5 введите описание изображения здесь

#17 x5 введите описание изображения здесь #18 x2 введите описание изображения здесь #19 x3 введите описание изображения здесь #20 x1 введите описание изображения здесь

#21 x5 введите описание изображения здесь #22 x2 введите описание изображения здесь #23 x1 введите описание изображения здесь #24 x1 введите описание изображения здесь

#25 x1 введите описание изображения здесь

Задание

Вы должны поместить плитку, сопоставляя края, пытаясь сохранить как можно больше смежных областей местности.

размещение

  • Плитки могут быть размещены только в одном из (до 4) пустых мест рядом с любой существующей плиткой (или плитками) в игровой зоне.
  • Плитка может поворачиваться на 90, 180 или 270 градусов.

Edge-согласование

  • Края размещенной плитки должны соответствовать соприкасающимся краям (до 4) соседних плиток, т. Е. Сенсорные пиксели имеют одинаковый цвет.

Смежная местность

  • «Закрытие области местности» относится к размещению плитки таким образом, чтобы любая непрерывная цветная область не могла быть затем продолжена при дальнейшем размещении плитки.
  • Если возможно альтернативное размещение, оно должно быть выбрано над любым размещением плитки, которое будет закрывать область местности.
  • Если вам нужно выбрать из нескольких мест закрытия, выберите любое. Если вам нужно выбрать между несколькими закрытыми местами размещения, выберите любое.
  • Не учитывать # ff00ff (угловые пиксели) при расчете смежных областей. Также не обращайте внимания на здания, то есть участки цвета, которые уже полностью заключены в плитку.

вход

  • Ввод двух изображений:

    1. Игровая площадка.

      • Начальная игровая зона состоит из плитки #11(одной плитки).
      • Расширенная игровая зона, созданная как выходная, также должна поддерживаться как входная.
    2. Плитка для размещения.

      • Все примеры плиток должны поддерживаться в качестве входных данных.
  • Определите совпадающие края / смежную местность, используя только эти данные изображения. Нет жесткого кодирования.

Выход

  • Выход - изображение, показывающее результирующую игровую зону после размещения плитки.
  • Изображение должно быть совместимо с вашей собственной программой, т. Е. Оно может использоваться как вход игровой зоны.
  • Если невозможно разместить плитку, верните ошибку.

Вы можете предположить, что

  • Плитка всегда 55 пикселей на 55 пикселей
  • Плитки будут только отображать цвета, используемые в данный момент в примерах плиток.

Заметки

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

Гол

  • Ваша оценка - это количество байтов вашей заявки.
  • Данные изображения не включены в ваш счет.
  • Самый низкий балл побеждает.


Играть в полную игру

Вы можете написать сценарий, который использует ваше подчинение, чтобы играть в полную игру, которая может состоять из:

  • Размещение плитки выбрано псевдослучайно из полного набора 85.
  • Возврат плитки к набору, если она не может быть размещена.
  • Повторяется до тех пор, пока не будет размещена каждая плитка - или пока две плитки подряд не могут быть размещены.

Он не будет включен в ваш счетчик байтов или улучшит ваш счет, но я, скорее всего, предложу вознаграждение за такой ответ.


1
В чем разница между 12, 15 и 17?
kaine

спасибо, что поймали это, 17 был дубликатом. однако 15 действительно отличается, так как потенциально может закрыть область местности. (кстати, области цвета не являются смежными, если касаются только углы пикселей)
jsh

Таким образом, одна пятерка и две двойки могут сделать две отдельные черные секции размером 2. В то время как одна пятерка и две двойки могут сделать черные секции размером 3 большие. Хорошо.
kaine

2
1. если вы можете использовать инструмент заливки ms ms для изменения цвета области, то это непрерывная область. в вашем примере будет 7 смежных областей. 2. это звучит разумно. если вы используете два изображения, как указано, вы можете делать это, как вы хотите. 3. Вы можете изобразить пустое пространство любым удобным вам способом. прозрачность - хороший вариант. Вы также можете использовать любой цвет, не показанный в примерах плиток.
JSH

1
@ hosch250 игровая зона бесконечна (расширяется по мере необходимости). Когда в игре находится только первая плитка, первая плитка - это вся игровая зона.
января

Ответы:


8

Perl 5 с PerlMagick: 875 789 763

Я не посчитал линию, начинающуюся с sub w, которая используется для сортировки позиций на расстоянии до центра, чтобы отдать предпочтение компактным решениям (теперь работает правильно). В этой версии закрытие избегается, как требуется, но я считаю, что противоположность более интересна и верна игре. Для этого измените строку $s=$t if!grep...на $s=$t if grep....

use Image::Magick;
sub p{/x/;@o=$r->GetPixel(y=>$'+pop,x,$`+pop);"@o"}
sub o{$w=&p;"0 0 0"eq$w?3:&p eq$w}
sub f{$r->FloodfillPaint(y=>$J+$',x,$I+$&,channel,All,fill,@_)}
($i=Image::Magick->new)->Read(@ARGV);$r=$b=$i->[0];
$h=$b->Get(rows)+112;$:=$b->Get(width)+112;
$b->Extent(geometry,"$:x$h-56-56",background,none);
@v=grep p()eq"0 0 0",map{map-54+55*$_.x.($'*55-54),//..$:/55}1..$h/55;
sub w{$_=pop;/x/;abs($:-2*$`)+abs($h-2*$')}@v=sort{w($b)<=>w($a)}@v;
map{map{/x/;$I=$`;$J=$';$r=$b->Clone();
($t=$r)->Composite(image,$i->[1],x,$I,y=>$J);
if((o(27,0,27,-1)&o(0,27,-1,27)&o(27,54,27,55)&o(54,27,55,27))==1){
$s=$t if!grep{/../;$r=$t->Clone();f(none);f(red);
!grep{p()eq"1 0 0"}@v}
map{/..$/;($_,$&.$`)}map{($_.-1,$_.55)}10,27,45;
$o=$r=$t;}$i->[1]->Rotate(degrees,90)}($_)x4}@v;
$s||=$o or exit 1;$s->Trim();$s->Write("car.png")

Использование: perl car.pl board.png tile.png. Результат сохранен в car.png. Статус выхода равен 1, если плитка не может быть размещена.

Скрипт для запуска полной игры. Он принимает код , указанный выше в файле car.plи плитки хранятся в tilesкаталоге с именем 01.pngв 25.png.

use List::Util shuffle;$x='00';
@t=shuffle map{($x++)x$_}split'',a4582941333353325523152111;
`cp tiles/11.png car.png`;
$i++,`perl car.pl car.png tiles/$_.png`,print"placed $i\n"for@t

Это работает довольно медленно сейчас. 8-12 минут на моей машине. С закрытием предпочтительнее: Предпочитаю закрытие примера с закрытием избегать (примечание ничего не закрыто).


Тест закрытия области, кажется, не работает должным образом . Плитка «город с углом дороги» в точке (0,1) была последней.
Jlahd

@jlahd Вы правы. Для тестов я изменил условие, так как регион гораздо проще не закрыть (в реальной игре это также лучшая стратегия - закрыть их). Но теперь я не уверен, работает ли это обратное условие правильно. Я исправлю это сегодня.
Nutki

@jlahd Исправлено, спасибо, что заметили. Противоположное условие было в порядке после всего BTW.
Nutki

15

Common Lisp, 2650 2221 1992 1186 1111 байт

Обновление: «Легкая» игра в гольф теперь сделана, дальнейшие достижения потребуют больших изменений.

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

Обновление 3: Незначительные изменения интерфейса для увеличения числа основных байтов.

Я также создал простой веб-интерфейс. Полный пакет (один файл LISP и изображения листов) может быть скачать здесь . Для того, чтобы попробовать, установить hunchentoot, zpngи png-readс quiclisp, нагрузки в carcassonne.lisp, и подключиться к localhost:8080. Код был протестирован на CCL / Windows и SBCL / Linux. Вышеупомянутые библиотеки нужны только для части пользовательского интерфейса / симулятора; Само решение является простым ANSI Common Lisp.

(defun c(f p &aux b a s z(c 55))
  (macrolet((d(v l &body b)`(dotimes(,v,l),@b))
            (b(b c)`(d i c(d j c(setf,b,c))))
            (r(&rest p)`(aref,@p))
            (n(u v i j)`(and(setf l(*(f,u,v)l))
                            (find(r f(+,u,i)(+,v,j))`(0,(r f,u,v))))))
    (labels((p(p w)(d y(ceiling w 2)(d x(- w y y)(rotatef(r p y #6=(+ x y))(r p #6##7=(- w y))(r p #7##8=(- w x y))(r p #8#y)))))
            (a(y x)(or(if(= 0(r f y x))1 #4=(and(= 1(incf(r s y x)))(=(r f y x)z)(push`(,y,x)a)0))0))
            (f(y x)(setf z(r f y x))(if #4#(loop for((y x))= a while(pop a)maximize(+(a(1- y)x)(a y(1- x))(a(1+ y)x)(a y(1+ x))))1)))
      (d i 8(when(d x #1=(array-dimension f 0)(or(= 0(r f(- #1#52 i)x))(return t)))(setf f(adjust-array f`(#2=,(+ #1#c)#2#))))(p f(1- #1#)))
      (d i 4(d u #9=(/ #1#c)(d v #9#
        (let((y(* u c))(x(* v c))(l 9e9))
          (when(= 0(r f y x))
            (b #10=(r f(+ y i)(+ x j))(r p i j))
            (setf s(make-array`(,#1#,#1#))a())
            (ignore-errors(if(> #11=(*(loop for d from 1 to 53
                                            sum(+(n y #3=(+ x d)-1 0)(n #5=(+ y d)(+ 54 x)0 1)(n(+ 54 y)#3#1 0)(n #5#x 0 -1)))
                                      (1+ l))
                                (or(car b)0))
                             (setf b`(,#11#,i,y,x))))
            (b #10#0)))))
         (p p 54))
      (when b(d j(cadr b)(p p 54))(b(r f(+(third b)i)(+(nth 3 b)j))(r p i j)))
      `(,f,b))))

Все переводы строк и межстрочный интервал предназначены только для косметики, чтобы обеспечить удобочитаемость и не учитываются в общей сумме.

Вы должны вызвать функцию cс двумя аргументами: текущим игровым полем и плиткой для размещения. Оба должны быть 2D-массивами; плитка 55x55 и поле, кратное этому. Кроме того, массив полей должен быть настраиваемым. Функция возвращает двухэлементный список с новым полем в качестве первого аргумента. Второй элемент, NILесли плитку нельзя разместить, или иным образом список, содержащий координаты верхнего левого угла и поворот самой последней плитки в этом массиве и счет для этой плитки. Эта информация может использоваться для целей визуализации.

Обратите внимание, что при дальнейших вызовах вы должны использовать новое поле, возвращаемое cдаже если второй элемент списка равен NIL(возможно, исходный массив был adjust-arrayотредактирован и, таким образом, признан недействительным).

Код теперь немного медленный, оптимизация подсчета байтов приводит к избыточным вычислениям. Пример ниже завершен примерно через три минуты в моей системе.

Пример прогона для всех 85 плиток:

введите описание изображения здесь

Скриншот веб-интерфейса:

введите описание изображения здесь


Желательно, чтобы размещение было внутри текущего прямоугольника. Я заметил, что если вы выбираете легкий путь, это может быть змеей.
BMac

не победный счет, но вы получаете награду за несколько приятных нововведений.
2011 года

9

DarkBASIC Pro: 2078 1932 1744 байта

ОБНОВЛЕНИЕ: просто больше усилий в гольф

ОБНОВЛЕНИЕ: теперь полностью соответствует спецификации, в том числе предпочитая не закрывающий выбор.

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

Я загрузил EXE для людей, у которых нет компилятора DarkBASIC ( Windows ).

Образец вывода

#constant m memblock
#constant f function
#constant k endfunction
#constant z exitfunction
#constant i image
#constant e endif
#constant t then
#constant o or
#constant s paste image
#constant n next
#constant r for
set i colorkey 0,20,0:load i "map.png",1:f$="next.png"
if file exist(f$)=0 t f$=str$(rnd(24)+1)+".png"
load i f$,2:make m from i 1,1:make m from i 2,2
global ts,h,j,u,v,td
ts=i width(2):h=i width(1):j=i height(1):u=h/ts:v=j/ts:td=ts*2
create bitmap 2,h+td+1,j+td+1:r b=1 to 4:r xx=0 to u+1:r yy=0 to v+1:x=xx*ts-1:y=yy*ts-1
cls 5120:s 1,ts,ts,1:if (a(x+1,y) o a(x,y+1) o a(x-ts,y) o a(x,y-ts)) and a(x,y)=0
x1=ts*xx:y1=ts*yy:make i from m 2,2:s 2,x1,y1,1
cl=0:r fd=0 to 1:r x2=1 to ts-2:r yt=0 to 1:y2=yt*ts-yt:y3=yt*ts+yt-1
aa=x2:ab=x2:ba=y2:bb=y3:t2=y1:r t3=0 to 1:p=point(x1+aa,y1+ba):q=point(x1+ab,y1+bb)
if p<>q and rgbg(q)<>20 and t2+b>0 t goto fa
if fd and p<>0xFF0000
if l(x1+aa,y1+ba,p)=0 t cl=1
e
aa=y2:ba=x2:bb=x2:ab=y3:t2=x1:n t3:n yt:n x2:n fd:dn=1:c=xx-1:g=yy-1:make i from m 3,2:if cl=0 t goto dm
e
fa:
n y:n x
d=ts/2:r x=0 to d:r y=0 to d-1:vx=ts-1-x:vy=ts-1-y:t1=rd(x,y):t2=rd(vy,x):wr(vy,x,t1):t1=rd(vx,vy):wr(vx,vy,t2):t2=rd(y,vx):wr(y,vx,t1):wr(x,y,t2):n x:n y:n b
dm:
if dn=0 t report error "Not placed"
p=c<0:q=g<0:t1=h+ts*(p o c>=u):t2=j+ts*(q o g>=v):cls 5120:p=ts*p:q=ts*q:s 1,p,q,1:s 3,c*ts+p,g*ts+q,1:get i 1,0,0,t1,t2,1:save i "map.png",1
end
f l(x,y,w)
if x<0 o y<0 o x>=h+td o y>=j+td t z 1
p=point(x,y)
if rgbg(p)=20 t z 1
if p<>w t z 0
dot x,y,0xFF0000:rt=l(x+1,y,p) o l(x-1,y,p) o l(x,y+1,p) o l(x,y-1,p)
k rt
f rd(x,y)
w=m dword(2,0):b=m dword(2,12+(y*w+x)*4)
k b
f wr(x,y,d)
w=m dword(2,0):write m dword 2,12+(y*w+x)*4,d
k
f a(x,y)
if x<0 o y<0 o x>=h o y>=j t z 0
b=m byte(1,15+(y*h+x)*4)
k b
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.