Python 2: 399 401 349 333 317 370 bajtów
2x Bug Bug: kredyt na poziomie 4 m2
-52 znaki: zaliczenie do podziemnej kolejki
-16 znaków: podziękowania dla Jonathana Frecha
-26 znaków: kredyt dla użytkownika202729
def f(b):
t=4,9,2,3,5,7,8,1,6;n=lambda k:[t[i]for i,j in enumerate(b)if j==k];p,o,a,I=n(2),n(1),n(0),t.index
for i in p:
for j in p:
for k in a:
if i+j+k==15and-j+i:return I(k)
for i in o:
for j in o:
for k in a:
if i+j+k==15and-j+i:return I(k)
for i in 9,3,7,1:
if i in a and 5 in p:return I(i)
for i in 5,4,2,8,6:
if i in a:return I(i)
return I(a[0])
Wypróbuj online!
Pierwszego dnia kursu algebry liniowej, który odbyłem w ostatnim semestrze, mój bystry absolwent instruktor zaproponował, że jeśli reprezentujesz tablicę kółko i krzyżyk jako matrycę:
4 | 9 | 2
--+---+--
3 | 5 | 7
--+---+--
8 | 1 | 6
zdobycie trzech z rzędu jest równoznaczne z wybraniem trzech liczb z zakresu [1,9], które sumują się do 15. Ta odpowiedź wykorzystuje ten pomysł. Funkcja przyjmuje listę zawierającą dziewięć liczb reprezentujących tablicę. 0 oznacza puste miejsce, 1 jest zajęty przez przeciwnika, a 2 oznacza poprzednią grę wykonaną przez program. Pierwsze 3 linie wyjaśniają, jakie numery wybrał program (p), przeciwnik wybrał (o) i są nadal dostępne (a). Następnie przegląda dostępne liczby i sprawdza, czy któryś z nich, w połączeniu z dwoma wybranymi przez siebie liczbami, dodaje do piętnastu. Jeśli tak, wybierze ten kwadrat i wygra. Jeśli nie ma natychmiastowych zwycięskich ruchów, sprawdzi, czy przeciwnik może wygrać przy użyciu tej samej metody. Jeśli mogą, zajmie ich zwycięski kwadrat. Jeśli nie jest dostępny ruch wygrywający ani blokujący, poruszy się w kącie. Zapobiega to głupcom:
- - -
- X -
- - -
- O - # Bad Move
- X -
- - -
- O X
- X -
- - -
- O X
- X -
O - -
- O X
- X -
O - X
Jeśli żadna z tych sytuacji nie wystąpi, wybierze kwadrat arbitralnie. Funkcja generuje liczbę [0,8] reprezentującą kwadrat indeksowany 0 wybrany przez algorytm.
Edycja: Algorytm priorytetowo traktuje teraz środek nad przekątną, co zapobiegnie kolejnej możliwości głupców wskazanej przez l4m2 i powiązane strategie.
Edycja: Aby wyjaśnić, funkcja przyjmuje tablicę w postaci tablicy i wysyła ruch jako liczbę całkowitą na [0,8]. Ponieważ ta strategia we / wy jest tak niezgrabna, oto skrypt opakowujący, który czyni ją bardziej interaktywną. Wymaga pojedynczego argumentu linii poleceń, który powinien wynosić 1, jeśli gracz idzie pierwszy, i 0, jeśli program idzie pierwszy.
import sys
def f(b):
t=4,9,2,3,5,7,8,1,6;n=lambda k:[t[i]for i,j in enumerate(b)if j==k];p,o,a,I=n(2),n(1),n(0),t.index
for i in p:
for j in p:
for k in a:
if i+j+k==15and-j+i:return I(k)
for i in o:
for j in o:
for k in a:
if i+j+k==15and-j+i:return I(k)
for i in 9,3,7,1:
if i in a and 5 in p:return I(i)
for i in 5,4,2,8,6:
if i in a:return I(i)
return I(a[0])
board = [0,0,0,0,0,0,0,0,0]
rep = {0:"-",1:"X",2:"O"}
turn = int(sys.argv[1])
while True:
for i in range(3):
print rep[board[i*3]]+" "+rep[board[i*3+1]]+" "+rep[board[i*3+2]]
print
if turn:
move = int(raw_input("Enter Move [0-8]: "))
else:
move = f(board)
board[move] = turn+1
turn = (turn+1)%2
we can assume that all previous moves of the 2nd player were also played by our engine