Pokerface
Giới thiệu
Leo thích chơi bài xì phé, nhưng công việc của anh tại Tech Inc. quá khắt khe để anh học cách chơi tốt. Leo, là một nhà khoa học máy tính, không nản lòng. Anh ta quyết định mất nhiều thời gian hơn là chỉ học poker, và sử dụng nó để viết bot poker để giúp anh ta chơi tốt hơn. Nhưng bây giờ Leo có một vấn đề: để hiểu cách chơi tốt hơn một chút, Leo cần quan sát nhiều trò chơi của nhiều "người", nhưng "mọi người" cần các cách chơi khác nhau để cải thiện chất lượng và tính thực tế của trò chơi.
Các thách thức
Leo nhớ lại rằng thực sự có một trang web dành riêng cho các thử thách lập trình và đang tranh thủ sự giúp đỡ của bạn! Công việc của bạn là viết một chương trình chơi "Pokerface" một phiên bản sửa đổi của bài xì phé 5 lá. Chương trình sẽ lấy đầu vào dưới dạng tay 5 thẻ theo bất kỳ định dạng nào bạn muốn, sau đó chương trình sẽ xuất ra:
- Chính xác (phân biệt chữ hoa chữ thường) "đúng" "1" hoặc "t" nếu người chơi muốn trao đổi thẻ, bất kỳ đầu ra không trống nào khác.
- Nếu đúng, danh sách các chỉ số của thẻ và / hoặc tên thẻ mà người chơi muốn trao đổi.
- Một số duy nhất trong khoảng từ 0 đến 3, xác định số lượng thẻ bổ sung mà người chơi muốn.
- In ra tay người chơi muốn sử dụng.
(Xem định dạng bên dưới)
Quy tắc chơi bài
- Vì pokerface là một trò chơi phiêu lưu dựa trên văn bản, thẻ phải được trình bày một cách nhất quán. Thẻ được thể hiện bằng hai mã ký tự, ký tự đầu tiên là phù hợp và thứ hai là tên của thẻ.
- Thẻ:
- 2-9 = 2-9
- 10 = T
- Jack = J
- Nữ hoàng = Q
- Vua = K
- Ace = A
- Bộ quần áo:
- Spades = S
- Câu lạc bộ = C
- Trái tim = H
- Kim cương = D
- Thẻ:
Vì vậy, ace of spades sẽ là SA, 10 trái tim là HT, thứ 4 của kim cương là D4, v.v.
- Một vòng Pokerface duy nhất bao gồm bốn bước:
- Bộ bài được chia sẻ lại và một tay bài năm lá được chia cho mỗi người chơi.
- Mỗi người chơi được trao cơ hội trao đổi bao nhiêu thẻ tùy thích.
- Mỗi người chơi được trao cơ hội nhận thêm tối đa ba thẻ.
- Mỗi người chơi phải tiết lộ bàn tay tốt nhất của họ.
- Tay tốt nhất sẽ thắng, và giành được điểm đó cho người chơi đó. Trong trường hợp hòa, cả hai người chơi được một điểm.
- Trong một trò chơi, mười vòng được chơi và người chơi có nhiều điểm nhất sẽ thắng và giành được một "điểm chiến thắng" duy nhất. Trong trường hợp hòa, cả hai người chơi đều giành được điểm thắng.
- Leo không thực sự có một số tiền lớn, vì vậy bot của bạn có thể cho rằng đây là một thế giới hoàn hảo không có cá cược.
Tay
- Tay có độ dài chính xác là 5 thẻ (đầu vào ban đầu và đầu ra cuối cùng).
- Tay được xếp hạng phù hợp với các quy tắc được mô tả ở đây .
Đầu ra đầu vào
- Leo chỉ biết Java, vì vậy chương trình của bạn phải được thực thi thông qua API quy trình (dòng lệnh) và sử dụng STDIN và STDOUT cho đầu vào và đầu ra, tương ứng.
- Đối với mỗi bước đầu vào và đầu ra chi tiết ở trên, mỗi đầu vào và đầu ra phải tồn tại trên một dòng.
- Phải có ít nhất một dòng mới sau đầu ra cuối cùng. (Điều này là do cách đọc đầu vào từ STDIN)
- Không cho phép đầu vào / đầu ra bên ngoài, ngoại trừ dấu cách và khoảng trắng hàng đầu. Trình phân tích cú pháp đơn giản là không hiểu những thứ như
final_hand=...
hoặcdraw 0
. - Khi vẽ, đầu ra là một số nguyên duy nhất, khi đầu ra trao đổi là một danh sách các số nguyên và / hoặc thẻ được xác định bên dưới và khi được xử lý bàn tay ban đầu, đầu ra là một danh sách các thẻ được xác định bên dưới.
- Tất cả các số đầu vào / đầu ra phải là số nguyên dương trong cơ sở 10.
- Bạn có thể xác định định dạng cho đầu vào thẻ (xem định dạng bài bên dưới).
- True được định nghĩa chính xác là "true", "1" hoặc "t" và false là bất kỳ giá trị không trống nào khác.
- Trong bước trao đổi:
- Các chỉ số thẻ phải là đầu ra có ít nhất một khoảng trắng giữa chúng (ví dụ
3 4 0
) - Tên thẻ phải được xuất ra với ít nhất một khoảng trắng giữa chúng (ví dụ
H4 S8
) - Tên thẻ và chỉ số có thể được trộn lẫn trong đầu ra (ví dụ
0 H7 3 D3
) - Trailing và không gian hàng đầu được cho phép.
- Đầu vào là kết quả của trình phát xuất ra ở trên sẽ được định dạng theo chỉ định của
bot.jlsc
tệp, theo đúng thứ tự như yêu cầu
- Các chỉ số thẻ phải là đầu ra có ít nhất một khoảng trắng giữa chúng (ví dụ
- Số lượng thẻ mà người chơi muốn thêm vào tay họ có thể có khoảng trắng ở đầu và cuối.
- Tay phải là đầu ra có ít nhất một
H4 D5 CA
khoảng trắng giữa chúng (ví dụ ), khoảng trắng ở cuối và khoảng trắng ở đầu được cho phép. - Tay không cần phải xuất ra theo đúng thứ tự (ví dụ
H4 D4 C4 DA SA
vàH4 DA D4 SA C4
cả hai đại diện cho 4, 4, 4, Ace, Ace, là một ngôi nhà đầy đủ). - Nếu bạn muốn xây dựng chiến lược bằng cách phân tích tay đối thủ, bạn có thể lưu trữ dữ liệu trong một
<botname>/data
thư mục.- Sau khi các bot cạnh tranh đã hiển thị bàn tay của chúng, chúng sẽ được ghi vào mọi thư mục dữ liệu của bot, trong hand.txt, với mỗi tay trên một dòng mới (cách nhau bởi \ n). Tập tin sẽ được mã hóa bằng US_ASCII.
- Sau khi bot của bạn yêu cầu thẻ mới hoặc thẻ trao đổi, thẻ sẽ được nhập tùy thuộc vào định dạng bạn chỉ định trong
bot.jlsc
tệp.
Định dạng bài
- Mỗi bài đăng phải bao gồm hai điều:
- Mã nguồn của bot của bạn hoặc liên kết đến kho lưu trữ công khai.
- Một tệp zip chứa:
- Phiên bản được biên dịch / thực thi của bot của bạn (Nếu tệp là tệp .exe hoặc tệp không thể biên dịch khác, vui lòng chỉ bao gồm các hướng dẫn biên dịch trong bài đăng của bạn).
- Một
bot.jlsc
tệp, xem bên dưới (ghi chú bên: phần mở rộng .jlsc chỉ vì một dự án phụ của tôi, định dạng cấu hình. Tệp bên dưới khớp với cú pháp thích hợp, vì vậy đừng lo lắng).
- Tệp .zip phải được đặt tên giống như bot của bạn.
- Nếu bạn không có quyền truy cập vào windows hoặc một số tiện ích nén khác hoặc không thể tạo .zip vì bất kỳ lý do gì, chỉ cần đưa văn bản của tệp bot.jlsc vào bài đăng của bạn
tập tin bot.jlsc:
name= "Botty"
link= "example.com"
cmd= "java -jar Botty.jar"
input_hand= "${0} ${1} ${2} ${3} ${4}"
input_1= "${0}"
input_2= "${0} ${1}"
input_3= "${0} ${1} ${2}"
input_4= "${0} ${1} ${2} ${3}"
Ở đâu:
- "cmd" là lệnh dòng lệnh windows để chạy bot của bạn. Lưu ý rằng bot của bạn sẽ nằm trong thư mục
<botname>
, vì vậy hãy điều chỉnh lệnh cho phù hợp. - "Tên" là tên của bot của bạn.
- "Liên kết" là liên kết đến câu trả lời của bạn, bạn sẽ phải chỉnh sửa nội dung này sau khi đăng.
- "input_hand" là cách bạn muốn giao dịch gốc được định dạng (với $ {#} đại diện cho thẻ 0-4).
- "input_1" là cách bạn muốn đầu vào của một thẻ bổ sung được định dạng.
- "input_2" là cách bạn muốn đầu vào của hai thẻ bổ sung được định dạng.
- "input_3" là cách bạn muốn đầu vào của ba thẻ bổ sung được định dạng.
- "input_4" là cách bạn muốn đầu vào của bốn thẻ bổ sung được định dạng.
Cụ thể
- Những sơ hở này không được phép (xem 'cạm bẫy chung')
- Bạn không thể viết bot, sẽ luôn xuất ra bàn tay tốt nhất có thể, mọi lúc, trong bộ quy tắc. (tức là không có bot vũ phu chạy dài, không có gì nên 'tốt' như LeoBot)
- Bot của bạn nên chạy trong ~ 100 ms hoặc ít hơn (Lenient vào thời điểm này, tối đa ~ 1 giây)
- Bất kỳ đầu ra nào của bot sau bàn tay đã chọn sẽ bị bỏ qua.
- Sơ hở tiêu chuẩn là không được phép.
- Vâng, tôi biết linux tốt hơn, nhưng tôi có PC Windows, vì vậy hãy chắc chắn rằng phiên bản được biên dịch / thực thi của chương trình của bạn có thể được chạy từ dòng lệnh windows.
- Tôi đã cài đặt python và java trên máy tính của mình, nhưng tôi sẵn sàng cập nhật lên các phiên bản mới và cài đặt các môi trường khác, vì vậy vui lòng chỉ định loại môi trường mà chương trình của bạn yêu cầu.
- Bạn không thể viết một bot làm điều tương tự như một bot khác trong mọi trường hợp. Bot rác được cho phép, nhưng không khuyến khích.
- Bot của bạn chỉ có thể sử dụng thẻ mà nó có. Thẻ bị mất thông qua trao đổi hoặc không được xử lý để bắt đầu là đầu ra không hợp lệ trong tay cuối cùng.
- Đầu vào và đầu ra chỉ có thể chứa các ký tự ASCII.
Giải đấu
- Các giải đấu sẽ được tổ chức khi tôi có thời gian (lịch trình của tôi gần như chật cứng như của Leo, vì vậy đây là một chút không thường xuyên. Xin lỗi vì sự bất tiện này.).
- Bots sẽ là hố đối đầu với nhau trong các trò chơi 4 người, và sẽ có một trò chơi cho mỗi tập hợp con có thể có của bot (tức là rất nhiều trò chơi).
- Quá trình này sẽ được lặp lại năm lần.
- Do cách người xử lý giải đấu tạo ra các nhóm bot, tối đa ba bot phụ sẽ được thêm vào để làm cho số lượng bot chia hết cho 4. Những bot này sẽ trả lại bàn tay mà chúng đã xử lý ban đầu.
- Sau mỗi vòng và trò chơi được chạy, điểm số của các bot sẽ được tính dựa trên số trò chơi mà chúng giành được.
- Nhiều bot có thể chia sẻ một vị trí (mối quan hệ cho chiến thắng đầu tiên được đăng lần đầu tiên).
- Sau khi một giải đấu kết thúc, điểm số sẽ được thêm vào cuối bài này.
Chấm điểm
Quy tắc KoTH bình thường. Các bot chiến thắng hầu hết các trò chơi sẽ chiến thắng thử thách.
LeoBot
Bot của Leo khá thông minh. Nó không trao đổi bất kỳ thẻ nào, quá khó, nhưng nó yêu cầu số lượng thẻ bổ sung tối đa và nó xác định tay tốt nhất có thể làm được và chơi tay đó. Logic chính của leobot là dưới đây.
package com.gmail.socraticphoenix.pokerface.leobot;
import com.gmail.socraticphoenix.pokerface.lib.card.Card;
import com.gmail.socraticphoenix.pokerface.lib.card.Deck;
import com.gmail.socraticphoenix.pokerface.lib.rule.HandRegistry;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class LeoBot {
public static void main(String[] args) {
List<Card> hand = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
hand.addAll(Card.parseHand(scanner.nextLine()));
System.out.println(false);
System.out.println(3);
hand.addAll(Card.parseHand(scanner.nextLine()));
List<List<Card>> possibleHands = LeoBot.getSubsets(hand, 5);
System.out.println(Deck.toString(possibleHands.stream().sorted((a, b) -> HandRegistry.determineWinner(b, a).comparable()).findFirst().get()));
}
private static <T> void getSubsets(List<T> superSet, int k, int idx, List<T> current, List<List<T>> solution) {
if (current.size() == k) {
solution.add(new ArrayList<>(current));
return;
}
if (idx == superSet.size()) return;
T x = superSet.get(idx);
if (!current.contains(x)) {
current.add(x);
}
getSubsets(superSet, k, idx + 1, current, solution);
current.remove(x);
getSubsets(superSet, k, idx + 1, current, solution);
}
public static <T> List<List<T>> getSubsets(List<T> superSet, int k) {
List<List<T>> res = new ArrayList<>();
getSubsets(superSet, k, 0, new ArrayList<T>(), res);
return res;
}
}
Lưu ý rằng nếu LeoBot liên tục chiến thắng các giải đấu và có một số lượng tốt các mục, tôi sẽ ngừng bao gồm anh ta trong cuộc chạy.
Liên kết quan trọng
Khước từ
Leo và Tech Inc. là những yếu tố câu chuyện và bất kỳ sự tương đồng nào với các công ty hoặc người thực tế hoàn toàn là vô tình. (Tuy nhiên, khi 'tình huống' của Leo thêm hoặc bớt các điều kiện khỏi câu hỏi, đó thực sự là một phần của câu hỏi ...)
"f"q+
đáp ứng các yêu cầu tối thiểu. Nếu có 10 người trong cuộc thi, điều này có thể đánh bại tất cả các mục không câm (mục không phải là câm có thể có> 75 ký tự, 5 * 10 (điểm số của bot câm, sắp tới) = 50 <75 (điểm của bot thông minh rất nhỏ (đến trước))). Do đó, có lẽ bạn nên loại bỏ codegolf khỏi thử thách này