비 Java 제출을위한 랩퍼
참고 MAP_SIZE 지원이 추가되었습니다. 당신이 관심이 있다면, 그에 따라 제출을 업데이트하십시오.
이것은 랩퍼를위한 커뮤니티 위키 항목으로, 게임을하고 싶지만 Java를 모르거나 알지 못하는 사람들이 사용할 수 있습니다. 사용 하시고 재미있게 보내 주시고 기꺼이 도와 드리겠습니다.
마무리 할 때 여기에 늦었습니다. 다른 Java 코더는 이것을 살펴보고 개선을 제안하십시오. 가능하면 문제를 제기하거나 패치를 제출하여 github 리포지토리를 통해 수행하십시오. 감사!
이 전체가 UNLICENSE와 함께 배포되고 있으므로 github 저장소에서 추적 하십시오 . 문제가 발견되면 패치를 제출하고이 게시물을 업데이트하겠습니다.
사용중인 래퍼의 현재 예
plannapus : R의 WolfCollectiveMemory
칫솔 : ECMAScript의 칫솔
사용하는 방법
다음은 원격 늑대에 대해 정의한 PIPES를 통한 프로세스 간 통신 프로토콜에 대한 지침입니다. 참고 OP의 문제 설명에 존재하지만 존재하지 않는 것처럼 MAP_SIZE를 건너 뛰었습니다. 표시되면이 게시물을 업데이트하겠습니다.
중요 사항 :
- 외부 프로세스를 한 번만 호출 할 수 있습니다 (따라서 처리 논리를 무한 루프로 랩핑하십시오. 또한 디스크를 사용하는 대신 처리를 인 메모리로 유지할 수 있습니다).
- 모든 통신은 STDIN 및 STDOUT을 통한이 단일 외부 프로세스와의 통신
- STDOUT으로 전송 된 모든 출력을 명시 적으로 플러시하고 줄 바꿈으로 끝나야합니다.
사양
원격 스크립트는 STDIN 및 STDOUT 후크를 통한 간단한 프로토콜에 의해 지원되며 초기화, 이동 및 공격으로 나뉩니다. 각 경우에 귀하의 프로세스와의 통신은 STDIN을 통해 이루어지며 STDOUT으로부터 회신이 필요합니다. 1 초 안에 회신을받지 못하면 프로세스가 종료 된 것으로 간주되어 예외가 발생합니다. 일관성을 유지하기 위해 모든 문자는 UTF-8로 인코딩됩니다. 모든 입력은 줄 바꿈 문자로 종료되며 프로세스는 모든 출력 응답을 줄 바꿈으로 종료해야합니다.
경고 Java 랩퍼가 출력을 볼 수 있도록 매 쓰기 후에 출력 버퍼를 플러시하십시오. 세척하지 않으면 원격 Wolf가 고장날 수 있습니다.
하나의 프로세스 만 작성되며 모든 Wolves는 해당 프로세스 하나에서 관리해야합니다. 이 사양이 어떻게 도움이 될지 계속 읽으십시오.
초기화
STDIN : S<id><mapsize>
\ n
STDOUT : K<id>
\ n
<id>
: 00
또는 01
또는 ... 또는99
설명:
문자는 S
두 숫자 뒤에 전송 될 00
, 01
..., 99
초기화되고있는 100 늑대 나타낸다. 미래의 특정 늑대와의 모든 의사 소통에서 동일 <id>
하게 사용될 것입니다.
ID 다음에 가변 길이의 숫자 문자가 전송됩니다. 이것은지도의 크기입니다. 줄 바꿈 ( \n
)에 도달하면 일련의 숫자가 끝났음을 알 수 있습니다 .
당신의 프로세스가 살아 있도록하려면, 당신 이받은 K
것과 같은 문자로 답장해야합니다 <id>
. 다른 답변은 예외를 초래하여 늑대를 죽입니다.
운동
STDIN : M<id><C0><C1>...<C7><C8>
\ n
STDOUT : <mv><id>
\ n
<Cn>
: W
또는
또는 B
또는 S
또는L
W
: 늑대
: 빈 공간
B
: 곰
S
: 스톤
L
: 사자
<mv>
: H
또는 U
또는 L
또는 R
또는D
H
: Move.HOLD
U
: 이동
L
: 이동 . 왼쪽
R
: 이동
D
: 아래로 이동
설명:
어떤 늑대가 이동을 선택해야하는지 표시하기 위해 문자 M
가 전송되고 두 문자가 전송됩니다 <id>
. 그런 다음 Wolf의 주변 환경을 나타내는 9 개의 문자가 행 순서 (맨 위 행, 가운데 행, 맨 아래 행에서 맨 오른쪽 행)로 전송됩니다.
유효한 이동 문자 중 하나를 입력 한 <mv>
다음 <id>
확인을 위해 Wolf의 두 자리 숫자 로 답장하십시오 .
공격
STDIN : A<id><C>
\ n
STDOUT : <atk><id>
\ n
<C>
: W
또는 B
또는 S
또는L
<atk>
: R
또는 P
또는 S
또는D
R
: 공격 . 록
P
: Attack.PAPER
S
: 공격 . 가위
D
: 공격 . SUICIDE
설명:
어떤 늑대가 공격에 참여하고 있는지 표시하기 위해 문자 A
가 전송되고 두 문자가 전송됩니다 <id>
. 그 다음에 <C>
는 공격 할 물건의 종류 ( W
올프, B
귀, S
톤 또는 L
이온)를 나타내는 단일 문자가옵니다 .
<atk>
위에 나열된 문자 중 하나로 응답하여 <id>
확인 에 대한 두 자리 숫자 로 공격에 대한 응답을 나타냅니다 .
그리고 그게 다야. 더 이상 없습니다. 만약 당신이 공격을 잃어 버리면, 그것은 <id>
다시 당신의 프로세스로 보내지지 않을 것입니다. 그것이 당신의 울프가 죽었다는 것을 알게 될 것 <id>
입니다.
결론
단 하나의 "프로세스"만 원격 늑대로 구성되므로 생성 된 모든 늑대의 늑대는 예외로 인해 원격 늑대의 모든 늑대가 죽습니다.
이 저장소에는 Wolf.java
파일이 있습니다. 다음 문자열을 검색하여 바꾸어 봇을 설정하십시오.
교체 <invocation>
제대로 프로세스를 실행 명령 행 인수.
교체 <custom-name>
하여 늑대의 고유 한 이름으로.
예를 들어 저장소 보면 내가 가지고있는 경우, WolfRandomPython.java
그 내 예를 들어 원격의 호출 PythonWolf.py
(파이썬 3 + 늑대).
파일 이름을로 바꾸십시오. Wolf<custom-name>.java
여기서 <custom-name>
선택한 이름으로 바뀝니다.
Wolf를 테스트하려면 Java 프로그램 ( javac Wolf<custom-name>.java
)을 컴파일하고 Rusher의 지시 사항에 따라이를 시뮬레이션 프로그램에 포함 시키십시오.
중요 사항 : 위에서 설명한 체계를 따르는 실제 Wolf를 컴파일 / 실행하는 방법에 대한 명확 하고 간결한 지시 사항 을 제공하십시오 .
행운을 빕니다.
래퍼 코드
이 작업을 수행하려면 대략적으로 검색하고 대치해야합니다. 당신의 호출이 특히 털이 많은 경우, 저에게 연락하여 도움을 요청하십시오.
main
이 랩퍼에는 로컬 상자에서 기본적인 "통과 / 실패"테스트를 수행 할 수 있는 방법이 있습니다. 이렇게하려면 프로젝트에서 Animal.java 클래스를 다운로드하고 package animals;
두 파일 에서 줄을 제거하십시오 . Animal.java의 MAP_SIZE 줄을 100과 같은 상수로 바꿉니다. javac Wolf<custom-name>.java
를 통해 실행을 사용하여 컴파일하십시오 java Wolf<custom-name>
.
package animals;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
/**
* Remote Wolf<custom-name> wrapper class.
*/
public class Wolf<custom-name> extends Animal {
/**
* Simple test script that sends some typical commands to the
* remote process.
*/
public static void main(String[]args){
Wolf<custom-name>[] wolves = new Wolf<custom-name>[100];
for(int i=0; i<10; i++) {
wolves[i] = new Wolf<custom-name>();
}
char map[][] = new char[3][3];
for (int i=0;i<9;i++)
map[i/3][i%3]=' ';
map[1][1] = 'W';
for(int i=0; i<10; i++) {
wolves[i].surroundings=map;
System.out.println(wolves[i].move());
}
for(int i=0; i<10; i++) {
System.out.println(wolves[i].fight('S'));
System.out.println(wolves[i].fight('B'));
System.out.println(wolves[i].fight('L'));
System.out.println(wolves[i].fight('W'));
}
wolfProcess.endProcess();
}
private static WolfProcess wolfProcess = null;
private static Wolf<custom-name>[] wolves = new Wolf<custom-name>[100];
private static int nWolves = 0;
private boolean isDead;
private int id;
/**
* Sets up a remote process wolf. Note the static components. Only
* a single process is generated for all Wolves of this type, new
* wolves are "initialized" within the remote process, which is
* maintained alongside the primary process.
* Note this implementation makes heavy use of threads.
*/
public Wolf<custom-name>() {
super('W');
if (Wolf<custom-name>.wolfProcess == null) {
Wolf<custom-name>.wolfProcess = new WolfProcess();
Wolf<custom-name>.wolfProcess.start();
}
if (Wolf<custom-name>.wolfProcess.initWolf(Wolf<custom-name>.nWolves, MAP_SIZE)) {
this.id = Wolf<custom-name>.nWolves;
this.isDead = false;
Wolf<custom-name>.wolves[id] = this;
} else {
Wolf<custom-name>.wolfProcess.endProcess();
this.isDead = true;
}
Wolf<custom-name>.nWolves++;
}
/**
* If the wolf is dead, or all the wolves of this type are dead, SUICIDE.
* Otherwise, communicate an attack to the remote process and return
* its attack choice.
*/
@Override
public Attack fight(char opponent) {
if (!Wolf<custom-name>.wolfProcess.getRunning() || isDead) {
return Attack.SUICIDE;
}
try {
Attack atk = Wolf<custom-name>.wolfProcess.fight(id, opponent);
if (atk == Attack.SUICIDE) {
this.isDead = true;
}
return atk;
} catch (Exception e) {
System.out.printf("Something terrible happened, this wolf has died: %s", e.getMessage());
isDead = true;
return Attack.SUICIDE;
}
}
/**
* If the wolf is dead, or all the wolves of this type are dead, HOLD.
* Otherwise, get a move from the remote process and return that.
*/
@Override
public Move move() {
if (!Wolf<custom-name>.wolfProcess.getRunning() || isDead) {
return Move.HOLD;
}
try {
Move mv = Wolf<custom-name>.wolfProcess.move(id, surroundings);
return mv;
} catch (Exception e) {
System.out.printf("Something terrible happened, this wolf has died: %s", e.getMessage());
isDead = true;
return Move.HOLD;
}
}
/**
* The shared static process manager, that synchronizes all communication
* with the remote process.
*/
static class WolfProcess extends Thread {
private Process process;
private BufferedReader reader;
private PrintWriter writer;
private ExecutorService executor;
private boolean running;
public boolean getRunning() {
return running;
}
public WolfProcess() {
process = null;
reader = null;
writer = null;
running = true;
executor = Executors.newFixedThreadPool(1);
}
public void endProcess() {
running = false;
}
/**
* WolfProcess thread body. Keeps the remote connection alive.
*/
public void run() {
try {
System.out.println("Starting Wolf<custom-name> remote process");
ProcessBuilder pb = new ProcessBuilder("<invocation>".split(" "));
pb.redirectErrorStream(true);
process = pb.start();
System.out.println("Wolf<custom-name> process begun");
// STDOUT of the process.
reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
System.out.println("Wolf<custom-name> reader stream grabbed");
// STDIN of the process.
writer = new PrintWriter(new OutputStreamWriter(process.getOutputStream(), "UTF-8"));
System.out.println("Wolf<custom-name> writer stream grabbed");
while(running){
this.sleep(0);
}
reader.close();
writer.close();
process.destroy(); // kill it with fire.
executor.shutdownNow();
} catch (Exception e) {
e.printStackTrace();
System.out.println("Wolf<custom-name> ended catastrophically.");
}
}
/**
* Helper that invokes a read with a timeout
*/
private String getReply(long timeout) throws TimeoutException, ExecutionException, InterruptedException{
Callable<String> readTask = new Callable<String>() {
@Override
public String call() throws Exception {
return reader.readLine();
}
};
Future<String> future = executor.submit(readTask);
return future.get(timeout, TimeUnit.MILLISECONDS);
}
/**
* Sends an initialization command to the remote process
*/
public synchronized boolean initWolf(int wolf, int map_sz) {
while(writer == null){
try {
this.sleep(0);
}catch(Exception e){}
}
boolean success = false;
try{
writer.printf("S%02d%d\n", wolf, map_sz);
writer.flush();
String reply = getReply(5000l);
if (reply != null && reply.length() >= 3 && reply.charAt(0) == 'K') {
int id = Integer.valueOf(reply.substring(1));
if (wolf == id) {
success = true;
}
}
if (reply == null) {
System.out.println("did not get reply");
}
} catch (TimeoutException ie) {
endProcess();
System.out.printf("Wolf<custom-name> %d failed to initialize, timeout\n", wolf);
} catch (Exception e) {
endProcess();
System.out.printf("Wolf<custom-name> %d failed to initialize, %s\n", wolf, e.getMessage());
}
return success;
}
/**
* Send an ATTACK command to the remote process.
*/
public synchronized Attack fight(int wolf, char opponent) {
Attack atk = Attack.SUICIDE;
try{
writer.printf("A%02d%c\n", wolf, opponent);
writer.flush();
String reply = getReply(1000l);
if (reply.length() >= 3) {
int id = Integer.valueOf(reply.substring(1));
if (wolf == id) {
switch(reply.charAt(0)) {
case 'R':
atk = Attack.ROCK;
break;
case 'P':
atk = Attack.PAPER;
break;
case 'S':
atk = Attack.SCISSORS;
break;
case 'D':
atk = Attack.SUICIDE;
break;
}
}
}
} catch (TimeoutException ie) {
endProcess();
System.out.printf("Wolf<custom-name> %d failed to attack, timeout\n", wolf);
} catch (Exception e) {
endProcess();
System.out.printf("Wolf<custom-name> %d failed to attack, %s\n", wolf, e.getMessage());
}
return atk;
}
/**
* Send a MOVE command to the remote process.
*/
public synchronized Move move(int wolf, char[][] map) {
Move move = Move.HOLD;
try{
writer.printf("M%02d", wolf);
for (int row=0; row<map.length; row++) {
for (int col=0; col<map[row].length; col++) {
writer.printf("%c", map[row][col]);
}
}
writer.print("\n");
writer.flush();
String reply = getReply(1000l);
if (reply.length() >= 3) {
int id = Integer.valueOf(reply.substring(1));
if (wolf == id) {
switch(reply.charAt(0)) {
case 'H':
move = Move.HOLD;
break;
case 'U':
move = Move.UP;
break;
case 'L':
move = Move.LEFT;
break;
case 'R':
move = Move.RIGHT;
break;
case 'D':
move = Move.DOWN;
break;
}
}
}
} catch (TimeoutException ie) {
endProcess();
System.out.printf("Wolf<custom-name> %d failed to move, timeout\n", wolf);
} catch (Exception e) {
endProcess();
System.out.printf("Wolf<custom-name> %d failed to move, %s\n", wolf, e.getMessage());
}
return move;
}
}
}