카르카손 타일 배치


23

보드 게임

보드 게임 " Carcassonne "에서 플레이어는 가장자리를 일치시켜 타일을 배치하고 넓은 연속적인 지형 영역을 만들어 최고 점수를 얻습니다. 다음은 게임에 포함 된 타일의 종류와 수량입니다.

#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도 회전 할 수 있습니다.

가장자리 매칭

  • 배치 된 타일의 가장자리는 (최대 4) 인접 타일의 터치 가장자리와 일치해야합니다. 즉, 터치 픽셀은 동일한 색상입니다.

연속 지형

  • "지형 영역 닫기"는 타일을 배치하여 연속 된 색상 영역을 추가 타일 배치로 계속할 수 없도록하는 것을 말합니다.
  • 대체 배치가 가능한 경우 지형 영역을 닫을 타일 배치 중에서 선택해야합니다.
  • 여러 개의 폐쇄 게재 위치 중에서 선택해야하는 경우 원하는 것을 선택하십시오. 닫지 않는 여러 게재 위치 중에서 선택해야하는 경우 원하는 항목을 선택하십시오.
  • 연속 영역을 계산할 때는 # ff00ff (코너 픽셀)를 무시하십시오. 또한 타일, 타일로 완전히 둘러싸인 색상 영역을 무시하십시오.

입력

  • 입력은 두 개의 이미지입니다.

    1. 놀이 공간.

      • 초기 플레이 영역은 타일 #11(단일 타일) 로 구성됩니다 .
      • 출력으로 생성 된 증강 플레이 영역도 입력으로 지원되어야합니다.
    2. 배치 할 타일입니다.

      • 모든 예제 타일이 입력으로 지원되어야합니다.
  • 이 이미지 데이터 만 사용하여 일치하는 가장자리 / 연속 지형을 결정하십시오. 하드 코딩이 없습니다.

산출

  • 출력은 타일을 배치 한 후 결과 재생 영역을 보여주는 이미지입니다.
  • 이미지는 자신의 프로그램과 호환 가능해야합니다. 즉, 재생 영역 입력으로 사용할 수 있습니다.
  • 타일을 배치 할 수 없으면 오류를 반환하십시오.

당신은 가정 할 수 있습니다

  • 타일은 항상 55x55 픽셀입니다.
  • 타일은 예제 타일에 현재 사용 된 색상 만 특징으로합니다.

노트

  • 귀하의 답변에는 2 회 이상의 합격 후 예제 출력이 포함되어야합니다 (더 많은 권장).
  • 이것은 원래 보드 게임의 부분적이고 부정확 한 렌더링이므로 여기에 언급되지 않은 규칙이나 전술을 적용 할 필요는 없습니다.

점수

  • 점수는 제출물의 바이트 수입니다.
  • 이미지 데이터는 점수에 포함되지 않습니다.
  • 최저 점수가 이깁니다.


정식 게임

복종을 사용하여 정식 게임을하는 스크립트를 작성할 수 있습니다.

  • 전체 85 세트에서 의사 무작위로 선택한 타일 배치.
  • 타일을 놓을 수 없으면 세트로 되돌립니다.
  • 모든 타일이 배치 될 때까지 또는 한 행에 두 개의 타일을 배치 할 수 없을 때까지 반복합니다.

바이트 수에 포함되지 않거나 점수를 향상 시키지는 않지만 이런 종류의 답변에 현상금을 제공 할 것입니다.


1
12, 15, 17의 차이점은 무엇입니까?
kaine

그것을 발견해 주셔서 감사합니다. 17은 중복되었습니다. 그러나 15는 지형 영역을 잠재적으로 닫을 수 있기 때문에 다릅니다. (btw, 픽셀의 모서리 만 닿으면 색상 영역이 인접하지 않습니다)
jsh

따라서 1 15와 2 2는 크기가 2 인 2 개의 별도의 검은 섹션을 만들 수 있지만, 1 12와 2 2는 대신 3 큰 검은 섹션을 만들 수 있습니다. 승인.
kaine

2
1. ms paint fill bucket 도구를 사용하여 영역의 색상을 변경할 수 있으면 인접한 영역입니다. 귀하의 예에는 7 개의 연속 영역이 있습니다. 2. 합리적으로 들립니다. 지정된 두 개의 이미지를 사용하는 한 원하는대로 할 수 있습니다. 3. 원하는 방식으로 빈 공간을 묘사 할 수 있습니다. 투명성은 좋은 옵션입니다. 예제 타일에없는 색상을 사용할 수도 있습니다.
jsh

1
@ hosch250 재생 영역은 무한합니다 (필요한 경우 확장). 플레이에서 첫 번째 타일 만 있으면 첫 번째 타일 전체 플레이 영역입니다.
jlahd

답변:


8

PerlMagick을 사용하는 Perl 5 : 875789 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.png25.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

공통 리스프, 2650 2221 1992 1186 1111 바이트

업데이트 : "쉬운"골프가 완료되었습니다. 더 많은 이익을 얻으려면 더 큰 변화가 필요합니다.

업데이트 2 : 경쟁이 치열 해짐에 따라 새 버전은 더 이상 현재 경기장 필드 내부의 위치를 ​​선호하지 않습니다 (57 바이트 추가). 간단한 속도 최적화뿐만 아니라이 옵션은 시뮬레이터가있는 다운로드 가능한 버전에서 기본적으로 활성화되어 있지만 아래 공식 답변에서는 그렇지 않습니다.

업데이트 3 : 주요 바이트 수 이득에 대한 사소한 인터페이스 변경.

간단한 웹 UI도 만들었습니다. 전체 패키지 (단일 LISP 파일 및 타일 이미지)는 여기에서 다운로드 할 수 있습니다 . , 그것을 시도 설치 hunchentoot, zpngpng-readquiclisp에서 부하 carcassonne.lisp와 연결할 localhost:8080. 이 코드는 CCL / Windows 및 SBCL / Linux에서 테스트되었습니다. 위에서 언급 한 라이브러리는 UI / 시뮬레이터 부분에만 필요합니다. 솔루션 자체는 일반 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무효화 되었을 수 있음) 일지라도 반환되는 새 필드를 사용해야합니다 .

코드는 이제 느린 쪽의 바이트 수 최적화로 인해 중복 계산이 발생합니다. 아래 예제는 시스템에서 약 3 분 안에 완료되었습니다.

85 개 타일 모두에 대한 예제 실행 :

여기에 이미지 설명을 입력하십시오

웹 UI 스크린 샷 :

여기에 이미지 설명을 입력하십시오


게재 위치를 현재 사각형 내에 두는 것이 좋습니다. 나는 당신이 쉬운 길을 가면 뱀이되는 경향이 있다는 것을 알았습니다.
BMac

이기는 점수는 아니지만 몇 가지 멋진 혁신에 대한 보상을받습니다.
jsh

9

DarkBASIC Pro : 2078 1932 1744 바이트

업데이트 : 더 많은 골프 노력

업데이트 : 이제 닫는 선택을 선호하는 것을 포함하여 사양을 완전히 충족시킵니다.

DarkBASIC을 선택한 이유는 다소 장황하지만 이미지 조작을위한 매우 간단하고 간단한 명령 세트를 제공하기 때문입니다.

DarkBASIC 컴파일러 ( Windows ) 가없는 사람들을 위해 EXE를 업로드했습니다 .

샘플 출력

#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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.