Objektorientiert in C-Sprache: "○ ✕ game" wurde überarbeitet und nach Python portiert

Auslösen

Ich habe @ kei011s "○ ✕ Spiel" gesehen. Der Zweck von Anfängern ist es, ein Programm zu absolvieren, das selbstständig funktioniert. Es ist also großartig, dies zu erreichen und die Ergebnisse zu veröffentlichen.

Ich war jedoch enttäuscht, dass der Programmcode Anfängern gemeinsam ist.

Refactoring

Ich habe mich umgestaltet, während ich mir der Objektorientierung bewusst war. 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.

Listen Sie zunächst die Dinge und Akteure auf, die im "○ ✕ Spiel" erscheinen.

Geben Sie jeden ein.

Außerdem habe ich die Zeichenkette string_t und die Position point_t, an der der Stein platziert ist, eingegeben.

Quellcode in C-Sprache

Hier ist der überarbeitete Quellcode der C-Sprache.

tictactoe.c


#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>

#ifdef __GNUC__
#define scanf_s scanf
#endif

#define SIZE (3)                        //Brettgröße (vertikal)=Seite)
typedef enum {
    SPACE   = '-',                      //Wert, wenn kein Stein auf dem Brett ist
    STONE_A = 'A',
    STONE_B = 'B',
} stone_t;                              //Stein zum Anbringen auf dem Brett
typedef stone_t board_t[SIZE][SIZE];    //Tafel
typedef int point_t;                    //Board xy Position(0 ~ STEP-1)
typedef int step_t;                     //Unterschied aktualisieren
typedef const char *string_t;           //String

typedef struct player player_t; //Spieler (Menschen und Computer)
struct player {
    string_t name;
    stone_t stone;
    string_t order;
    void (*play)(player_t *player, board_t board);
    player_t *opponent;
};

//Board-Anzeige
void show(board_t board)
{
    printf("★ Aktuelle Tabelle ★\n"
           "\n  x");
    for (point_t x = 0; x < SIZE; x++) {
        printf(" %2d", x);
    }
    printf("\n y -");
    for (point_t x = 0; x < SIZE; x++) {
        printf("---");
    }
    for (point_t y = 0; y < SIZE; y++) {
        printf("\n%2d| ", y);
        for (point_t x = 0; x < SIZE; x++) {
            printf(" %c ", board[y][x]);
        }
    }
    printf("\n");
}

//Stimmt, wenn es einen Platz auf dem Brett gibt
bool space(board_t board)
{
    for (point_t y = 0; y < SIZE; y++) {
        for (point_t x = 0; x < SIZE; x++) {
            if (board[y][x] == SPACE) {
                return true;
            }
        }
    }
    return false;
}

//Gibt true zurück, wenn der angegebene Stein dem Brett folgt und die Zeile vollständig ist
bool follow(board_t board, stone_t stone, point_t y, point_t x, step_t dy, step_t dx)
{
    for (step_t i = 1; i < SIZE; i++) {
        y = (y + dy + SIZE) % SIZE;
        x = (x + dx + SIZE) % SIZE;
        if (board[y][x] != stone) {
            return false;
        }
    }
    return true;
}

//Wenn die Linie auf dem Brett mit dem angegebenen Stein abgeschlossen ist*py, *Setze px und gib true zurück
bool line(board_t board, stone_t first, stone_t other, point_t *py, point_t *px) {
    const step_t INCRESE_Y = 1, INCRESE_X = 1, DECRESE_X = -1, STAY_Y = 0, STAY_X = 0;
    for (point_t y = 0; y <SIZE ; y++) {
        for (point_t x = 0; x < SIZE; x++) {
            if (board[y][x] == first &&
                (follow(board, other, y, x, STAY_Y, INCRESE_X) ||   //Seite
                 follow(board, other, y, x, INCRESE_Y, STAY_X))) {  //Vertikal
                *py = y, *px = x;
                return true;
            }
        }
        point_t x = y;
        if (board[y][x] == first &&
            follow(board, other, y, x, INCRESE_Y, INCRESE_X)) {  //Unten rechts
            *py = y, *px = y;
            return true;
        }
        x = SIZE - 1 - y;
        if (board[y][x] == first &&
            follow(board, other, y, x, INCRESE_Y, DECRESE_X)) { //Unten links
            *py = y, *px = x;
            return true;
        }
    }
    return false;
}

//Wenn Sie in Reichweite sind*px, *Setze py und gib true zurück
bool reach(board_t board, stone_t stone, point_t *py, point_t *px)
{
    return line(board, SPACE, stone, py, px);
}

//Gibt true zurück, wenn sich der Bingo-Status befindet
bool bingo(board_t board, stone_t stone)
{
    point_t y, x;
    return line(board, stone, stone, &y, &x);
}

//Positionseingabe
point_t input(player_t *player, string_t target)
{
    printf("%s:%s(%c)von%Geben Sie s ein:", player->order, player->name, player->stone, target);
    point_t point;
    switch (scanf_s("%d", &point)) {
    case EOF:
        exit(1);
    case 1:
        if (0 <= point && point < SIZE) {
            return point;
        }
        break;
    default:
        scanf("%*s");  //Eingabe verwerfen
    }
    printf("Der Wert ist falsch.\n\n");
    return -1;
}

//Menschen spielen(Mach einen Schritt)
void human(player_t *player, board_t board)
{
    while (true) {
        point_t x = input(player, "Seite(x)");
        if (x < 0) continue;
        point_t y = input(player, "Vertikal(y)");
        if (y < 0) continue;
        if (board[y][x] == SPACE) {
            board[y][x] = player->stone;
            return;
        }
        printf("Die angegebene Position ist falsch.\n\n");
    }
}

//Computer spielt(Mach einen Schritt)
void computer(player_t *player, board_t board)
{
    point_t y, x;
    if (reach(board, player->stone, &y, &x)) {
        //Wählen Sie Ihre Reichweite
    } else if (reach(board, player->opponent->stone, &y, &x)) {
        //Beeinträchtigen Sie die Reichweite des Gegners
    } else {
        y = 1, x = 1;  //Mitte
        while (board[y][x] != SPACE) {
            y = rand() % SIZE, x = 0;
            while (x < SIZE - 1 && board[y][x] != SPACE) {
                x++;
            }
        }
    }
    board[y][x] = player->stone;
}

//SIZE Alignment-Spiel
void game() 
{
    player_t player1 = { "Sie",       STONE_A, "Erstschlag", human    },
             player2 = { "Computer", STONE_B, "Zweiter Angriff", computer },
             *player = &player1;
    player1.opponent = &player2;
    player2.opponent = &player1;
    board_t board;
    for (point_t y = 0; y < SIZE; y++) {
        for (point_t x = 0; x < SIZE; x++) {
            board[y][x] = SPACE;
        }
    }
    show(board);
    while (space(board)) {
        player->play(player, board);
        show(board);
        if (bingo(board, player->stone)) {
            printf("%s Sieg!\n", player->name);
            return;
        }
        player = player->opponent;
    }
    printf("zeichnen!\n");
}

int main(void)
{
    srand((unsigned int)time(NULL));

    game();

    return 0;
}

"Mr. Board, sind Sie irgendwo?" "Mr. Board, sind diese drei Steine in einer Reihe?" "Du, bitte mach einen Zug" "Computer, mach einen Schritt" Wenn Sie darüber nachdenken, wen Sie fragen, wird "who" als Variablenname und erstes Argument der Funktion verwendet.

Python-Port

Ich habe versucht, den Quellcode der C-Sprache in die objektorientierte Sprache Python zu portieren. Wenn Sie die Sprache C lesen können, können Sie Python so lesen, wie es ist. "Wer" ist als Klasse definiert. Jede Funktion ist einer Klasse zugeordnet, die berücksichtigt, wer der Job ist. Da "who" aus der Klasse betrachtet "self" ist, ist das erste Argument der Variablenname self. Wenn Sie eine Funktion in einer Klasse aufrufen möchten, schreiben Sie in der Reihenfolge "who.function name (argument)", und sie wird in der entsprechenden Klasse in "who, argument) "konvertiert und aufgerufen. .. Also lass dich selbst das erste Argument sein. Wenn Sie einen Python3-Interpreter haben, können Sie ihn ausführen, indem Sie an der Eingabeaufforderungpython tictactoe.py` eingeben. Ich wollte die C-Sprache so lassen, wie sie ist, deshalb vermeide ich Python-ähnliches Schreiben so weit wie möglich.

tictactoe.py


from random import randint

SPACE = '-'    #Wert, wenn kein Stein auf dem Brett ist


class Board(list):  # typedef char board_t[3][3]; (Liste ist ein Array)

    #Board-Initialisierung (spezieller Name von Python festgelegt)
    def __init__(self):
        super().__init__([ [ SPACE, SPACE, SPACE ],
                           [ SPACE, SPACE, SPACE ],
                           [ SPACE, SPACE, SPACE ] ])

    #Board-Anzeige
    def show(self):  # void show(board_t board)
        print("★ Aktuelle Tabelle ★\n\n"
              "  x 0 1 2\n"
              " y -------")
        for y in range(3):
            print(" %d| %c %c %c" % (y, self[y][0], self[y][1], self[y][2]))

    #Geben Sie true zurück, wenn sich ein Platz auf dem Brett befindet
    def space(self):  # bool_t space(board_t board)
        for y in range(3):
            for x in range(3):
                if self[y][x] == SPACE:
                    return True
        return False

    #Gibt die Koordinaten zurück, wenn die angegebenen drei Steine auf dem Brett ausgerichtet sind. Keine, wenn sie nicht ausgerichtet sind
    def line(self, stone1, stone2, stone3):  #Python kann mehrere Werte als Rückgabewerte zurückgeben>Argumentreduktion mit
        for y in range(3):
            for x in range(3):
                if (self[y][x] == stone1 and
                    ((self[y][(x + 1) % 3] == stone2 and  #Seite an Seite
                      self[y][(x + 2) % 3] == stone3) or
                     (self[(y + 1) % 3][x] == stone2 and  #Vertikal
                      self[(y + 2) % 3][x] == stone3))):
                    return (y, x)
            if (self[(y + 0) % 3][(y + 0) % 3] == stone1 and  #Unten rechts
                self[(y + 1) % 3][(y + 1) % 3] == stone2 and
                self[(y + 2) % 3][(y + 2) % 3] == stone3):
                return (y, y)
            if (self[(y + 0) % 3][(2 - y + 3) % 3] == stone1 and  #Unten links
                self[(y + 1) % 3][(1 - y + 3) % 3] == stone2 and
                self[(y + 2) % 3][(0 - y + 3) % 3] == stone3):
                return (y, (2 - y + 3) % 3)
        return None

    #Gibt die Position zurück, wenn erreicht, Keine, wenn nicht
    def reach(self, stone):
        return self.line(SPACE, stone, stone)

    #Gibt true zurück, wenn sich der Bingo-Status befindet
    def bingo(self, stone):
        return self.line(stone, stone, stone) is not None


class Player:

    def __init__(self, name, stone, order):
        self.name = name
        self.stone = stone
        self.order = order


class Human(Player):

    #Positionseingabe
    def input(self, target):
        try:
            point = int(input("%s:%s(%c)von%Geben Sie s ein:" % (self.order, self.name, self.stone, target)))
            if 0 <= point <= 2:
                return point
        except ValueError:
            pass
        print("Der Wert ist falsch.\n")
        return -1

    #Spielen(Mach einen Schritt)
    def play(self, board):
        while True:
            x = self.input("Seite(x)")
            if x < 0: continue
            y = self.input("Vertikal(y)")
            if y < 0: continue
            if board[y][x] == SPACE:
                board[y][x] = self.stone
                return
            print("Die angegebene Position ist falsch.\n")


class Computer(Player):

    #Spielen(Mach einen Schritt)
    def play(self, board):
        position = board.reach(self.stone)  #Ihre Reichweite Wahl
        if position is None:
            position = board.reach(self.opponent.stone)  #Beeinträchtigung der Reichweite der anderen Partei
        if position is None:
            y, x = 1, 1  #Mitte
            while board[y][x] != SPACE:
                y, x = randint(0, 2), 0
                while x < 2 and board[y][x] != SPACE:
                    x += 1
            position = (y, x)
        y, x = position
        board[y][x] = self.stone


#Dreiäugiges Spiel
def main():
    player1 = Human("Sie", 'A', "Erstschlag")
    player2 = Computer("Computer", 'B', "Zweiter Angriff")
    player = player1
    player1.opponent = player2
    player2.opponent = player1
    board = Board()
    board.show()
    while board.space():
        player.play(board)
        board.show()
        if board.bingo(player.stone):
            print("%s Sieg!" % player.name)
            return
        player = player.opponent
    print("zeichnen!")
    return

if __name__ == '__main__':
    main()

Recommended Posts

Objektorientiert in C-Sprache: "○ ✕ game" wurde überarbeitet und nach Python portiert
So generieren Sie eine Sequenz in Python und C ++
Versuchen Sie es mit GUI, PyQt in Python
So verpacken Sie C in Python
So installieren Sie OpenCV in Cloud9 und führen es in Python aus
Implementieren Sie den FIR-Filter in Python und C.
Schreiben Sie die O_SYNC-Datei in C und Python
Verwendung ist und == in Python
Verwendung der C-Bibliothek in Python
Was ist "funktionale Programmierung" und "objektorientiert"? Python Edition
POST JSON mit Python und empfange mit PHP
Zur Darstellung von Datum, Uhrzeit, Uhrzeit und Sekunden in Python
Wie man Autokorrelation und partielle Autokorrelation mit Python zeichnet
Lösen mit Ruby, Perl, Java und Python AtCoder ARC 086 C Hash-Sortierung
[Python] So benennen Sie Tabellendaten und geben sie mit csv aus (to_csv-Methode)
Weiter Python in C-Sprache
Beachten Sie, dass cibuildwheel das Python-Rad (einschließlich des C ++ - Moduls) in großen Mengen mit CI erstellt und auf PyPI hochlädt
C-API in Python 3
Konvertieren Sie Datum und Uhrzeit in Zeitzonen in Unixtime in Python2.7
Versuchen Sie, ein Python-Modul in C-Sprache zu erstellen
Schreiben Sie Tests in Python, um die Abdeckung zu profilieren und zu überprüfen
[Python] So sortieren Sie Diktate in Listen und Instanzen in Listen
Wie man Decorator in Django benutzt und wie man es macht
Python: Kann in Lambda wiederholt werden
Gehen Sie in die Sprache, um Teil 7 C in der Sprache GO zu sehen und sich daran zu erinnern
Python-Skript, das das Azure-Status-RSS crawlt und an Hipchat sendet
Ich möchte die Variablen in der Python-Vorlagendatei ersetzen und in einer anderen Datei in Massenproduktion herstellen
Es ist einfach, SQL mit Python auszuführen und das Ergebnis in Excel auszugeben
Ein Skript, das bis zu 5 Sekunden zählt und in Blenders Python stoppt
[C / C ++] Übergeben Sie den in C / C ++ berechneten Wert an eine Python-Funktion, um den Prozess auszuführen, und verwenden Sie diesen Wert in C / C ++.
So löschen Sie stdout in Python
So tauschen Sie Elemente in einem Array in Python aus und wie kehren Sie ein Array um.
Anwendung zum Anzeigen und Durchsuchen lokaler Memos (Tagebuch) in Python
Melden Sie sich auf der Website in Python an
Lösen Sie die Wortanzahl (entspricht Paiza Rang C) in Python
Überlegen Sie, ob das Programmieren in Python und C ein Anime war
[Einführung in die Udemy Python3 + -Anwendung] 36. Verwendung von In und Not
Zeigen Sie Zahlen und Zeichen an, die Variablen im Python-Druck zugewiesen sind
Tipps zum Codieren kurz und einfach in Python zu lesen
Rufen Sie die Excel-Liste rekursiv in einem bestimmten Ordner mit Python ab und schreiben Sie sie in Excel.
Binäre Suche in Python / C ++
Eine Standardmethode zum Entwickeln und Verteilen von Paketen in Python
Ich habe versucht, die Zeit und die Zeit der C-Sprache zu veranschaulichen
Nützliche Tricks in Bezug auf Listen und Anweisungen in Python
[Python] Ich habe das Spiel von pip installiert und versucht zu spielen
Vergleich der Verwendung von Funktionen höherer Ordnung in Python 2 und 3
Stapel und Warteschlange in Python
Sprechen mit Python [Text zu Sprache]
Der Prozess, Python-Code objektorientiert zu machen und zu verbessern
Lesen Sie json mit C # und konvertieren Sie es in den Wörterbuchtyp (erzwungen)
Einführung in die Effektüberprüfung Schreiben der Kapitel 4 und 5 in Python
Unittest und CI in Python
Wie man in Python entwickelt
Ausführen externer Shell-Skripte und -Befehle in Python
Installieren Sie CaboCha in der Ubuntu-Umgebung und rufen Sie es mit Python auf.
Versuchen Sie einfach, einen Webhook mit ngrok und Python zu erhalten
Ich habe versucht, das Blackjack of Trump-Spiel mit Python zu implementieren
Eine einfache Möglichkeit, die in Python benötigte Zeit anzuzeigen und sie intelligenter zu verbessern
Löse Fizz Buzz (entspricht Paiza Rang C) in Python