Jouons à Othello avec Python.
La carte sera tenue dans un tableau unidimensionnel de taille 64, et les valeurs seront les suivantes.
--0: Espace libre ―― 1: Kurokoma (exprimé par *) ―― 2: Shirakoma (exprimé par o)
python3
import numpy as np
def create_board():
a = np.zeros(64, dtype=int)
a[27] = a[36] = 1
a[28] = a[35] = 2
return a
def print_board(a):
print(' a b c d e f g h')
for i in range(8):
print(i+1, end=' ')
print(' '.join('.*o'[j] for j in a[i*8:][:8]))
a = create_board()
print_board(a)
>>>
a b c d e f g h
1 . . . . . . . .
2 . . . . . . . .
3 . . . . . . . .
4 . . . * o . . .
5 . . . o * . . .
6 . . . . . . . .
7 . . . . . . . .
8 . . . . . . . .
Créez une fonction qui place votre pièce w (1 ou 2) à la position p (0 à 63). Puisque les huit données verticales, horizontales et diagonales sont des données unidimensionnelles, regardez dans la direction déviée de la position actuelle de [-9, -8, -7, -1, 1, 7, 8, 9]. Ceci est vérifié avec une combinaison de [-1, 0, 1] et [-8, 0, 8](à l'exclusion des paires 0 et 0). Si vous sortez le tableau (b) pour chaque direction et multipliez par 0-1 si c'est la pièce de l'adversaire (b == 3-w) cumulativement, les pièces qui peuvent être prises sont représentées par 1, donc si vous prenez le total (somme) , Vous pouvez voir le nombre de pièces n qui peuvent être prises. Mettons-le en position 20 ("e3").
python3
def put_piece(a, p, w, puton=True, chk=True):
t, x, y = 0, p%8, p//8
for di, fi in zip([-1, 0, 1], [x, 7, 7-x]):
for dj, fj in zip([-8, 0, 8], [y, 7, 7-y]):
if not di == dj == 0:
b = a[p+di+dj::di+dj][:min(fi, fj)]
n = (b==3-w).cumprod().sum()
if b.size <= n or b[n] != w: n = 0
t += n
if puton:
b[:n] = w
if puton:
if chk: assert(a[p] == 0 and t > 0)
a[p] = w
return t
put_piece(a, 20, 1)
print_board(a)
>>>
a b c d e f g h
1 . . . . . . . .
2 . . . . . . . .
3 . . . . * . . .
4 . . . * * . . .
5 . . . o * . . .
6 . . . . . . . .
7 . . . . . . . .
8 . . . . . . . .
Pour trouver une bonne main, ajoutez les points suivants avec un poids approprié.
«Vous pouvez en obtenir beaucoup. ――Il y a moins d'endroits pour frapper l'adversaire
python3
def best(a, w):
from math import exp
r, b, c = [], a.copy(), 1+exp(-np.count_nonzero(a)/16)
for i in range(64):
if b[i] != 0: continue
t = put_piece(b, i, w, True, False)
if t == 0:
b[i] = 0
continue
u = sum(b[j]==0 and put_piece(b, j, 3-w, False) > 0 for j in range(64))
r.append((t-c*u+np.random.rand()*0.5, i))
b = a.copy()
return sorted(r)[-1][1] if r else -1
p pour passer, q pour terminer.
python3
if __name__ == '__main__':
a = create_board()
w = 1
while np.count_nonzero(a) < 64:
print_board(a)
s = input('> ')
if not s or s=='q': break
if s != 'p':
try:
x, y = ord(s[0])-97, int(s[1])-1
put_piece(a, x+8*y, w)
except:
continue
p = best(a, 3-w)
if p >= 0:
put_piece(a, p, 3-w)
print_board(a)
n1, n2 = (a==1).sum(), (a==2).sum()
print('%d - %d %s' % (n1, n2,
'You win' if n1 > n2 else
'You lose' if n1 < n2 else 'Draw'))
>>>
a b c d e f g h
1 . . . . . . . .
2 . . . . . . . .
3 . . . . . . . .
4 . . . * o . . .
5 . . . o * . . .
6 . . . . . . . .
7 . . . . . . . .
8 . . . . . . . .
> e3
a b c d e f g h
1 . . . . . . . .
2 . . . . . . . .
3 . . . . * o . .
4 . . . * o . . .
5 . . . o * . . .
6 . . . . . . . .
7 . . . . . . . .
8 . . . . . . . .
> f4
a b c d e f g h
1 . . . . . . . .
2 . . . . . . . .
3 . . . . * o . .
4 . . . * * o . .
5 . . . o o o . .
6 . . . . . . . .
7 . . . . . . . .
8 . . . . . . . .
> g3
a b c d e f g h
1 . . . . . . . .
2 . . . . . . . .
3 . . . . * * * .
4 . . o o o o . .
5 . . . o o o . .
6 . . . . . . . .
7 . . . . . . . .
8 . . . . . . . .
> c5
a b c d e f g h
1 . . . . . . . .
2 . . . . . . . .
3 . . . o * * * .
4 . . o o o o . .
5 . . * o o o . .
6 . . . . . . . .
7 . . . . . . . .
8 . . . . . . . .
>
Vous devriez le lire un peu plus loin.
bash
docker run -it --rm tsutomu7/reversi python reversi.py
Lorsque vous le faites avec un navigateur, procédez comme suit.
bash
firefox http://localhost:8888 &
docker run -it --rm -p 8888:8888 tsutomu7/reversi
c'est tout
Recommended Posts