Pokerface
บทนำ
เลโอสนุกกับการเล่นโป๊กเกอร์ แต่งานของเขาที่ Tech Inc. นั้นเรียกร้องเกินกว่าที่เขาจะเรียนรู้วิธีเล่นได้ดี เลโอเป็นนักวิทยาศาสตร์คอมพิวเตอร์ไม่ท้อถอย เขาตัดสินใจที่จะใช้เวลามากกว่าที่จะเรียนรู้โป๊กเกอร์และใช้มันเพื่อเขียนบอทโป๊กเกอร์เพื่อช่วยให้เขาเล่นได้ดีขึ้น แต่ตอนนี้ลีโอมีปัญหา: เพื่อที่จะเข้าใจวิธีการเล่นให้ดีขึ้นเลโอต้องสังเกตหลาย ๆ เกมของ "คน" หลายคน แต่ "คน" ต้องการสไตล์การเล่นที่แตกต่างกันเพื่อปรับปรุงคุณภาพและความเป็นจริงของเกม
ความท้าทาย
ลีโอเล่าว่ามีเว็บไซต์ที่ทุ่มเทให้กับการเขียนโปรแกรมท้าทายและขอความช่วยเหลือจากคุณ! งานของคุณคือการเขียนโปรแกรมที่เล่น "Pokerface" เป็นไพ่โป๊กเกอร์แบบ 5 ใบที่ปรับเปลี่ยนแล้ว โปรแกรมจะรับอินพุตเป็นไพ่ 5 ใบในรูปแบบที่คุณต้องการหลังจากนั้นโปรแกรมจะแสดงผล:
- แน่นอน (ตรงตามตัวพิมพ์ใหญ่ - เล็ก) "จริง" "1" หรือ "t" หากผู้เล่นต้องการแลกเปลี่ยนไพ่อื่น ๆ ที่ไม่ว่างเปล่าเป็นอย่างอื่น
- หากเป็นจริงรายการของดัชนีของการ์ดและ / หรือชื่อการ์ดที่ผู้เล่นต้องการแลกเปลี่ยน
- ตัวเลขเดี่ยวระหว่าง 0 และ 3 ซึ่งระบุจำนวนบัตรเพิ่มเติมที่ผู้เล่นต้องการ
- พิมพ์มือที่ผู้เล่นต้องการใช้
(ดูรูปแบบด้านล่าง)
กฎ Pokerface
- เนื่องจาก pokerface เป็นเกมผจญภัยแบบข้อความคุณต้องแสดงการ์ดในลักษณะที่สอดคล้องกัน ไพ่จะถูกแทนด้วยรหัสตัวละครสองตัวตัวแรกคือชุดสูทและตัวที่สองคือชื่อของการ์ด
- การ์ด:
- 2-9 = 2-9
- 10 = T
- แจ็ค = เจ
- ราชินี = Q
- King = K
- Ace = A
- ชุด:
- Spades = S
- สโมสร = C
- หัวใจ = H
- เพชร = D
- การ์ด:
เอซโพดำก็คือ SA, 10 ดวงคือ HT, อันดับ 4 ของเพชรคือ D4, เป็นต้น
- Pokerface รอบเดียวประกอบด้วยสี่ขั้นตอน:
- สำรับได้รับการปรับโฉมใหม่และไพ่ห้าใบแจกให้ผู้เล่นแต่ละคน
- ผู้เล่นแต่ละคนจะได้รับโอกาสในการแลกเปลี่ยนการ์ดได้มากเท่าที่พวกเขาต้องการ
- ผู้เล่นแต่ละคนจะได้รับโอกาสในการได้รับไพ่เพิ่มอีกสามใบ
- ผู้เล่นแต่ละคนจะต้องเปิดเผยมือที่ดีที่สุดของพวกเขา
- มือที่ดีที่สุดชนะและได้รับคะแนนผู้เล่นคนนั้น ในกรณีที่เสมอกันผู้เล่นทั้งสองจะได้รับแต้ม
- ในเกมเดียวจะมีการเล่นสิบรอบและผู้เล่นที่มีคะแนนมากที่สุดจะเป็นผู้ชนะและได้รับ "win point" เพียงหนึ่งเดียว ในกรณีที่เสมอกันผู้เล่นทั้งสองจะได้รับคะแนนชนะ
- ลีโอไม่มีเงินจำนวนมากจริงๆดังนั้น ธ ปท. ของคุณสามารถสันนิษฐานได้ว่านี่เป็นโลกที่สมบูรณ์แบบโดยไม่มีการเดิมพัน
มือ
- มือมีความยาวไพ่ 5 ใบอย่างแน่นอน (อินพุตเริ่มต้นและเอาต์พุตสุดท้าย)
- มือมีการจัดอันดับความสอดคล้องกับกฎที่อธิบายไว้ที่นี่
อินพุต / เอาต์พุต
- Leo รู้เฉพาะ Java เท่านั้นดังนั้นโปรแกรมของคุณจะต้องสามารถเรียกใช้งานได้ผ่านProcess API (บรรทัดคำสั่ง) และใช้ STDIN และ STDOUT สำหรับอินพุตและเอาต์พุตตามลำดับ
- สำหรับแต่ละขั้นตอนของอินพุตและเอาต์พุตที่มีรายละเอียดด้านบนแต่ละอินพุตและเอาต์พุตต้องมีอยู่ในหนึ่งบรรทัด
- ต้องมีบรรทัดใหม่ต่อท้ายอย่างน้อยหนึ่งบรรทัดหลังจากเอาต์พุตสุดท้าย (นี่เป็นเพราะวิธีการอ่านอินพุตจาก STDIN)
- ไม่อนุญาตอินพุต / เอาท์พุตภายนอกนอกเหนือจากช่องว่างต่อท้ายและช่องว่างนำหน้า ตัวแยกวิเคราะห์เพียงแค่ไม่เข้าใจสิ่งที่ต้องการหรือ
final_hand=...
draw 0
- เมื่อการวาดภาพเอาต์พุตเป็นจำนวนเต็มเดียวเมื่อการแลกเปลี่ยนเอาต์พุตเป็นรายการจำนวนเต็มและ / หรือการ์ดที่กำหนดไว้ด้านล่างและเมื่อมีการแจกไพ่ดั้งเดิมมือเอาท์พุทคือรายการของการ์ดที่กำหนดไว้ด้านล่าง
- หมายเลขอินพุต / เอาต์พุตทั้งหมดต้องเป็นจำนวนเต็มบวกในฐาน 10
- คุณสามารถกำหนดรูปแบบสำหรับอินพุตของการ์ด (ดูรูปแบบโพสต์ด้านล่าง)
- True ถูกกำหนดเป็น "true," "1" หรือ "t" อย่างแน่นอนและ false เป็นค่าอื่น ๆ ที่ไม่ว่างเปล่า
- ระหว่างขั้นตอนการแลกเปลี่ยน:
- ดัชนีของการ์ดจะต้องส่งออกอย่างน้อยหนึ่งช่องว่างระหว่างพวกเขา (เช่น
3 4 0
) - ชื่อบัตรจะต้องถูกส่งออกอย่างน้อยหนึ่งช่องว่างระหว่างพวกเขา (เช่น
H4 S8
) - ชื่อและดัชนีของการ์ดอาจผสมกันในเอาท์พุท (เช่น
0 H7 3 D3
) - อนุญาตให้ใช้ช่องว่างส่วนท้ายและส่วนหน้า
- อินพุตที่เป็นผลมาจากผู้เล่นที่เอาท์พุทข้างต้นจะถูกฟอร์แมทตามที่ระบุโดย
bot.jlsc
ไฟล์ตามลำดับที่ร้องขอ
- ดัชนีของการ์ดจะต้องส่งออกอย่างน้อยหนึ่งช่องว่างระหว่างพวกเขา (เช่น
- จำนวนไพ่ที่ผู้เล่นต้องการเพิ่มในมือสามารถมีช่องว่างนำหน้าและต่อท้ายได้
- มือจะต้องถูกส่งออกอย่างน้อยหนึ่งช่องว่างระหว่างพวกเขา (เช่น
H4 D5 CA
) ช่องว่างต่อท้ายและช่องว่างนำ - มือไม่จำเป็นต้องส่งออกในลำดับที่เหมาะสม (เช่น
H4 D4 C4 DA SA
และH4 DA D4 SA C4
ทั้งสองเป็นตัวแทน 4, 4, 4, Ace, Ace ซึ่งเป็นบ้านเต็มรูปแบบ) - หากคุณต้องการสร้างกลยุทธ์โดยการวิเคราะห์ฝ่ายตรงข้ามคุณอาจเก็บข้อมูลไว้ใน
<botname>/data
ไดเรกทอรี- หลังจากบอทที่แข่งขันแสดงมือของพวกเขาแล้วพวกเขาจะถูกเขียนไปยังทุกไดเรกทอรีข้อมูลบอทใน hands.txt โดยแต่ละมือในบรรทัดใหม่ (คั่นด้วย \ n) ไฟล์จะถูกเข้ารหัสใน US_ASCII
- หลังจากบอทของคุณร้องขอการ์ดใหม่หรือการ์ดแลกเปลี่ยนการ์ดจะถูกป้อนขึ้นอยู่กับรูปแบบที่คุณระบุใน
bot.jlsc
ไฟล์
รูปแบบโพสต์
- โพสต์ทุกคนจะต้องมีสองสิ่ง:
- ซอร์สโค้ดของบ็อตของคุณหรือลิงก์ไปยังที่เก็บข้อมูลสาธารณะ
- ไฟล์ zip ที่มี:
- บอทของคุณที่คอมไพล์หรือรันได้ (หากไฟล์นั้นเป็นไฟล์. exe หรือไฟล์ที่ไม่สามารถคอมไพล์ได้โปรดใส่คำแนะนำในการคอมไพล์ในโพสต์ของคุณ)
bot.jlsc
ไฟล์ดูด้านล่าง (หมายเหตุด้าน: ขยาย .jlsc เป็นเพียงเพราะด้านหนึ่งของโครงการเหมือง, รูปแบบการตั้งค่าไฟล์ด้านล่างที่ตรงกันไวยากรณ์ที่เหมาะสมดังนั้นไม่ต้องกังวล.)
- ไฟล์. zip ต้องตั้งชื่อเหมือนกับ bot ของคุณ
- หากคุณไม่สามารถเข้าถึง windows หรือยูทิลิตี้การซิปอื่น ๆ หรือไม่สามารถทำการ. zip ด้วยเหตุผลใดก็ตามเพียงแค่ใส่ข้อความของไฟล์ bot.jlsc ในโพสต์ของคุณ
ไฟล์ 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}"
ที่ไหน:
- "cmd" เป็นคำสั่งwindows command line เพื่อเรียกใช้ bot ของคุณ โปรดทราบว่าบอทของคุณจะอยู่ในไดเรกทอรี
<botname>
ดังนั้นปรับคำสั่งให้เหมาะสม - "name" คือชื่อบอทของคุณ
- "link" เป็นลิงค์ไปยังคำตอบของคุณคุณจะต้องแก้ไขในหลังจากโพสต์
- "input_hand" เป็นวิธีที่คุณต้องการให้รูปแบบการทำธุรกรรมดั้งเดิม (มี $ {#} แสดงถึงบัตร 0-4)
- "input_1" เป็นวิธีที่คุณต้องการให้อินพุตการ์ดเพิ่มเติมหนึ่งแผ่นถูกจัดรูปแบบ
- "input_2" เป็นวิธีที่คุณต้องการให้ฟอร์แมตการ์ดเพิ่มเติมสองใบ
- "input_3" เป็นวิธีที่คุณต้องการให้ฟอร์แมตการ์ดเพิ่มเติมสามใบ
- "input_4" เป็นวิธีที่คุณต้องการให้ฟอร์แมตการ์ดเพิ่มเติมอีกสี่การ์ด
ข้อมูลจำเพาะ
- ช่องโหว่เหล่านี้ไม่ได้รับอนุญาต (ดู 'ข้อผิดพลาดทั่วไป')
- คุณไม่สามารถเขียนบอทที่จะส่งออกมือที่ดีที่สุดที่เป็นไปได้ทุกครั้งภายในชุดกฎ (เช่นไม่มีบ็อตเดรัจฉานที่ใช้กำลังนานไม่ควรมีอะไรที่ 'ดี' เท่า LeoBot มากนัก)
- บอทของคุณควรทำงานใน ~ 100 ms หรือน้อยกว่า (ผ่อน ณ จุดนี้สูงสุด ~ 1 วินาที)
- ผลลัพธ์ของบอทหลังจากมือที่เลือกจะถูกละเว้น
- ช่องโหว่มาตรฐานไม่ได้รับอนุญาต
- ใช่ฉันรู้ว่า linux นั้นดีกว่า แต่ฉันมี windows PC ดังนั้นโปรดตรวจสอบให้แน่ใจว่าโปรแกรมของคุณสามารถคอมไพล์ / รันได้จากคอมไพล์บรรทัดคำสั่ง windows
- ฉันได้ติดตั้งไพ ธ อนและ Java ไว้ในคอมพิวเตอร์แล้ว แต่ฉันยินดีที่จะอัปเดตเป็นเวอร์ชันใหม่และติดตั้งสภาพแวดล้อมอื่น ๆ ดังนั้นโปรดระบุประเภทของสภาพแวดล้อมที่โปรแกรมของคุณต้องการ
- คุณไม่สามารถเขียนบอทที่ทำสิ่งเดียวกันกับบอทอื่นในทุกกรณี อนุญาตบอทสแปม แต่ไม่สนับสนุน
- บอทของคุณอาจใช้การ์ดที่มีเท่านั้น ไพ่ที่หายไปจากการแลกเปลี่ยนหรือไม่ได้รับการจัดการเพื่อเริ่มต้นนั้นเป็นเอาท์พุทที่ไม่ถูกต้องในมือสุดท้าย
- อินพุตและเอาต์พุตอาจมีอักขระ ASCII ได้เท่านั้น
ทัวร์นาเมนต์
- ทัวร์นาเมนต์จะถูกเรียกใช้เมื่อฉันมีเวลา (ตารางงานของฉันเกือบจะเต็มไปด้วยเลโอดังนั้นนี่จะเป็นเวลาที่ฉันไม่บ่อยนักขออภัยในความไม่สะดวก)
- บอทจะเป็นหลุมต่อแต่ละคนในเกม 4 คนและจะมีหนึ่งเกมสำหรับแต่ละเซตย่อยของบอทที่เป็นไปได้ (เช่นเกมจำนวนมาก)
- กระบวนการนี้จะทำซ้ำห้าครั้ง
- เนื่องจากวิธีที่ผู้จัดการทัวร์นาเมนต์สร้างกลุ่มของบ็อตจะมีการเพิ่มบ็อตฟิลเลอร์มากถึงสามตัวเพื่อทำให้จำนวนของบอทหารด้วย 4 บอทเหล่านี้จะส่งคืนมือที่จัดการเดิม
- หลังจากทุกรอบและเล่นเกมแล้วคะแนนของบอตจะคำนวณตามจำนวนเกมที่ชนะ
- บอตหลายตัวสามารถแชร์ตำแหน่งได้ (ความสัมพันธ์สำหรับการชนะครั้งแรกโดยโพสต์ครั้งแรก)
- หลังจากการแข่งขันเสร็จสิ้นคะแนนจะถูกผนวกเข้าที่ด้านล่างของโพสต์นี้
เกณฑ์การให้คะแนน
กฎ KoTH ปกติ บอทที่ชนะการแข่งขันมากที่สุดชนะการท้าทาย
LeoBot
บอทของลีโอเป็นคนฉลาด มันไม่ได้แลกเปลี่ยนไพ่ใด ๆ ที่ยากเกินไป แต่จะขอจำนวนสูงสุดของการ์ดเพิ่มเติมและจะกำหนดมือที่ดีที่สุดเท่าที่จะทำได้และเล่นมือนั้น ตรรกะหลักของ leobot อยู่ด้านล่าง
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;
}
}
โปรดทราบว่าหาก LeoBot ชนะการแข่งขันอย่างต่อเนื่องและมีจำนวนรายการที่ดีฉันจะหยุดรวมถึงเขาในการวิ่ง
ลิงค์สำคัญ
คำปฏิเสธ
Leo และ Tech Inc. เป็นองค์ประกอบเรื่องราวและมีความคล้ายคลึงกับ บริษัท หรือคนในชีวิตจริงโดยไม่ได้ตั้งใจ (อย่างไรก็ตามเมื่อ 'สถานการณ์' ของลีโอเพิ่มหรือลบเงื่อนไขออกจากคำถามเหล่านั้นจะเป็นส่วนหนึ่งของคำถาม ... )
"f"q+
ตอบสนองความต้องการขั้นต่ำ หากมีผู้แข่งขัน 10 คนน่าจะชนะรายการที่ไม่ใช่แบบโง่ทั้งหมด (รายการที่ไม่ใช่แบบโง่อาจมี> 75 ตัวอักษร 5 * 10 (คะแนนแบบบอทโง่มาครั้งสุดท้าย) = 50 <75 (คะแนนบอทอัจฉริยะขนาดเล็กมาก (มาก่อน))) ดังนั้นคุณน่าจะลบ codegolf ออกจากการแข่งขันนี้