วางกระเบื้อง Carcassonne


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 (พิกเซลมุม) เมื่อคำนวณพื้นที่ต่อเนื่อง นอกจากนี้ยังไม่สนใจสิ่งปลูกสร้างเช่นพื้นที่ที่มีสีอยู่แล้วภายในกระเบื้อง

อินพุต

  • อินพุตเป็นภาพสองภาพ:

    1. พื้นที่เล่น

      • พื้นที่เล่นเริ่มต้นประกอบด้วยไทล์#11(ไทล์เดียว)
      • พื้นที่เล่นเสริมที่สร้างขึ้นเป็นเอาต์พุตต้องได้รับการสนับสนุนเป็นอินพุตด้วย
    2. กระเบื้องที่จะวาง

      • ไทล์ตัวอย่างทั้งหมดต้องได้รับการสนับสนุนเป็นอินพุต
  • ระบุการจับคู่ขอบ / ภูมิประเทศที่ต่อเนื่องกันโดยใช้ข้อมูลภาพนี้เพียงอย่างเดียว ไม่มีการเข้ารหัส

เอาท์พุต

  • เอาท์พุทเป็นภาพที่แสดงพื้นที่เล่นผลลัพธ์หลังจากวางกระเบื้อง
  • ภาพจะต้องเข้ากันได้กับโปรแกรมของคุณเองเช่นสามารถใช้เป็นอินพุตของพื้นที่เล่น
  • ถ้ามันเป็นไปไม่ได้ที่จะวางกระเบื้องกลับข้อผิดพลาด

คุณสามารถสันนิษฐานได้ว่า

  • ไทล์มีขนาด 55 px คูณ 55 px
  • ไทล์จะแสดงสีที่ใช้ในไทล์ตัวอย่างเท่านั้น

หมายเหตุ

  • คำตอบของคุณจะต้องแสดงตัวอย่างผลลัพธ์หลังจากผ่านไปอย่างน้อย 2 ครั้ง
  • นี่เป็นการแสดงผลเกมกระดานบางส่วนและไม่ถูกต้องคุณไม่จำเป็นต้องใช้กฎหรือยุทธวิธีใด ๆ ที่ไม่ได้กล่าวถึงที่นี่

คะแนน

  • คะแนนของคุณคือจำนวนไบต์ของการส่งของคุณ
  • ข้อมูลรูปภาพไม่รวมอยู่ในคะแนนของคุณ
  • คะแนนต่ำสุดชนะ


เล่นเกมเต็ม

คุณอาจต้องการเขียนสคริปต์ที่ใช้ submissison ของคุณเพื่อเล่นเกมเต็มซึ่งอาจประกอบด้วย:

  • การวางไทล์สุ่มเลือกจากชุดเต็มของ 85
  • ส่งคืนไทล์ไปยังชุดหากไม่สามารถวางได้
  • ทำซ้ำจนกว่าจะวางทุกไทล์ - หรือจนกว่าจะวางไพ่สองใบในแถวไม่ได้

มันจะไม่รวมอยู่ในการนับจำนวนไบต์ของคุณหรือปรับปรุงคะแนนของคุณ แต่ฉันน่าจะให้คำตอบแบบนี้


1
ข้อแตกต่างระหว่าง 12, 15 และ 17 คืออะไร
kaine

ขอบคุณที่จับได้ว่า 17 รายการซ้ำกัน อย่างไรก็ตาม 15 จะแตกต่างกันเนื่องจากอาจปิดพื้นที่ภูมิประเทศ (BTW, พื้นที่ของสีที่ไม่ต่อเนื่องกันถ้าเพียง แต่มุมของพิกเซลสัมผัส)
JSH

ดังนั้นหนึ่ง 15 และสอง 2 สามารถแบ่งส่วนสีดำขนาด 2 2 ในขณะที่หนึ่ง 12 และสอง 2 สามารถสร้างส่วนสีดำที่ 3 ใหญ่แทน ตกลง.
kaine

2
1. ถ้าคุณสามารถใช้เครื่องมือฝากข้อมูล ms paint เพื่อเปลี่ยนสีของพื้นที่มันเป็นพื้นที่ต่อเนื่อง ในตัวอย่างของคุณจะมี 7 พื้นที่ที่ต่อเนื่องกัน 2. ฟังดูสมเหตุสมผล ตราบใดที่คุณใช้สองภาพตามที่ระบุคุณสามารถทำได้อย่างไรก็ตามคุณต้องการ 3. คุณสามารถแสดงพื้นที่ว่างในแบบที่คุณชอบ ความโปร่งใสเป็นตัวเลือกที่ดี คุณสามารถใช้สีใดก็ได้ที่ไม่ได้แสดงไว้ในไทล์ตัวอย่าง
jsh

1
@ hosch250 พื้นที่เล่นไม่มีที่สิ้นสุด (ขยายตามความจำเป็น) ด้วยไทล์แรกในการเล่นไทล์แรกคือพื้นที่เล่นทั้งหมด
jlahd

คำตอบ:


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.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

Common LISP, 2650 2221 1992 1186 1111 ไบต์

อัปเดต: การตีกอล์ฟ "ง่าย" เสร็จสิ้นแล้วกำไรเพิ่มเติมจะต้องมีการเปลี่ยนแปลงที่ใหญ่กว่า

อัปเดต 2:เมื่อการแข่งขันเริ่มรุนแรงขึ้นเวอร์ชันใหม่จะไม่สนับสนุนตำแหน่งภายในสี่เหลี่ยมสนามเด็กเล่นในปัจจุบันอีกต่อไป (ซึ่งจะเพิ่มเป็น 57 ไบต์) ตัวเลือกนี้รวมถึงการเพิ่มประสิทธิภาพความเร็วอย่างง่ายคือการเปิดใช้งานตามค่าเริ่มต้นในเวอร์ชั่นที่ดาวน์โหลดได้พร้อมตัวจำลอง แต่ไม่ได้อยู่ในคำตอบอย่างเป็นทางการด้านล่าง

อัปเดต 3:การเปลี่ยนแปลงอินเตอร์เฟสรองสำหรับรับจำนวนไบต์ที่สำคัญ

ฉันสร้าง Web UI อย่างง่ายเช่นกัน แพคเกจเต็มรูปแบบ (ไฟล์เสียงกระเพื่อมเดียวและภาพกระเบื้อง) สามารถดาวน์โหลดได้ที่นี่ ที่จะลองติดตั้งhunchentoot, zpngและpng-readกับ quiclisp ภาระในและเชื่อมต่อไปยังcarcassonne.lisp localhost:8080รหัสได้รับการทดสอบบน CCL / Windows และ SBCL / Linux ไลบรารีที่กล่าวถึงข้างต้นจำเป็นสำหรับส่วน UI / โปรแกรมจำลองเท่านั้น การแก้ปัญหาของตัวเองเป็นธรรมดา ANSI เสียงกระเพื่อม

(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 มิติ ไทล์ 55x55 และฟิลด์หลายอัน นอกจากนี้อาเรย์เขตข้อมูลจะต้องปรับได้ ฟังก์ชั่นส่งกลับรายการสององค์ประกอบที่มีเขตข้อมูลใหม่เป็นอาร์กิวเมนต์แรก องค์ประกอบที่สองคือNILหากไม่สามารถวางไทล์หรือรายการที่มีพิกัดด้านบนซ้ายและการหมุนของไทล์ล่าสุดในอาร์เรย์นั้นและคะแนนสำหรับไทล์นั้น ข้อมูลนี้สามารถใช้เพื่อจุดประสงค์ในการสร้างภาพ

โปรดทราบว่าในการโทรเพิ่มเติมคุณต้องใช้ฟิลด์ใหม่ที่ส่งคืนโดยcแม้ว่าองค์ประกอบรายการที่สองคือNIL(อาเรย์ดั้งเดิมอาจถูกadjust-arrayแก้ไขและทำให้ใช้งานไม่ได้)

ตอนนี้โค้ดช้าไปหน่อยการเพิ่มประสิทธิภาพนับไบต์ทำให้มีการคำนวณซ้ำซ้อน ตัวอย่างด้านล่างเสร็จสมบูรณ์ในเวลาประมาณสามนาทีในระบบของฉัน

ตัวอย่างการรันสำหรับไทล์ทั้งหมด 85 รายการ:

ป้อนคำอธิบายรูปภาพที่นี่

ภาพหน้าจอ Web UI:

ป้อนคำอธิบายรูปภาพที่นี่


การกำหนดตำแหน่งให้อยู่ภายในสี่เหลี่ยมปัจจุบันเป็นความคิดที่ดี ฉันสังเกตเห็นว่ามันมีแนวโน้มที่จะเป็นงูถ้าคุณใช้เส้นทางที่ง่าย
BMac

ไม่ใช่คะแนนที่ชนะ แต่คุณได้รับรางวัลสำหรับนวัตกรรมที่ดีเพียงไม่กี่อย่าง
jsh

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.