챔피언이 되십시오


11

틱택 라틴!

이것은 실제 이야기이므로 이름이 변경되었습니다.

저의 라틴어 교사 인 Mr. Latin은 자신 만의 고유 한 틱택 토 변형을 만들었습니다. 그것을 틱택 라틴이라고합시다. 게임은 간단합니다. 기본적으로 4 x ​​4 그리드에서 재생되는 틱택 토입니다.

공식적인 규칙 선언

선은 행, 열 또는 대각선입니다. 'X'와 'O'의 두 가지 기호가 있지만 하나 또는 둘 다 다른 기호로 대체 될 수 있습니다.
당신은 당신의 상징 중 3 개와 다른 인물 중 하나가있을 때 1 점을 얻습니다.

이러한 배치는 다음과 같이 점수를 매 깁니다.

---영형
-영형--
XXXO
XOOX

O -XX
- O -
- X -
--- O

이 점수는 없습니다 :

----
XXXX
----
OOOO

----
트리플 엑스-
----
OOO-

한 플레이어가 다른 플레이어보다 더 많은 포인트를 가질 때마다 게임에서 승리합니다. 게임은 보드가 가득 찬 경우에만 추첨입니다.

도전

이 게임을 해결하십시오. 당신의 임무는 승리 또는 동점을 보장하는 방법을 제공하는 것입니다.

솔루션은 첫 번째 또는 두 번째 시작을 선택할 수 있으므로 기호를 선택할 수 있습니다. 사용자 입력이 이동하고 해당 디스플레이가 변경되는 대화 형 게임을 반드시 구현해야하는 것은 아닙니다. 또한 게임 상태로 입력을 받아 새로운 보드 또는 이동 설명을 출력하는 기능 또는 프로그램 일 수 있습니다 . 두 옵션 중 하나를 움직일 때마다 약 10 초 이내에 실행해야합니다.


일련의 움직임에 대해 플레이어를 플레이하면 최적의 결과를 제공해야합니다. 이것은 입력 위치가 플레이어와의 플레이에서 도달 할 수있는 위치라고 가정 할 수 있음을 의미합니다. 제출물은 결정 론적이어야하며 반드시 최적의 증거를 제공 할 필요는 없지만 제출물이 깨져서 제출 된 경우 제출물이 유효하지 않은 것으로 간주됩니다 (제출할 수는 있지만 헤드 라인에 추가됨).
이것은 사소한 일이 아니므로 유효한 제출물은 인상적이며 허용되는 진드기의 가치가 있지만 코드 골프를 주요 우승 기준으로 삼을 것입니다.

당첨자는 한 명의 당첨자가 선택 될 때까지이 목록을 내려 가서 당첨됩니다.

  • 항상이기는 ​​가장 짧은 해결 된 구현
  • 최단 구현

1
"먼저 놀이의 질을 봅니다"주관적이라고 생각하지 않습니까?
user48538

재생할 인터페이스를 제공하는 작업은 완벽한 플레이어를 작성하는 데있어 중요한 것 같습니다. 나는 현재 게임 상태를 입력으로 단순히 통과시키고 승리하는 움직임을 출력하기 위해 코드를 요구하거나 심지어 완벽한 플레이 (승리, 무승부, 패배)에서 평가하는 것이 좋습니다.
xnor

1
비효율적 인 무차별 대입 검색을 수행하면 솔루션이 골치 거리가 될 수 있습니다. 코드가 매우 느리게 실행되면 괜찮습니까?
xnor

1
" 점수를 매기면 게임에서 이기고 상대방은 점수를 얻지 못합니다. "이것은 상대방 이 할 때가 아니라 조각을 놓을 때만 이길 수 있다는 것을 의미합니까? 움직임이 두 선수 모두에게 승리의 선을 만들면 어떻게 될까요?
피터 테일러

1
@RohanJhunjhunwala 게임 상태의 허용 된 입력을 명확히해야합니다. 그렇지 않으면 사람들이 현재 정의되지 않은 입력 형식을 활용하고 솔루션을 많이 돕는 형식을 선택할 수 있습니다.
ASCII 전용

답변:


6

Perl, 147 바이트 (비경쟁, 이동 당 10 초 이상 소요)

에 +4 포함 -0p

프로그램이 재생 X됩니다. 완벽한 게임을 할 것입니다.

STDIN에 보드를 입력하십시오. 예 :

tictaclatin.pl
-X-O
-X--
X-X-
O--O
^D

ouptut은 모두 같은 보드로 X교체되며 O그 반대도 마찬가지입니다. 빈 자리는 X가 그 자리에서 경기 할 경우 결과를 나타내는 숫자로 채워 지며 1결과는 승리, 2무승부 및 3손실입니다. 완성 된 게임은 색상이 반전 된 동일한 위치를 반환합니다.

이 예제에서 출력은 다음과 같습니다.

1O1X
1O33
O3O3
X33X

따라서 X그가 위와 왼쪽을 따라 3 개의 지점에서 뛰면 위치는 승리입니다 . 다른 모든 움직임은 패배합니다.

이 혼란스러운 결과는 실제로 이동 후 게임이 어떻게 진행되는지 알고 싶다면 실제로 편리합니다. 프로그램이 항상 연극 때문에 X당신은 교체해야 X하고 O의 움직임을보고 O. 예를 들어 X왼쪽 상단에서 플레이 하면 이기는 것이 분명 하지만 X상단을 따라 세 번째 포지션에서 플레이 하는 경우 는 어떻습니까? 출력을 복사하고 O선택한 이동 위치에 넣고 다른 모든 숫자를 -다시 바꿉니다.

-OOX
-O--
O-O-
X--X

를 야기하는:

3XXO
3X33
X3X3
O33O

분명히 모든 움직임 O은 잃어야한다. 그래서 그가 왼쪽 상단에서 뛰면 어떻게 지는가? 다시 O왼쪽 상단 에 넣고 숫자를 -다음 과 같이 바꾸십시오 .

OXXO
-X--
X-X-
O--O

기부:

XOOX
1O33
O3O3
X33X

따라서 X는 자신의 승리를 위해 갈 수있는 유일한 방법이 있습니다 :

XOOX
OO--
O-O-
X--X

기부

OXXO
XX33
X3X3
O33O

상황 O은 절망적이다. 모든 움직임 X이 즉시 이길 수 있음 을 쉽게 알 수 있습니다 . 최소한 3 O를 연속해서 시도해 봅시다.

OXXO
XX--
X-X-
O-OO

기부:

XOOX
OO13
O3O3
X3XX

X유일하게이기는 움직임을합니다 (이것은 XXXO세 번째 열 을 따라 한다는 점에 유의하십시오 :

XOOX
OOO-
O-O-
X-XX

출력은 다음과 같습니다.

OXXO
XXX-
X-X-
O-OO

게임이 이미 완료 되었기 때문입니다. 당신은 세 번째 열에서 승리를 볼 수 있습니다.

실제 프로그램 tictaclatin.pl:

#!/usr/bin/perl -0p
y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/sx;$@<=>0||s%-%$_="$`O$'";$$_||=2+do$0%eg&&(/1/||/2/-1)

빈 보드에 적용하면 내 컴퓨터에서 30Gb 및 41 분이 걸리는 9506699 위치를 평가합니다. 결과는 다음과 같습니다.

2222
2222
2222
2222

따라서 모든 시작 움직임이 그립니다. 따라서 게임은 무승부입니다.

극단적 인 메모리 사용량은 주로를 사용하는 재귀에 의해 발생합니다 do$0. 일반 기능을 사용하여이 154 바이트 버전을 사용하려면 3Gb 및 11 분이 필요합니다.

#!/usr/bin/perl -0p
sub f{y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/sx;$@<=>0||s%-%$_="$`O$'";$$_||=2+&f%eeg&&(/1/||/2/-1)}f

더 견딜 만합니다 (그러나 여전히 너무 많은 것은 여전히 ​​메모리 누수가 있어야합니다).

여러 가지 속도 향상을 결합하면이 160 바이트 버전 (빈 보드의 경우 5028168 위치, 4 분 및 800M)이됩니다.

#!/usr/bin/perl -0p
sub f{y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/osx;$@<=>0||s%-%$_="$`O$'";$a{$_}//=&f+1or return 1%eeg&&/1/-1}f

마지막 0으로 승리 (와 혼동하지 마십시오 O), 1추첨 및 2패배에 사용합니다. 이것의 결과도 더 혼란 스럽다. 컬러 스왑없이 승리 한 경우 X의 승리 움직임을 채 웁니다. 그러나 입력 게임이 이미 승리 한 경우 여전히 컬러 스왑을 수행하며 아무 움직임도 채우지 않습니다.

물론 모든 버전은 보드가 가득 차면서 더 빨라지고 더 적은 메모리를 사용합니다. 더 빠른 버전은 2 ~ 3 번 이동하자마자 10 초 이내에 이동을 생성해야합니다.

원칙적으로이 146 바이트 버전도 작동해야합니다.

#!/usr/bin/perl -0p
y/XO/OX/,$@=-$@while/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^/sx,--$|;$@<=>0||s%-%$_="$`O$'";$$_||=2+do$0%eg&&(/1/||/2/-1)

그러나 내 컴퓨터에서는 펄 버그를 유발하고 코어를 덤프합니다.

6 바이트 위치 캐싱 $$_||=이 제거되었지만 시간과 메모리가 너무 많이 사용되어 거의 채워진 보드에서만 작동하는 경우 모든 버전은 원칙적으로 여전히 작동합니다 . 그러나 이론적으로는 140 바이트 솔루션이 있습니다.

당신은 넣으면 $\=바로 전에 (3 바이트 비용) $@<=>0: 각 출력 보드 전체 보드의 상태에 따라야 할 것입니다 1에 대한 X승리, 0무승부와 -1손실.

위에서 언급 한 가장 빠른 버전을 기반으로하는 대화식 드라이버는 다음과 같습니다. 드라이버는 게임이 끝나는 시점에 대한 논리가 없으므로 스스로를 중단해야합니다. 골프 코드는 알고 있습니다. 제안 된 움직임 -이 다른 것으로 대체 되지 않고 돌아 오면 게임이 끝난 것입니다.

#!/usr/bin/perl
sub f{
    if ($p++ % 100000 == 0) {
        local $| = 1;
        print ".";
    }
y/XO/OX/,$@=-$@while$|-=/(@{[map{(O.".{$_}O"x3)=~s%O%Z|$`X$'|Z%gr}0,3..5]})(?{$@++})^|$/osx;$@<=>0||s%-%$_="$`O$'";$a{$_}//=&f+1or return 1%eeg&&/1/-1}

# Driver
my $tomove = "X";
my $move = 0;
@board = ("----\n") x 4;
while (1) {
    print "Current board after move $move ($tomove to move):\n  ABCD\n";
    for my $i (1..4) {
        print "$i $board[$i-1]";
    }
    print "Enter a move like B4, PASS (not a valid move, just for setup) or just press enter to let the program make suggestions\n";
    my $input = <> // exit;
    if ($input eq "\n") {
        $_ = join "", @board;
        tr/OX/XO/ if $tomove eq "O";
        $p = 0;
        $@="";
        %a = ();
        my $start = time();
        my $result = f;
        if ($result == 1) {
            tr/OX/XO/ if $tomove eq "O";
            tr/012/-/;
        } else {
            tr/OX/XO/ if $tomove eq "X";
            tr/012/123/;
        }
        $result = -$result if $tomove eq "O";
        my $period = time() - $start;
        print "\nSuggested moves (evaluated $p positions in $period seconds, predicted result for X: $result):\n$_";
        redo;
    } elsif ($input =~ /^pass$/i) {
        # Do nothing
    } elsif (my ($x, $y) = $input =~ /^([A-D])([1-4])$/) {
        $x = ord($x) - ord("A");
        --$y;
        my $ch = substr($board[$y],$x, 1);
        if ($ch ne "-") {
            print "Position already has $ch. Try again\n";
            redo;
        }
        substr($board[$y],$x, 1) = $tomove;
    } else {
        print "Cannot parse move. Try again\n";
        redo;
    }
    $tomove =~ tr/OX/XO/;
    ++$move;
}

좋은 답변. 이것을 테스트 할 수있는 쉬운 방법을 제공해 주시겠습니까? 이상적으로는 대화 형 버전을보고 싶을 것입니다 ... (이것은 내 호기심을 자극합니다).
Rohan Jhunjhunwala

@RohanJhunjhunwala Ok, 간단한 대화 형 드라이버 추가
Ton Hospel

변수 '$ move'는 prog.pl:2에서 선언되지 않았습니다
Rohan Jhunjhunwala

인간이 구현할 수있는 휴리스틱 솔루션이 있습니까?
Rohan Jhunjhunwala

@RohanJhunjhunwala 드라이버 프로그램을 다시 확인했습니다. 벌금을 실행, $move인간의 휴리스틱이있는 경우 라인 (11)에 나는 아무 생각이 선언된다. 단지 게임 트리에 최소 최대 않습니다이 프로그램은, 그것은없는 어떤 전략적 지식을.
Ton Hospel

2

자바 스크립트 (ES6) 392 바이트

a=>b=>(c="0ed3b56879a4c21f",r=[],k=f=>r.push([a.filter(f),b.filter(f)]),[0,1,2,3].map(i=>k(n=>n%4==i)+k(n=>(n/4|0)==i)),k(n=>n%5==0),k(n=>n&&n-15&&!(n%3)),g=r.find(o=>(o[0].length==1&&o[1].length==2)||(o[0].length==2&&o[1].length==1)),g?parseInt(c[30-[...g[0],...g[1]].map(i=>parseInt(c[i],16)).reduce((p,c)=>p+c)],16):[...a,...b].indexOf(15-a[0])+1?15-a.find(i=>b.indexOf(15-i)==-1):15-a[0])

용법

"봇"이 두 번째로 재생됩니다.

다음과 같이 번호가 매겨진 4x4 그리드를 그립니다.

+----+----+----+----+
|  0 |  1 |  2 |  3 |
+----+----+----+----+
|  4 |  5 |  6 |  7 |
+----+----+----+----+
|  8 |  9 | 10 | 11 |
+----+----+----+----+
| 12 | 13 | 14 | 15 |
+----+----+----+----+

브라우저 콘솔에서 실행 해 봅시다 : f=코드 앞에 놓기 만하면됩니다.

내가에서 시작하고 싶다면 1달리고 f([1])([])나에게 줄 것이다 14.

좋은 움직임 ... 2나중에 게임을하면 어떻게 되나요? f([2,1])([14]). 반환 13됩니다.

렘은 항복을 시도합니다. 플레이 3. f([3,2,1])([14,13]). 아 0! 당신은 저를 얻었다!

플레이 0? f([0,2,1])([14,13]). 15그래 계속 연주하자 ...

노트

  1. 대화식으로 플레이하십시오. 로 시작하십시오 f([your-step])([]).

  2. 다음 단계를 앞에 두십시오. (위의 데모 참조)

  3. "bot"이 단계를 입력하도록 도와주세요. 임의의 설정을 지정하면 좋은 결과를 얻지 못합니다. (좋아할 f([1,2,4])([14,12])것입니다 14-봇 13이 두 번째 움직임 에서 플레이하기를 원했습니다 !

간단한 요약

항복하지 않는 한 봇은 거울을 움직입니다.

게임 규칙과 골프 팁을 잘못 읽었다 고 알려주는 @EHTproductions에게 감사드립니다. : P

이제 검사자가 있는지 여부도 감지합니다. 그렇다면 차단하십시오!

우선 순위 : 블록> 미러> (대체) 미러를 재현하는 방법 찾기


나는 "미러 움직임"전술을 정말 좋아한다 :) 나는 오해 할 수도 있지만, 3,2,1당신과 0봇 에게는 당신을 위한 승리가 아닌가?
ETHproductions

죄송합니다. "3 가지 패턴과 1 가지 패턴을 캡처하는 사람"으로 오해했습니다. Lemme는 솔루션을 약간 조정했습니다. @ETHproductions 감사합니다.
Sunny Pun

몇 가지 골프 팁 :로 골프를 [0,1,2,3].map(i=>{k(n=>n%4==i);k(n=>Math.floor(n/4)==i);})칠 수 있습니다 [0,1,2,3].map(i=>k(n=>n%4==i)+k(n=>(n/4|0)==i)).
ETHproductions

나는 이것이 이길 수 있다고 생각하지 않는다
Rohan Jhunjhunwala

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.