Tempatkan ubin Carcassonne

23

Permainan papan

Dalam permainan papan, pemain " Carcassonne " menempatkan ubin dengan mencocokkan tepi mereka dan mendapatkan skor tertinggi dengan menciptakan area medan yang berdekatan. Berikut ini adalah (kira-kira) jenis dan jumlah ubin yang termasuk dalam game:

#01 x4 masukkan deskripsi gambar di sini #02 x5 masukkan deskripsi gambar di sini #03 x8 masukkan deskripsi gambar di sini #04 x2 masukkan deskripsi gambar di sini

#05 x9 masukkan deskripsi gambar di sini #06 x4 masukkan deskripsi gambar di sini #07 x1 masukkan deskripsi gambar di sini #08 x3 masukkan deskripsi gambar di sini

#09 x3 masukkan deskripsi gambar di sini #10 x3 masukkan deskripsi gambar di sini #11 x4 masukkan deskripsi gambar di sini #12 x5 masukkan deskripsi gambar di sini

#13 x3 masukkan deskripsi gambar di sini #14 x3 masukkan deskripsi gambar di sini #15 x2 masukkan deskripsi gambar di sini #16 x5 masukkan deskripsi gambar di sini

#17 x5 masukkan deskripsi gambar di sini #18 x2 masukkan deskripsi gambar di sini #19 x3 masukkan deskripsi gambar di sini #20 x1 masukkan deskripsi gambar di sini

#21 x5 masukkan deskripsi gambar di sini #22 x2 masukkan deskripsi gambar di sini #23 x1 masukkan deskripsi gambar di sini #24 x1 masukkan deskripsi gambar di sini

#25 x1 masukkan deskripsi gambar di sini

Tugas

Anda harus meletakkan ubin dengan mencocokkan tepinya, sambil mencoba mempertahankan area dataran berdekatan yang seluas mungkin.

Penempatan

  • Ubin hanya dapat ditempatkan di salah satu (hingga 4) ruang kosong yang berdekatan dengan ubin yang ada (atau ubin) di area bermain.
  • Ubin dapat diputar 90, 180 atau 270 derajat.

Pencocokan tepi

  • Tepi ubin yang ditempatkan harus cocok dengan tepi menyentuh dari (hingga 4) ubin tetangga, yaitu menyentuh piksel adalah warna yang sama.

Medan yang berdekatan

  • "Menutup area medan" mengacu pada menempatkan ubin sedemikian rupa sehingga area warna yang berdekatan tidak dapat dilanjutkan dengan penempatan ubin lebih lanjut.
  • Jika penempatan alternatif dimungkinkan, itu harus dipilih daripada penempatan ubin apa pun yang akan menutup area medan.
  • Jika Anda harus memilih di antara sejumlah penempatan penutupan, pilih salah satunya. Jika Anda harus memilih di antara sejumlah penempatan yang tidak ditutup, pilih salah satunya.
  • Abaikan # ff00ff (piksel sudut) saat menghitung area yang berdekatan. Juga mengabaikan bangunan, yaitu area warna yang sudah tertutup sepenuhnya dalam ubin.

Memasukkan

  • Input adalah dua gambar:

    1. Area bermain.

      • Area bermain awal terdiri dari ubin #11(ubin tunggal).
      • Area bermain yang diperbesar yang dibuat sebagai output juga harus didukung sebagai input.
    2. Ubin yang akan ditempatkan.

      • Semua ubin contoh harus didukung sebagai input.
  • Tentukan tepi yang cocok / medan yang berdekatan menggunakan data gambar ini saja. Tidak ada hardcoding.

Keluaran

  • Output adalah gambar yang menunjukkan area bermain yang dihasilkan setelah menempatkan ubin.
  • Gambar harus kompatibel dengan program Anda sendiri, yaitu dapat digunakan sebagai input area bermain.
  • Jika tidak mungkin menempatkan ubin, kembalikan kesalahan.

Anda bisa berasumsi itu

  • Ubin selalu 55 px kali 55 px
  • Ubin hanya akan menampilkan warna yang saat ini digunakan dalam ubin contoh.

Catatan

  • Jawaban Anda harus menampilkan contoh output setelah setidaknya 2 berlalu (lebih didorong).
  • Ini adalah rendering parsial dan tidak akurat dari gim papan asli, Anda tidak perlu menerapkan aturan atau taktik yang tidak disebutkan di sini.

Skor

  • Skor Anda adalah jumlah byte kiriman Anda.
  • Data gambar tidak termasuk dalam skor Anda.
  • Skor terendah menang.


Bermain game penuh

Anda mungkin ingin menulis skrip yang menggunakan submissison Anda untuk memainkan permainan penuh, yang mungkin terdiri dari:

  • Menempatkan ubin yang dipilih secara acak dari set lengkap 85.
  • Mengembalikan ubin ke set jika tidak dapat ditempatkan.
  • Ulangi sampai setiap ubin ditempatkan - atau sampai dua ubin berturut-turut tidak dapat ditempatkan.

Itu tidak akan dimasukkan dalam hitungan byte Anda, atau meningkatkan skor Anda, tetapi saya kemungkinan akan menawarkan hadiah untuk jawaban semacam ini.

jsh
sumber
1
apa perbedaan antara 12, 15, dan 17?
kaine
terima kasih sudah menangkapnya, 17 adalah duplikat. namun 15 berbeda karena berpotensi menutup area medan. (btw, area warna tidak berdekatan jika hanya sudut-sudut piksel yang menyentuh)
jsh
Jadi satu 15 dan dua 2 bisa membuat 2 bagian hitam terpisah ukuran 2. Sedangkan satu 12 dan dua 2 bisa membuat bagian hitam yang 3 besar sebagai gantinya. Baik.
kaine
2
1. jika Anda dapat menggunakan alat bucket MS paint fill untuk mengubah warna suatu area, ini adalah area yang berdekatan. dalam contoh Anda akan ada 7 area yang bersebelahan. 2. itu terdengar masuk akal. selama Anda menggunakan dua gambar seperti yang ditentukan, Anda dapat melakukan ini sesuai keinginan Anda. 3. Anda dapat menggambarkan ruang kosong dengan cara apa pun yang Anda suka. transparansi adalah pilihan yang baik. Anda juga bisa menggunakan warna apa pun yang tidak ditampilkan dalam ubin contoh.
jsh
1
@ hosch250 area bermain tidak terbatas (memanjang seperlunya). Dengan hanya ubin pertama pada permainan, ubin pertama adalah seluruh area bermain.
jlahd

Jawaban:

8

Perl 5 dengan PerlMagick: 875 789 763

Saya tidak menghitung garis dimulai dengan sub w, yang digunakan untuk mengurutkan posisi pada jarak ke pusat untuk lebih memilih solusi yang ringkas (sekarang berfungsi dengan baik). Dalam penutupan versi ini dihindari seperti yang diminta tetapi saya menemukan sebaliknya lebih menarik dan benar untuk permainan. Untuk mencapai itu ubah baris $s=$t if!grep...ke $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")

Penggunaan: perl car.pl board.png tile.png. Hasil disimpan di car.png. Status keluar adalah 1 jika ubin tidak dapat ditempatkan.

Script untuk menjalankan game yang lengkap. Ini mengasumsikan kode di atas adalah dalam file car.pldan ubin disimpan dalam tilesdirektori bernama 01.pngke 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

Ini berjalan cukup lambat sekarang. 8-12 menit di mesin saya. Dengan penutupan lebih disukai: Lebih suka contoh penutupan Dengan penutupan dihindari (perhatikan tidak ada yang ditutup).

nutki
sumber
Tes dekat area tampaknya tidak berfungsi dengan baik . Ubin city-with-road-corner di (0,1) adalah yang terakhir ditempatkan.
jlahd
@ jlahd Anda benar. Untuk tes saya membalikkan kondisinya karena jauh lebih mudah untuk tidak menutup wilayah (juga merupakan strategi yang lebih baik dalam permainan sebenarnya untuk menutupnya). Tapi sekarang saya tidak yakin apakah kondisi sebaliknya ini berfungsi dengan baik. Saya akan memperbaikinya hari ini.
nutki
@ jlahd Diperbaiki, terima kasih telah memperhatikan. Kondisi sebaliknya ternyata baik-baik saja setelah semua BTW.
nutki
15

Common Lisp, 2650 2221 1992 1186 1111 byte

Perbarui: "Mudah" bermain golf sekarang dilakukan, keuntungan lebih lanjut akan membutuhkan perubahan yang lebih besar.

Pembaruan 2: Dengan persaingan yang semakin ketat, versi baru tidak lagi menyukai posisi di dalam kotak lapangan bermain saat ini (yang akan menjadi 57 byte tambahan). Opsi ini, serta optimalisasi kecepatan sederhana, secara default diaktifkan di versi yang dapat diunduh bersama simulator, tetapi tidak dalam jawaban resmi di bawah ini.

Pembaruan 3: Perubahan antarmuka kecil untuk perolehan jumlah byte utama.

Saya membuat UI Web sederhana juga. Paket lengkap (satu file LISP dan gambar ubin) dapat diunduh di sini . Untuk mencobanya, instal hunchentoot, zpngdan png-readdengan quiclisp, muat carcassonne.lisp, dan sambungkan ke localhost:8080. Kode telah diuji pada CCL / Windows dan SBCL / Linux. Perpustakaan yang disebutkan di atas hanya diperlukan untuk bagian UI / simulator; solusinya sendiri biasa 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))))

Semua umpan baris dan spasi awal hanya untuk kosmetik, untuk memastikan keterbacaan, dan tidak dihitung ke jumlah total.

Anda harus memanggil fungsi cdengan dua argumen: Bidang bermain saat ini, dan ubin untuk menempatkan. Keduanya harus berupa array 2D; ubin 55x55 dan bidang kelipatannya. Selain itu, array bidang harus dapat disesuaikan. Fungsi mengembalikan daftar dua elemen dengan bidang baru sebagai argumen pertama. Elemen kedua adalah NILjika ubin tidak dapat ditempatkan, atau daftar yang berisi koordinat kiri atas dan rotasi ubin terbaru pada array itu dan skor untuk ubin itu. Informasi ini dapat digunakan untuk keperluan visualisasi.

Perhatikan bahwa dalam panggilan selanjutnya, Anda harus menggunakan bidang baru yang dikembalikan oleh cbahkan jika elemen daftar kedua adalah NIL(array asli mungkin telah adjust-arraydiedit dan dengan demikian tidak valid).

Kode sekarang sedikit di sisi lambat, optimasi jumlah byte menghasilkan perhitungan yang berlebihan. Contoh di bawah ini selesai dalam waktu sekitar tiga menit pada sistem saya.

Contoh dijalankan untuk semua 85 ubin:

masukkan deskripsi gambar di sini

Tangkapan layar Web UI:

masukkan deskripsi gambar di sini

jlahd
sumber
Memilih penempatan di dalam persegi panjang saat ini adalah ide yang bagus. Saya memperhatikan bahwa itu cenderung ular jika Anda mengambil rute yang mudah.
BMac
bukan skor kemenangan, tetapi Anda mendapatkan karunia untuk beberapa inovasi yang bagus.
jsh
9

DarkBASIC Pro: 2078 1932 1744 bytes

PEMBARUAN: Hanya upaya golf yang lebih banyak

UPDATE: Sekarang sepenuhnya memenuhi spesifikasi, termasuk lebih memilih pilihan yang tidak menutup.

Saya memilih DarkBASIC karena walaupun agak bertele-tele, itu memberikan perintah yang sangat mudah dan sederhana untuk memanipulasi gambar.

Saya mengunggah EXE untuk orang-orang yang tidak memiliki kompiler DarkBASIC ( Windows ).

Output sampel

#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
BMac
sumber