Tính điểm Doppelkopf


9

Giới thiệu

Doppelkopf là một trò chơi bài truyền thống của Đức dành cho 4 người chơi. Bộ bài gồm 48 lá bài (9, 10, Jack, Queen, King, Ace của mỗi bộ đồ trong khi mỗi lá bài trong trò chơi hai lần), vì vậy mỗi người chơi được 12 lá khi bắt đầu một vòng.

Luôn có 2 đội được xác định bởi sự phân phối của Câu lạc bộ Nữ hoàng. 2 người chơi đang nắm giữ đội hình thành một đội và đấu với 2 người chơi còn lại. Đội có Nữ hoàng Câu lạc bộ được gọi là "Re" -team, đội không có là "Contra" -team.
Khi bắt đầu vòng thi không ai biết ai thuộc đội nào. Việc phân phối đội sẽ được tiết lộ trong tiến trình của vòng đấu, điều này bổ sung rất nhiều chiến lược cho trò chơi.

Trò chơi bao gồm 12 thủ thuật. Những người chơi thắng được một mánh khóe sẽ nhận được tất cả 4 lá bài trong đó. Mỗi thẻ đều có một giá trị nhất định (ví dụ: King đếm 4, Ace đếm 11), tất cả các thẻ cùng nhau tổng cộng tối đa 240 điểm, đó là kết quả cao nhất có thể.

Kết thúc một vòng, số điểm được tính và đội có số điểm cao nhất sẽ thắng vòng đó. Rồi vòng tiếp theo bắt đầu ...

Các thách thức

Mỗi vòng có một số điểm nhất định được xác định bởi số điểm mà đội chiến thắng có được và các thông báo tiềm năng. Bạn sẽ phải viết một chương trình lấy phân phối điểm và thông báo tiềm năng (xem giải thích bên dưới) làm đầu vào và xuất điểm của vòng và người chiến thắng.

Cách tính điểm

Như đã đề cập, có một Re- và một đội Contra. Ngoài ra, có tối đa 240 điểm có thể trong một vòng. Đội Re phải giành được 121 điểm để giành chiến thắng, trong khi đội Contra chỉ cần 120. Ngoài ra còn có khả năng thông báo "Re" hoặc "Contra" khi bắt đầu vòng nếu bạn nghĩ rằng mình sẽ thắng trò chơi . Bằng cách này, bạn đang nâng cao điểm số.

Dưới đây là các quy tắc tính điểm:

  • +1 để chiến thắng trò chơi
  • +1 nếu đội thua có ít hơn 90 điểm ("Keine 90")
  • +1 nếu đội thua có ít hơn 60 điểm ("Keine 60")
  • +1 nếu đội thua có ít hơn 30 điểm ("Keine 30")
  • +1 nếu đội thua có 0 điểm ("Schwarz")
  • +2 cho một thông báo về Contra
  • +2 cho một thông báo của Re
  • +1 nếu đội Contra giành chiến thắng ("Gegen die Alten")

Lưu ý: Re / Contra-Thông báo luôn được áp dụng, bất kể người chiến thắng. Xem các ví dụ trong các thử nghiệm dưới đây.

Đầu vào và đầu ra

Đầu vào của chương trình sẽ là điểm số của Nhóm Re và các thông báo tiềm năng của Re hoặc Contra. Vì luôn có 240 điểm trong trò chơi, bạn có thể dễ dàng tính được điểm số của đội Contra.

Đầu vào sẽ là một chuỗi duy nhất có điểm số của nhóm Re trước, sau đó là các thông báo tiềm năng, trong khi "R" dành cho Re và "C" dành cho Contra. Nếu cả hai được công bố, Re sẽ luôn đến đầu tiên.

Đầu ra sẽ là số điểm của trò chơi theo sau là đội chiến thắng ("C" cho Contra, "R" cho Re)

Quy tắc

  • Trình của bạn có thể là một chương trình đầy đủ hoặc một chức năng. Nếu bạn chọn cái sau bao gồm một ví dụ về cách gọi nó.
  • Đầu vào có thể được cung cấp bởi các đối số dòng lệnh hoặc hàm hoặc đầu vào của người dùng.
  • Đầu ra có thể được cung cấp dưới dạng giá trị trả về hoặc in ra màn hình.
  • Tiêu chuẩn áp dụng.
  • Byte-Count thấp nhất sẽ thắng!

Tủ thử

Input -> Output (Explanation)

145R  -> 3R  (Re won, +1 for winning, +2 for Re-Announcement)
120   -> 2C  (Contra won, +1 for winning, +1 for winning as Contra)
80C   -> 5C  (Contra won, +1 for winning, +1 for no 90, +1 for winning as Contra, +2 for Contra-Announcement)
240R  -> 7R  (Re won, +1 for winning, +1 for no 90, +1 for no 60, +1 for no 30, +1 for no points for the losing team, +2 for Re-announcedment)
90    -> 2C  (Contra won, +1 for winning, +1 for winning as Contra)
110RC -> 6C  (Contra won, +1 for winning, +1 for winning as Contra, +2 for Re-Announcement, +2 for Contra-Announcement)
110R  -> 4C  (Contra won, +1 for winning, +1 for winnins as Contra, +2 for Re-Announcement)
184C  -> 5R  (Re won, +1 for winning, +1 for no 90, +1 for no 60, +2 for Contra-Announcement)

Lưu ý ngắn: Tôi đã bỏ qua một số quy tắc (như solo và điểm thưởng) nhằm mục đích giữ cho thử thách đơn giản. Vì vậy, nếu bạn đã quen thuộc với trò chơi, đừng nhầm lẫn :)

Chúc mừng mã hóa!

Câu trả lời:



4

Mê cung , 136 103 94 92 87 84 76 74 69 61 byte

 (}?
;)
,)
`
2
0:
 {
_-+}}82"
}"     {{"(#0/#--!.@
 -=-)}67 )

Hãy thử trực tuyến!

Ahh, đã quá lâu kể từ khi tôi sử dụng Labyrinth. Nó luôn luôn là một niềm vui để chơi nó. :)

Giải trình

Điều này là một chút lỗi thời bây giờ. Cấu trúc tổng thể của chương trình vẫn giống nhau, nhưng một vài chi tiết đã thay đổi. Tôi sẽ cập nhật điều này sau. Đây là giải pháp trước đây, để tham khảo:

 (}?
;)
,)
`
2
0 }82{_240{- ("
{ ;        #;`"~#0/#--!.@
:}-"-))}67{{
  ;#

Hãy chia nhỏ điểm số một chút:

  • Nếu chúng ta đếm các ký tự sau số trong đầu vào, hãy gọi nó M, sau đó sẽ có 2M+1điểm trong điểm số cuối cùng, để giành chiến thắng, Re và Contra.
  • Nếu số điểm là 120 hoặc ít hơn, Contra thắng và số điểm được tăng lên theo 1.
  • Nhìn vào điểm thua, chúng ta có thể (số nguyên) chia cho 30 để xác định điểm bổ sung. Điều đó có ba vấn đề mặc dù: 1. giá trị tăng theo hướng sai, vì vậy chúng ta cần trừ nó khỏi điểm số (và thêm 3 vào nó để sửa cho điều đó). 2. Điều này cho điểm bổ sung cho kết quả chính xác là 120, mà chúng ta cần loại bỏ. 3. Nó chưa xử lý kết quả bằng 0 (đối với bên thua cuộc), nhưng chúng ta có thể đưa nó vào bằng cách biến 0 thành -1 (vì phép chia số nguyên của Labyrinth sẽ làm tròn -∞).

Đó là khá nhiều cách mã hoạt động. Sp3000 đã đăng một mồi tốt cho Labyrinth ngày hôm nay, vì vậy tôi quyết định đánh cắp nó. :)

  • Labyrinth dựa trên stack và hai chiều, với việc thực thi bắt đầu từ ký tự được nhận dạng đầu tiên. Có hai ngăn xếp, ngăn xếp chính và ngăn xếp phụ, nhưng hầu hết các toán tử chỉ hoạt động trên ngăn xếp chính. Cả hai ngăn xếp đều không đáy, chứa đầy số không.
  • Tại mỗi nhánh của mê cung, đỉnh của ngăn xếp được kiểm tra để xác định nơi tiếp theo. Tiêu cực là rẽ trái, không là thẳng về phía trước và tích cực là rẽ phải.
  • Các chữ số không tự đẩy mình (như chúng làm trong Befunge,> <> hoặc Prelude) - thay vào đó chúng "nối thêm" vào đầu ngăn xếp, bằng cách nhân 10 đầu và tự thêm vào.

Vì vậy, việc thực thi bắt đầu (ở hàng đầu tiên, với con trỏ lệnh (IP) ở bên phải. (chỉ cần biến đỉnh của ngăn xếp chính thành -1}chuyển nó sang ngăn phụ, nơi chúng ta có thể quên nó. Chương trình thực sự bắt đầu với việc ?đọc số nguyên từ STDIN. IP sau đó đi vào ngõ cụt và quay lại.

}chuyển đầu vào sang ngăn xếp phụ và (giảm số 0 khác -1. Đây sẽ là điểm số cuối cùng. Bây giờ chúng ta nhập một vòng lặp theo chiều kim đồng hồ rất chặt chẽ:

;)
,)

Số điểm ))tăng lên gấp đôi (vì vậy lần đầu tiên chúng ta đi qua vòng lặp, điểm số sẽ trở thành 1, điểm số để chiến thắng). Sau đó ,đọc một ký tự. Miễn là đó không phải là EOF, vòng lặp tiếp tục. ;loại bỏ nhân vật, bởi vì chúng tôi không quan tâm nếu đó là Rhoặc C))thêm hai vào điểm số một lần nữa. Điều này sẽ lặp lại 0, 1 hoặc 2 lần tùy thuộc vào đầu vào.

Chúng tôi rời khỏi vòng lặp, khi chúng tôi đạt EOF, đỉnh của ngăn xếp sẽ là -1. Sau đó chúng tôi chạy phần tuyến tính này:

`20{:}-

`phủ định đơn phương, vì vậy chúng tôi nhận được 1, sau đó 20biến nó thành a 120. {:}lấy một bản sao của số nguyên đầu vào từ ngăn xếp phụ và -tính toán sự khác biệt với 120. Chúng ta có thể sử dụng dấu hiệu của kết quả này để xác định ai là người chiến thắng.

  1. Nếu kết quả là âm tính, Re đã thắng và chúng tôi đi theo con đường phía bắc, thực hiện:

    ;}82{_240{-#;
    

    ;loại bỏ kết quả này, }chuyển điểm số đi, 82đặt chính nó (mã ký tự R) ở dưới cùng của ngăn xếp chính, {lấy lại điểm số trên đầu, _240{-trừ đi số nguyên đầu vào từ 240 để chúng ta có thể làm việc với các điểm của Contra (mất điểm).

    Điều #;này chỉ để đảm bảo rằng chúng ta có một giá trị khác không trên ngăn xếp để chúng ta có thể tham gia cả hai đường dẫn một cách đáng tin cậy.

  2. Nếu kết quả là khả quan, Contra đã thắng và chúng tôi đi theo con đường phía nam, thực hiện:

    ;#"-))}67{{#;
    

    Việc #đẩy độ sâu ngăn xếp đó là 1. Điều này được trừ vào điểm số trước khi chúng tôi thêm 2với )). 67đặt chính nó (mã ký tự của C) ở dưới cùng của ngăn xếp chính. {{lấy lại các giá trị khác

  3. Nếu kết quả bằng 0, Contra vẫn thắng. Tuy nhiên, đó là trường hợp 120/120 mà chúng tôi cần thêm một điểm phụ vào điểm số cuối cùng (xem ở trên). Đó là lý do tại sao đường dẫn này không đẩy 1 với #, nhưng thay vào đó chỉ để lại số 0 sao cho -đơn giản là loại bỏ số 0 đó khỏi ngăn xếp.

Các ngăn xếp bây giờ được nối lại với nhau và chúng tôi đã tính tất cả mọi thứ trừ phần chúng tôi chia cho 30. Nhưng trước tiên, chúng tôi cần biến điểm 0 thành -1. Đó là những gì đường vòng nhỏ này làm:

("
`"~

Các `không ảnh hưởng đến một số không, "là một không-op và ~là Bitwise phủ. Bitwise KHÔNG của 0-1theo yêu cầu. Nếu điểm số là tích cực thay vào đó, sau đó `làm cho nó âm tính, (giảm nó bằng 1~hoàn tác cả hai thao tác đó trong một lần.

#0/#--!.@

Độ sâu ngăn xếp bây giờ là 3 (nhân vật chiến thắng, tổng số điểm cho đến nay và số điểm bị mất), do đó #đẩy mạnh 3. 0biến nó thành một 30, /không phân chia. #đẩy người khác 3bị trừ và kết quả đó lần lượt bị trừ khỏi điểm số cuối cùng. !in nó dưới dạng một số nguyên, .in bên chiến thắng dưới dạng ký tự và @chấm dứt chương trình.


3

JavaScript (ES6), 106

Khoảng 100 byte với ngôn ngữ không chơi gôn.

x=>([,r,t]=x.match`(\\d+)(.*)`,t=1+t.length*2,w=r>120?(r=240-r,'R'):(++t,'C'),t+!r+(r<30)+(r<60)+(r<90)+w)

Kiểm tra

f=x=>(
  [,r,t]=x.match`(\\d+)(.*)`,
  t=1+t.length*2,
  w=r>120?(r=240-r,'R'):(++t,'C'),
  t+!r+(r<30)+(r<60)+(r<90)+w
)

console.log=x=>O.textContent+=x+'\n'

test=[
['145R', '3R'], //(Re won, +1 for winning, +2 for Re-Announcement)
['120',  '2C'], //(Contra won, +1 for winning, +1 for winning as Contra)
['80C',  '5C'], //(Contra won, +1 for winning, +1 for no 90, +1 for winning as Contra, +2 for Contra-Announcement)
['240R', '7R'], //(Re won, +1 for winning, +1 for no 90, +1 for no 60, +1 for no 30, +1 for no points for the losing team, +2 for Re-announcedment)
['90',   '2C'], //(Contra won, +1 for winning, +1 for winning as Contra)
['110RC','6C'], //(Contra won, +1 for winning, +1 for winning as Contra, +2 for Re-Announcement, +2 for Contra-Announcement)
['110R', '4C'], //(Contra won, +1 for winning, +1 for winnins as Contra, +2 for Re-Announcement)
['184C', '5R'], //(Re won, +1 for winning, +1 for no 90, +1 for no 60, +2 for Contra-Announcement)
]
  
test.forEach(t=>{
  var i=t[0],k=t[1],r=f(i)
console.log((k==r?'OK ':'KO ')+i+' -> '+r+(k!=r?' (expected: '+k+')':''))
})
<pre id=O></pre>


Chỉ khoảng hai lần số byte của câu trả lời CJam ... không tệ ^^
Denker

2

ES6, 92 byte

s=>(p=s.match(/\d+|./g),n=+p[0],r=n>120,p.length*2-r+!(n%120)+3-((r?240-n:n)/30|0)+"CR"[+r])

p.length*2đánh giá quá cao điểm số 1 nếu Re thắng nên tôi phải trừ rlại. !(n%120)+3-((r?240-n:n)/30|0)là những gì tôi nghĩ ra để gói gọn các quy tắc cho điểm "Keine"; Tôi rất mong muốn các ranh giới là 31, 61 và 91 vì điều đó sẽ tạo ra công thức 4-((r?269-n:29+n)/30|0).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.