Ich überarbeitete "Ich habe versucht, Othello AI zu machen, als Programmieranfänger Python studierten"

Ich sah @ keisuke1111s "Anfängerprogrammierung studierte Python, ich habe Othello AI gemacht". Obwohl ich ein Anfänger war, war ich daran interessiert, herausfordernde Probleme anzugehen. Es schien jedoch, dass er große Probleme mit der starken Verwendung globaler Variablen, der redundanten Verarbeitung und der tiefen Verschachtelung hatte, die Anfängern gemeinsam sind. Daher dachte ich, dass dies eine Referenz für die Programmerstellung sein würde, und versuchte daher, jede Rolle so zu klassifizieren, dass keine globalen Variablen verwendet werden, und die Verarbeitung so aufzuteilen, dass eine Funktion oder Methode in 24 Zeilen auf einem Bildschirm des Terminals passt. Ich hoffe, dass es für die zukünftige Programmerstellung nützlich sein wird.

Ich selbst überarbeite durch Versuch und Irrtum. Wenn Sie also andere gute Ideen haben, würde ich mich freuen, wenn Sie einen Kommentar abgeben könnten.

othello.py


#!/usr/bin/env python3
# -*- coding:utf-8 -*-

'''
@author: Keisuke Ueda
http://qiita.com/keisuke1111/items/53353896a957136b1d7e
refactoring by @shiracamus
'''

import time
import random
import copy
 
 
class Othello:
 
    def play(self):
        start_time = time.time()
        board = Board()
        player1 = computer = Computer(BLACK, "PC")
        player2 = user = User(WHITE, "Sie")
        #player1 = user = User(BLACK, "Sie")
        #player2 = computer = Computer(WHITE, "PC")
 
        turn = 0
        hand1 = hand2 = None
        while board.is_playable() and not hand1 == hand2 == "pass":
            turn += 1
            print("TURN = %s" % turn)
 
            print(board)
            hand1 = player1.play(board)
            print("%s Hand: %s" % (player1.name, hand1))
 
            print(board)
            hand2 = player2.play(board)
            print("%s Hand: %s" % (player2.name, hand2))
 
        self.show_result(board)
 
        end_time = time.time()
        print("Spielzeit:" + str(end_time - start_time))
 
    def show_result(self, board):
        print("------------------RESULT-------------------")  #Ergebnisansage
        print(board)
        computer_stones = board.count(computer.stone)
        user_stones = board.count(user.stone)
        print("Computer: %s" % computer_stones)
        print("You: %s" % user_stones)
        print()
        if computer_stones > user_stones:
            print("YOU LOST!!!!!")
        elif computer_stones < user_stones:
            print("YOU WON!!!!!")
        else:
            print("DRAW")
 
 
class Stone(str):
    pass
 
BLACK = Stone("●")
WHITE = Stone("○")
BLANK = Stone("×")
OPPONENT = {BLACK: WHITE, WHITE: BLACK}
 
 
class Board:
    SIZE = 8
    DIRECTIONS_XY = ((-1, -1), (+0, -1), (+1, -1),
                     (-1, +0),           (+1, +0),
                     (-1, +1), (+0, +1), (+1, +1))
 
    def __init__(self):
        size = self.SIZE
        center = size // 2
        square = [[BLANK for y in range(size)] for x in range(size)]  #Definieren Sie das erste Board
        square[center - 1][center - 1:center + 1] = [WHITE, BLACK]
        square[center + 0][center - 1:center + 1] = [BLACK, WHITE]
        self.square = square
 
    def __str__(self):
        return '\n'.join(''.join(row) for row in self.square)
 
    def __getitem__(self, x):
        return self.square[x]
 
    def is_playable(self):
        return any(col != BLANK
                   for row in self.square
                   for col in row)
 
    def count(self, stone):         #Eine Funktion, die zurückgibt, wie viele Steine es gibt
        return sum(col == stone     # True is 1, False is 0
                   for row in self.square
                   for col in row)
 
    def put(self, x, y, stone):     # y,x ist die Koordinate des zu platzierenden Steins und Stein ist WEISS oder SCHWARZ.
        self[x][y] = stone
        # reverse
        for dx, dy in Board.DIRECTIONS_XY:
            n = self.count_reversible(x, y, dx, dy, stone)
            for i in range(1, n + 1):
                self[x + i * dx][y + i * dy] = stone
 
    def count_reversible(self, x, y, dx, dy, stone):
        size = self.SIZE
        for n in range(size):
            x += dx
            y += dy
            if not (0 <= x < size and 0 <= y < size):
                return 0
            if self[x][y] == BLANK:
                return 0
            if self[x][y] == stone:
                return n
        return 0
 
    def is_available(self, x, y, stone):
        if self[x][y] != BLANK:
            return False
        return any(self.count_reversible(x, y, dx, dy, stone) > 0
                   for dx, dy in self.DIRECTIONS_XY)
 
    def availables(self, stone):  #Auf der Suche nach einem Treffpunkt
        return [(x, y)
                for x in range(self.SIZE)
                for y in range(self.SIZE)
                if self.is_available(x, y, stone)]
 
 
class Player:   # abstract class
 
    def __init__(self, stone, name):
        self.stone = stone
        self.name = name
 
    def play(self, board):
        availables = board.availables(self.stone)
        if not availables:
            return "pass"
        return self.think(board, availables)
 
 
class Computer(Player):
 
    def think(self, board, availables):
        starttime = time.time()
        print(availables)
        print("thinking……")
        own = self.stone
        opponent = OPPONENT[own]
        evaluations, x, y = AlphaBeta(board, availables, own, opponent)
        print(evaluations)
        board.put(x, y, self.stone)
        endtime = time.time()
        interval = endtime - starttime
        print("%s Sekunden" % interval)  #Berechnungszeit anzeigen
        return x, y
 
 
class User(Player):
 
    def think(self, board, availables):
        while True:
            print("Wo du schlagen kannst(Y, X): " + str(availables))   #Intern x,X wird als y angezeigt,Beachten Sie, dass Y das Gegenteil ist
            try:
                line = input("Y X or quit: ")
            except:
                print("erzwungene Kündigung")
                exit(1)
            if line == "quit" or line == "exit":
                print("Ende der Aufgabe")
                exit(1)
            try:
                x, y = map(int, line.split())
                if (x, y) in availables:
                    board.put(x, y, self.stone)
                    return x, y
                else:
                    print("Kann nicht dort setzen")
            except:
                print("Unbekannt")
 
 
def AlphaBeta(board, availables, own, opponent):  #Suche nach Alpha Beta-Methode
    evaluations = AlphaBeta_evaluate1(board, availables, own, opponent)
    maximum_evaluation_index = evaluations.index(max(evaluations))
    x, y = availables[maximum_evaluation_index]
    return evaluations, x, y
 
def AlphaBeta_evaluate1(board, availables, own, opponent):
    def pruning2(max_evaluations3):
        return len(evaluations1) > 0 and max(evaluations1) >= max_evaluations3
    evaluations1 = []
    for x, y in availables:
        board1 = copy.deepcopy(board)
        board1.put(x, y, own)
        evaluations2 = AlphaBeta_evaluate2(board1, own, opponent, pruning2)
        if len(evaluations2) > 0:
            evaluations1 += [min(evaluations2)]
    return evaluations1
 
def AlphaBeta_evaluate2(board, own, opponent, pruning):
    def pruning3(min_evaluations4):
        return len(evaluations2) > 0 and min(evaluations2) <= min_evaluations4
    evaluations2 = []
    for x, y in board.availables(opponent):
        board2 = copy.deepcopy(board)
        board2.put(x, y, opponent)
        evaluations3 = AlphaBeta_evaluate3(board2, own, opponent, pruning3)
        if len(evaluations3) > 0:
            max_evaluations3 = max(evaluations3)
            evaluations2 += [max_evaluations3]
            if pruning(max_evaluations3):
                break
    return evaluations2
 
def AlphaBeta_evaluate3(board, own, opponent, pruning):
    def pruning4(max_evaluations5):
        return len(evaluations3) > 0 and max(evaluations3) >= max_evaluations5
    evaluations3 = []
    for x, y in board.availables(own):
        board3 = copy.deepcopy(board)
        board3.put(x, y, own)
        evaluations4 = AlphaBeta_evaluate4(board3, own, opponent, pruning4)
        if len(evaluations4) > 0:
            min_evaluations4 = min(evaluations4)
            evaluations3 += [min_evaluations4]
            if pruning(min_evaluations4):
                break
    return evaluations3
 
def AlphaBeta_evaluate4(board, own, opponent, pruning):
    def pruning5(evaluation5):
        return len(evaluations4) > 0 and min(evaluations4) <= evaluation5
    evaluations4 = []
    for x, y in board.availables(opponent):
        board4 = copy.deepcopy(board)
        board4.put(x, y, opponent)
        evaluations5 = AlphaBeta_evaluate5(board4, own, opponent, pruning5)
        if len(evaluations5) > 0:
            max_evaluation5 = max(evaluations5)
            evaluations4 += [max_evaluation5]
            if pruning(max_evaluation5):
                break
    return evaluations4
 
def AlphaBeta_evaluate5(board, own, opponent, pruning):
    evaluations5 = []
    for x, y in board.availables(own):
        board5 = copy.deepcopy(board)
        board5.put(x, y, own)
        ev_own = evaluate(board5, own)
        ev_opponent = evaluate(board5, opponent)
        evaluation = ev_own - ev_opponent
        evaluations5 += [evaluation]
        if pruning(evaluation):
            break
    return evaluations5
     

# pp = [45,-11,-16,4,-1,2,-1,-3,-1,0]
EVALUATION_BOARD = (  #Bewertungsgremium, das zeigt, wie viele Punkte sich auf welchem Quadrat befinden
    ( 45, -11,  4, -1, -1,  4, -11,  45),
    (-11, -16, -1, -3, -3, -1, -16, -11),
    (  4,  -1,  2, -1, -1,  2,  -1,   4),
    ( -1,  -3, -1,  0,  0, -1,  -3,  -1),
    ( -1,  -3, -1,  0,  0, -1,  -3,  -1),
    (  4,  -1,  2, -1, -1,  2,  -1,   4),
    (-11, -16, -1, -3, -3, -1, -16, -11),
    ( 45, -11,  4, -1, -1,  4, -11,  45))
 
def evaluate(board, stone):  #Berechnen Sie den Bewertungswert eines Steins auf einem beliebigen Brett
    bp = 0
    for x in range(board.SIZE):
        for y in range(board.SIZE):
            if board[x][y] == BLANK:
                pass
            elif board[x][y] == stone:
                bp += EVALUATION_BOARD[x][y] * random.random() * 3
            else:
                bp -= EVALUATION_BOARD[x][y] * random.random() * 3
 
    p = confirm_stone(board, stone)
    q = confirm_stone(board, OPPONENT[stone])
    fs = ((p - q) + random.random() * 3) * 11
 
    b = board.availables(stone)
    cn = (len(b) + random.random() * 2) * 10
 
    evaluation = bp * 2 + fs * 5 + cn * 1
    return evaluation
 
def confirm_stone(board, stone):  #Zählen Sie die Anzahl der bestätigten Steine
    forward = range(0, board.SIZE)
    backward = range(board.SIZE - 1, -1, -1)
    corners = ((+0, +0, forward, forward),
               (+0, -1, forward, backward),
               (-1, +0, backward, forward),
               (-1, -1, backward, backward))
    confirm = 0
    for x, y, rangex, rangey in corners:
        for ix in rangex:
            if board[ix][y] != stone:
                break
            confirm += 1
        for iy in rangey:
            if board[x][iy] != stone:
                break
            confirm += 1
    return confirm
 
 
if __name__ == '__main__':
    Othello().play()

Recommended Posts

Ich überarbeitete "Ich habe versucht, Othello AI zu machen, als Programmieranfänger Python studierten"
Ich habe versucht, KI für Smash Bra zu machen
[Python] Ich habe versucht, eine Shiritori-KI zu erstellen, die den Wortschatz durch Schlachten verbessert
Als ich versuchte, Python3 in Atom einzuführen, blieb ich stecken
Python, das ich Anfängern in der Programmierung empfehlen möchte
Fortsetzung ・ Ich habe versucht, Slackbot zu erstellen, nachdem ich Python3 studiert habe
Ich habe versucht, mit Python faker verschiedene "Dummy-Daten" zu erstellen
Ich habe versucht, Python zu berühren (Installation)
Ich habe versucht, Othello AI zu machen, dass ich 7,2 Millionen Hände durch tiefes Lernen mit Chainer gelernt habe
Python-Anfänger versuchten es herauszufinden
[5.] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
Ich habe versucht, die Anfängerausgabe des Ameisenbuchs mit Python zu lösen
[2nd] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
Ich habe versucht, mit Python einen regulären Ausdruck für "Betrag" zu erstellen
[Python] Ich habe versucht, eine stabile Sortierung zu implementieren
Ich habe versucht, mit Python einen regulären Ausdruck von "Zeit" zu erstellen
[3.] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
Ich habe versucht, mit Python einen regulären Ausdruck von "Datum" zu erstellen
[Pandas] Ich habe versucht, Verkaufsdaten mit Python zu analysieren. [Für Anfänger]
Ich habe versucht, mit Selenium und Python einen regelmäßigen Ausführungsprozess durchzuführen
Ich habe versucht, mit Python eine 2-Kanal-Post-Benachrichtigungsanwendung zu erstellen
[Einführung] Ich möchte mit Python einen Mastodon-Bot erstellen! 【Anfänger】
Ich habe versucht, eine ToDo-App mit einer Flasche mit Python zu erstellen
[4.] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
[Python] Einfaches Japanisch ⇒ Ich habe versucht, ein englisches Übersetzungswerkzeug zu erstellen
[1.] Ich habe versucht, mit Python ein bestimmtes Authenticator-ähnliches Tool zu erstellen
Ich habe versucht, unerfahrenen Programmierern Python beizubringen
Ich habe versucht, mit Python + OpenCV eine Bildähnlichkeitsfunktion zu erstellen
Ich habe versucht, Othello AI mit Tensorflow zu machen, ohne die Theorie des maschinellen Lernens zu verstehen ~ Einführung ~
Ich habe versucht, Othello AI mit Tensorflow zu erstellen, ohne die Theorie des maschinellen Lernens zu verstehen ~ Implementierung ~
Ich habe versucht, die Behandlung von Python-Ausnahmen zusammenzufassen
Ich habe versucht, PLSA in Python zu implementieren
Ich habe Othello dazu gebracht, Kindern Python3 beizubringen (4)
[Episode 2] Anfänger haben Numeron AI mit Python ausprobiert
[Episode 3] Anfänger haben Numeron AI mit Python ausprobiert
Ich habe versucht, PLSA in Python 2 zu implementieren
Python3-Standardeingabe habe ich versucht zusammenzufassen
Ich habe Othello dazu gebracht, Kindern Python3 beizubringen (5)
Ich habe versucht, ADALINE in Python zu implementieren
[Episode 0] Anfänger haben Numeron AI mit Python ausprobiert
[Episode 1] Anfänger haben Numeron AI mit Python ausprobiert
Ich habe versucht, PPO in Python zu implementieren
Ich habe eine Web-API erstellt
[Python] Ich habe versucht, TF-IDF stetig zu berechnen
Ich habe versucht, Python zu berühren (grundlegende Syntax)
Ich habe Othello dazu gebracht, Kindern Python3 beizubringen (3)
Ich habe Othello dazu gebracht, Kindern Python3 beizubringen (1)
Ich habe versucht, eine Gesichtsdiagnose-KI für professionelle Golferinnen zu erstellen ①
[AWS] [GCP] Ich habe versucht, die Verwendung von Cloud-Diensten mit Python zu vereinfachen
Ich habe versucht, mit Raspeye 4 (Python Edition) ein signalähnliches Signal zu erzeugen.
[Zaif] Ich habe versucht, den Handel mit virtuellen Währungen mit Python zu vereinfachen
[Python] Als ich versuchte, ein Dekomprimierungswerkzeug mit einer Zip-Datei zu erstellen, die ich gerade kannte, war ich süchtig nach sys.exit ()
Ich habe versucht, Othello AI mit Tensorflow zu erstellen, ohne die Theorie des maschinellen Lernens zu verstehen ~ Battle Edition ~
Ich habe versucht, nächstes Jahr mit AI vorherzusagen
Ich habe versucht, einen periodischen Prozess mit CentOS7, Selenium, Python und Chrome durchzuführen
[Python] Ich habe versucht, 100 frühere Fragen zu lösen, die Anfänger und Fortgeschrittene lösen sollten [Teil 5/22]
Ich habe eine einfache Mail-Sendeanwendung mit tkinter von Python erstellt
[Python] Ich habe versucht, 100 frühere Fragen zu lösen, die Anfänger und Fortgeschrittene lösen sollten [Teil 7/22]
Als ich versuchte, eine VPC mit AWS CDK zu erstellen, konnte ich es aber nicht schaffen
KI-Anfänger versuchen, professionelle Studenten Bot zu machen