당신의 다음 움직임은 무엇입니까?


18

이 과제는 현재 보드 상태에 따라 틱택 토 게임의 NxN 게임 에서 다음으로 최고의 움직임을 출력하기 위해 선택한 언어로 minimax 기능 을 작성하는 것 입니다. 보드 입력은 Matrix, 2D Collection 또는 귀하에게 의미가 있지만 규칙을 준수하는 다른 것으로 받아 들여질 수 있습니다 . 되는 출력 다음 최고의 이동 을 위해 그것을 차례 누구든지이 현재 어디에, X가 시작 것으로 간주됩니다 .

Minimax 알고리즘에 대한 빠른 배경

minimax 알고리즘의 기본 아이디어는 가능한 모든 결과를 DAG로 열거 한 다음 처음으로 이동 한 키를 기준으로 이동 순서가 플레이어에게 미치는 이점에 따라 가중치를 부여하는 것입니다. 그런 다음 가능한 모든 결과는 첫 번째 움직임으로 '버킷 화'되며 모든 결과의 합계 (손실의 경우 -1, 동점의 경우 0, 승리의 경우 1)를 기준으로 점수가 매겨집니다. 여러 명의 플레이어가 플레이해야하는 구현에서는 플레이어의 모든 가능한 움직임과 상대방의 가능한 모든 응답을 열거합니다. 예를 들어, 틱택 토 게임 (첫 번째 이동 후)에는 8 개의 가능한 첫 번째 이동이있을 수 있으며 다음 턴을 분석 할 때 모두 동일하게 보일 수 있습니다. 그러나 각 가능한 이동 세트에 대해 가능한 모든 결과를 반복하여 최종 결과를 도출하고 모두 합산함으로써,

tic-tac-toe와 관련하여 mini-max 알고리즘에 대한보다 상세하고 상황에 맞는 요약을 보려면 여기를 참조하십시오 : http://neverstopbuilding.com/minimax

XKCD (3x3 솔루션 만)

틱택 토의 3x3 게임에 가능한 모든 움직임.

규칙

  • 모든 언어를 사용할 수 있지만 외부 minimax 라이브러리는 허용되지 않습니다.
  • 출력은 좌표 (0-n, 0-n) 또는 최상의 다음 이동을 나타내는 숫자 (1-n * n) 일 수 있습니다.
    • 또한, 최상의 시나리오가 승리가 아닌 손실 또는 동점 일 경우를 식별 할 수 있어야합니다.
    • 상실이나 동점을 나타내는 방법은 다시 한 번 당신에게 달려 있습니다.
  • 입력은 전통적인 X와 O를 사용해야하며 X가 먼저 움직이는 것으로 가정해야합니다. 공백은 무엇이든 나타낼 수 있습니다.
  • 프로그램으로 들어오는 모든 입력에 n O와 n + 1 X가 있다고 가정 할 수 있습니다. 다시 말해, 올바른 보드를 가지고 있다고 가정 할 수 있습니다.
  • 보드의 현재 상태는 프로그램에 대한 유일한 입력이어야합니다. 재귀를 사용하는 경우 입력 요구 사항을 용이하게하기 위해 헬퍼 메소드를 작성해야합니다. 자세한 설명 은 /codegolf//a/92851/59376 을 참조 하십시오 .
  • 10> = n> = 1의 값이 지원되어야합니다. n> 10 동안 프로그램이 "시간 초과"되면 일부 언어의 처리 능력이 현저히 낮아지기 때문에 (특히 웹 콘솔 사용)이 기능도 허용됩니다.

심사

  • 이것은 코드 골프이므로 프로그램의 최하위 바이트 수와 표준 허점은 보편적으로 허용되지 않습니다.
  • 동점 인 경우 가장 큰 'n'을 지원하는 프로그램이 승리합니다.

입력 예

2x2

[[X,O]
 [-,-]]

출력 : 2 또는 [0,1] (3 또는 [1,1]도 정확할 것임) (사용한 형식을 쉽게 설명 할 수있는 한 임의의 위치 표시 형식, 임의)


3x3

[[X,O,X]
 [O,X,-]
 [-,-,-]]

출력 : -1 (손실)


다시 한 번 원하는 입력 형식이 허용되지만 X와 O를 사용해야합니다. 제공된 예제는 해당 형식에 제한되는 것이 아니라 영감을주기위한 것입니다.


죄송합니다. DJMCMayhem, 나는 실제로 그런 것들을 태그하려고 시도했지만 여기에 처음 왔을 때 나는 할 수 없었습니다.
Magic Octopus Urn

보너스도 제거되어 지루한 것만 추가했습니다.
Magic Octopus Urn

허용되는 다음과 같은 출력 형식입니다 : 승리 / 손실이 리드를 재생했는지를 나타내는 각각의 원래 빈 공간을 독특한 캐릭터와 보드 위치의 그림은 / (예를 들어, W, L 및 D) 그릴
톤 Hospel

1
3x3 예제에서 O는 그가 무엇을 하던지 잃을 것이지만, 출력이 [2,1]이어야한다고 왜 그렇습니까?
Dada

잘 편집했습니다. 내가 무슨 생각을했는지 모르는 것이 부정적인 예였습니다.
Magic Octopus Urn

답변:


8

펄, 101 98 바이트

포함 +4을 위해-0p

STDIN의 입력으로 실행

tictactoe.pl
OXO
---
--X
^D

결과는 같은 다이어그램이지만 각 움직임이 상태로 업데이트되고 1승리를 2나타내며 무승부를 3나타내며 손실을 나타냅니다. 이 경우에는

OXO
223
21X

따라서 3 이동 무승부, 1 승리 및 1 패배 (이 출력 형식이 허용되지 않으면 솔루션을 업데이트하지만 기본 코드는 동일하게 유지됩니다)

tictactoe.pl:

#!/usr/bin/perl -0p
m%@{[map"O.{$_}"x"@-"."O|",1-/.(
)(.)/,@-]}Z%sx||s%-%$_="$`X$'";y/XO/OX/;do$0%eg?/1/?3:1+/2/:2

이것은 이미 고통스럽게 느리고 빈 3 * 3 보드에 많은 메모리를 사용합니다 (실제로 재귀가 그렇게 깊이 들어 가지 않습니다. 메모리 누수가 있어야합니다). 메모리 추가 비용은 6 바이트이지만 훨씬 더 안전합니다.

#!/usr/bin/perl -0p
$$_||=m%@{[map"O.{$_}"x"@-"."O|",1-/.(\n)(.)/,@-]}Z%sx||s%-%$_="$`X$'";y/XO/OX/;do$0%eg?/1/?3:1+/2/:2

와우, 그것이 pl이고 간신히 많은 빈 상태로 n = 10 동안 실행되지 않을 것이라는 것을 간과 ... 당신은 누군가가하기를 바랐던 두 가지 일을 모두했습니다. 문자열 입력 및 최상의 결과뿐만 아니라 모든 움직임에 대한 결과 매핑. 브라보.
Magic Octopus Urn

하나의 재귀 함수가 '누설'하면 어떻게 될 수 있습니까 ??? 언어가 너무 높으면 CPU에서 32 비트 레지스터 (또는 간단한 명령어)를
보지 못합니다

이러한 맥락에서 @RosLup 누출이 반드시 도달 할 수없는 메모리 손실을 의미하지는 않습니다. 펄은 메모리를 릴리즈 할 때 다소 특이하다. 예상보다 훨씬 늦게 메모리를 사용하므로 예상보다 많은 메모리를 사용한다. 또한 데이터 구조가 커질 것이라는 기대에 직접 필요한 것 이상을 할당하는 경향이 있습니다. 이 경우 남용 대신 함수와 함께 "정상"재귀를 do$0사용하면 10 배 적은 메모리가 사용됩니다. 이 경우가 너무 극단적이므로 실제로 실제 메모리 누수가 될 수 있습니다.
Ton Hospel

(lllls 명령에서) 레지스터 나 기본 명령을 볼 수 없을뿐만 아니라 메모리 사용 제어를 잃게됩니다 ... 저를 위해 확장 할 수 없습니다 ...
RosLuP

시간이 오래 걸렸습니다. 당신은 내 남자를 이겼습니다. 슬프지만 더 이상 시도하지 않았습니다.
Magic Octopus Urn

2

자바 스크립트 (ES6), 320 294 바이트

(b,p,d,M,S=-2)=>(T=(p,q,r,s)=>b[p][q]==(n=b[r][s|0])&&n!='-',w=0,b.map((r,y)=>(l=r.length-1,m=15,r.map((c,x)=>(m&=8*T(l-x,x,l)+4*T(x,x,0)+2*T(x,y,0,y)+T(y,x,y))),w|=m)),w?-1:(b.map((r,y)=>r.map((c,x)=>S<1&&c=='-'&&(r[x]='O.X'[p+1],(s=-f(b,-p,1))>S&&(S=s,M=[x,y]),r[x]=c))),S=S+2?S:0,d?S:[M,S]))

입력

1) 현재 보드를 설명하는 문자 배열 (예 :

[['X', '-'], ['-', 'O']]

2) 현재 턴을 설명하는 정수 : 1 = X, -1 =O

산출

다음으로 구성된 배열 :

  • 가장 좋은 [x, y]형식의 이동을 설명하는 배열
  • 정수로서의 게임 결과 : 1 = 승리, -1 = 손실, 0 = 넥타이

다음 예 X에서는를 플레이하여이기는 것이 보장됩니다 [1, 2].

let f =
(b,p,d,M,S=-2)=>(T=(p,q,r,s)=>b[p][q]==(n=b[r][s|0])&&n!='-',w=0,b.map((r,y)=>(l=r.length-1,m=15,r.map((c,x)=>(m&=8*T(l-x,x,l)+4*T(x,x,0)+2*T(x,y,0,y)+T(y,x,y))),w|=m)),w?-1:(b.map((r,y)=>r.map((c,x)=>S<1&&c=='-'&&(r[x]='O.X'[p+1],(s=-f(b,-p,1))>S&&(S=s,M=[x,y]),r[x]=c))),S=S+2?S:0,d?S:[M,S]))

console.log(JSON.stringify(f(
  [['O','X','O'],
   ['-','-','-'],
   ['-','-','X']],
  1
)));

변덕스러운 게임. 승리 한 유일한 움직임은 재생되지 않습니다.
좋은 게임 게임은 어떻습니까?


잘 했어, 첫 입국. 주어진 정보 'X는 항상 먼저 이동합니다'를 사용하여 바이트를 절약 할 수 있습니다. 그리고 3x3이 아닌 보드로 시도해 보셨습니까?))?
Magic Octopus Urn

@carusocomputing- 'X는 항상 먼저 움직일 것'이라는 것을 명심하십시오. 보드만으로도 어느 쪽이 움직이고 있는지 추론하는 데 사용될 수 있지만 실제로 더 많은 바이트를 소비하는 컴퓨팅; 그래서 당신이 다른 것에 대해 이야기하고 있다고 생각합니다. 예, 약간 더 큰 보드로 테스트를했습니다. 비어있는 위치가 너무 많지 않으면 예상대로 작동합니다. :-)
Arnauld

도전은 말합니다 The current state of the board must be the only input to your program. 코드에는이 규칙을 위반하는 두 개의 입력이 필요합니다.
Dada

1
@Dada-나는 그것에 대해 궁금해했지만 활성 색상 보드 상태의 일부 라고 가정했습니다 (체스 위치가 항상 활성 색상 + enpassant square + castling availability와 같이). 그래서 OP가 그 점을 분명히해야한다고 생각합니다. (그리고 당신이 옳다면, 그것은 불필요한 추가 어려움처럼 들립니다, IMHO.)
Arnauld

1
음 .. 나는 그의 반응에서 보드 상태에 대한 설명을 정말로 좋아한다. 그것을 생각할 때, 일부 lalague는 문자열을 입력으로 만 사용할 수 있으며, XXOOXO-OO와 같은 보드는 보드 크기와 같은 추가 정보가 없으면 적은 바이트 수로 해독하기가 어렵습니다. 보드 상태에 기여하는 추가 입력은 허용하지만, 여전히 'X가 먼저 움직인다고 가정'하는 정보는 '누군가가 그것을 돌려 놓은가'와 다르다고 생각합니다. 일부 언어는이를 가정으로 활용합니다.).
Magic Octopus Urn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.