カルカソンヌタイルを配置する


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度回転できます。

エッジマッチング

  • 配置されたタイルの端は、隣接するタイル(最大4つ)の接触端と一致する必要があります。つまり、接触ピクセルは同じ色です。

連続した地形

  • 「地形の領域を閉じる」とは、タイルを配置することを指します。これにより、隣接する色の領域がさらにタイル配置を続けることができなくなります。
  • 代替配置が可能な場合、地形のエリアを閉じるタイル配置よりも選択する必要があります。
  • 複数の終了プレースメントから選択する必要がある場合は、いずれかを選択します。多数の閉じていないプレースメントから選択する必要がある場合は、いずれかを選択します。
  • 連続領域を計算するときは#ff00ff(コーナーピクセル)を無視します。また、建物、つまりタイルで既に完全に囲まれている色の領域も無視してください。

入力

  • 入力は2つの画像です。

    1. プレイエリア。

      • 最初のプレイエリアはタイル#11(単一のタイル)で構成されています。
      • 出力として作成された拡張プレイエリアも入力としてサポートされる必要があります。
    2. 配置するタイル。

      • サンプルタイルはすべて、入力としてサポートされる必要があります。
  • この画像データのみを使用して、一致するエッジ/連続した地形を決定します。ハードコーディングなし。

出力

  • 出力は、タイルを配置した後の結果の再生領域を示す画像です。
  • 画像は、独自のプログラムと互換性がある必要があります。つまり、再生領域の入力として使用できます。
  • タイルを配置できない場合は、エラーを返します。

あなたはそれを仮定することができます

  • タイルは常に55ピクセルx 55ピクセルです
  • タイルには、サンプルタイルで現在使用されている色のみが表示されます。

ノート

  • あなたの答えは、少なくとも2回のパスの後の出力例を特徴とする必要があります(もっと推奨されます)。
  • これは、元のボードゲームの部分的かつ不正確なレンダリングです。ここで言及されていないルールや戦術を適用する必要はありません。

スコア

  • スコアは提出のバイト数です。
  • 画像データはスコアに含まれません。
  • 最低スコアが勝ちます。


完全なゲームをプレイする

サブミッションを使用して完全なゲームをプレイするスクリプトを作成できます。

  • 85の完全なセットから擬似ランダムに選択されたタイルを配置します。
  • 配置できない場合は、タイルをセットに戻します。
  • すべてのタイルが配置されるまで、または連続する2つのタイルを配置できなくなるまで繰り返します。

バイトカウントに含まれたり、スコアを改善したりすることはありませんが、この種の答えには賞金を提供する可能性があります。


1
12、15、17の違いは何ですか?
ケイン14年

それをキャッチしてくれてありがとう、17は重複していました。ただし、15は地形のエリアを潜在的に閉じることができるため異なります。(画素のみコーナーが触れる場合ところで、色の領域が連続していない)
JSH

したがって、1つの15と2つの2で、サイズ2の2つの別々の黒いセクションを作成できます。一方、1つの12と2つの2で、代わりに3つの大きな黒いセクションを作成できます。OK。
ケイン14年

2
1. ms塗りつぶしバケットツールを使用して領域の色を変更できる場合、それは連続した領域です。あなたの例では、7つの連続した領域があります。2.それは合理的に聞こえます。指定されたとおりに2つの画像を使用している限り、必要に応じてこれを行うことができます。3.好きなように空白を描くことができます。透明度は良いオプションです。サンプルタイルにない色を使用することもできます。
jsh 14年

1
@ hosch250プレイエリアは無限です(必要に応じて拡張します)。プレイの最初のタイルだけで、最初のタイルプレイエリア全体です。
jlahd

回答:


8

PerlMagickを使用したPerl 5: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あり、タイルがto 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 14

@jlahdあなたは正しい。テストでは、リージョンを閉じないほうがはるかに簡単なので、条件を逆にしました(実際のゲームでは、リージョンを閉じる方が良い戦略です)。しかし今、この逆条件が適切に機能するかどうかはわかりません。今日それを修正します。
nutki

@jlahd修正、気づいてくれてありがとう。反対の条件は、すべてのBTWの後でOKでした。
nutki 14

15

Common Lisp、2650 2221 1992 1186 1111バイト

更新:「簡単」なゴルフが完了しました。さらなる利益を得るには、より大きな変更が必要です。

更新2:競争が激化しているため、新しいバージョンでは現在の競技場の四角形内の位置が優先されなくなりました(57バイト余分になります)。このオプションは、単純な速度の最適化と同様に、シミュレーターを備えたダウンロード可能なバージョンではデフォルトで有効になっていますが、以下の公式の回答では無効になっています。

更新3:主要なバイトカウントの増加に関するマイナーインターフェイスの変更。

シンプルなWeb UIも作成しました。完全なパッケージ(単一のLISPファイルとタイルイメージ)はここからダウンロードできます。、それを試してインストールするにはhunchentootzpngおよびpng-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現在のプレイフィールドと配置するタイルの2つの引数で関数を呼び出す必要があります。両方とも2D配列でなければなりません。タイル55x55とその倍数のフィールド。さらに、フィールド配列は調整可能でなければなりません。この関数は、新しいフィールドを最初の引数として持つ2要素のリストを返します。2番目の要素はNIL、タイルを配置できない場合、またはその配列の最新のタイルの左上座標と回転、およびそのタイルのスコアを含むリストです。この情報は、視覚化の目的に使用できます。

後続の呼び出しではc、2番目のリスト要素がNIL(元の配列がadjust-array編集されて無効化されている場合でも)によって返される新しいフィールドを使用する必要があることに注意してください。

現在、コードは少し遅いため、バイトカウントが最適化され、計算が冗長になります。以下の例は、私のシステムで約3分で完了しました。

85タイルすべての実行例:

ここに画像の説明を入力してください

Web UIスクリーンショット:

ここに画像の説明を入力してください


現在の四角形内に配置することをお勧めします。あなたが簡単なルートをとると、ヘビのようになる傾向があることに気付きました。
BMac 14年

勝者の得点ではありませんが、いくつかの素晴らしい革新の恩恵を受けます。
jsh 14年

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.