J'ai vu le "[○ ✕ Game] de @ kei011](https://qiita.com/kei011/items/ea7bce8ce690bd56f9ff)". Le but des débutants est de terminer un programme qui fonctionne par eux-mêmes, c'est donc formidable d'y parvenir et d'afficher les résultats.
Cependant, j'ai été déçu que le code du programme soit commun aux débutants.
J'ai refactoré tout en étant conscient de l'orientation de l'objet. Je suis moi-même en train de refactoriser par essais et erreurs, donc si vous avez d'autres bonnes idées, je vous serais reconnaissant si vous pouviez commenter.
Commencez par lister les choses et les acteurs qui apparaissent dans le "○ ✕ jeu".
Tapez chacun d'eux.
De plus, j'ai tapé la chaîne de caractères string_t et la position point_t où la pierre est placée.
Voici le code source du langage C refactorisé.
tictactoe.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#ifdef __GNUC__
#define scanf_s scanf
#endif
#define SIZE (3) //Taille de la planche (verticale=côté)
typedef enum {
SPACE = '-', //Valeur quand il n'y a pas de pierre sur le plateau
STONE_A = 'A',
STONE_B = 'B',
} stone_t; //Pierre à mettre sur le plateau
typedef stone_t board_t[SIZE][SIZE]; //Planche
typedef int point_t; //Position du tableau xy(0 ~ STEP-1)
typedef int step_t; //Mettre à jour la différence
typedef const char *string_t; //Chaîne
typedef struct player player_t; //Joueurs (personnes et ordinateurs)
struct player {
string_t name;
stone_t stone;
string_t order;
void (*play)(player_t *player, board_t board);
player_t *opponent;
};
//Affichage du tableau
void show(board_t board)
{
printf("★ Tableau actuel ★\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");
}
//Vrai s'il y a une place sur le plateau
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;
}
//Renvoie vrai si la pierre spécifiée suit le tableau et que la ligne est complète
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;
}
//Lorsque la ligne est terminée sur le plateau avec la pierre spécifiée*py, *Définir px et renvoyer true
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) || //côté
follow(board, other, y, x, INCRESE_Y, STAY_X))) { //Verticale
*py = y, *px = x;
return true;
}
}
point_t x = y;
if (board[y][x] == first &&
follow(board, other, y, x, INCRESE_Y, INCRESE_X)) { //En bas à droite
*py = y, *px = y;
return true;
}
x = SIZE - 1 - y;
if (board[y][x] == first &&
follow(board, other, y, x, INCRESE_Y, DECRESE_X)) { //En bas à gauche
*py = y, *px = x;
return true;
}
}
return false;
}
//Si vous êtes à portée de main*px, *Définir py et retourner vrai
bool reach(board_t board, stone_t stone, point_t *py, point_t *px)
{
return line(board, SPACE, stone, py, px);
}
//Renvoie vrai si dans l'état de bingo
bool bingo(board_t board, stone_t stone)
{
point_t y, x;
return line(board, stone, stone, &y, &x);
}
//Entrée de position
point_t input(player_t *player, string_t target)
{
printf("%s:%s(%c)de%Entre dans:", 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"); //Ignorer l'entrée
}
printf("La valeur est incorrecte.\n\n");
return -1;
}
//Les gens jouent(Faites un pas)
void human(player_t *player, board_t board)
{
while (true) {
point_t x = input(player, "côté(x)");
if (x < 0) continue;
point_t y = input(player, "Verticale(y)");
if (y < 0) continue;
if (board[y][x] == SPACE) {
board[y][x] = player->stone;
return;
}
printf("La position spécifiée est incorrecte.\n\n");
}
}
//L'ordinateur joue(Faites un pas)
void computer(player_t *player, board_t board)
{
point_t y, x;
if (reach(board, player->stone, &y, &x)) {
//Choisissez votre portée
} else if (reach(board, player->opponent->stone, &y, &x)) {
//Interférer avec la portée de l'adversaire
} else {
y = 1, x = 1; //milieu
while (board[y][x] != SPACE) {
y = rand() % SIZE, x = 0;
while (x < SIZE - 1 && board[y][x] != SPACE) {
x++;
}
}
}
board[y][x] = player->stone;
}
//Jeu d'alignement SIZE
void game()
{
player_t player1 = { "tu", STONE_A, "Premier coup", human },
player2 = { "Ordinateur", STONE_B, "Deuxième attaque", 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("%la victoire!\n", player->name);
return;
}
player = player->opponent;
}
printf("dessiner!\n");
}
int main(void)
{
srand((unsigned int)time(NULL));
game();
return 0;
}
«M. Board, êtes-vous quelque part? «M. Board, ces trois pierres sont-elles alignées? "Vous, s'il vous plaît, faites un mouvement" "Ordinateur, faites un pas" En pensant à qui vous demandez, ce "qui" est utilisé comme nom de variable et premier argument de la fonction.
J'ai essayé de porter le code source du langage C vers le langage orienté objet Python. Si vous pouvez lire le langage C, vous pouvez lire Python tel quel.
«Qui» est défini comme une classe.
Chaque fonction est attribuée à une classe en tenant compte de qui est le travail.
Puisque "who" est "self" vu de l'intérieur de la classe, le premier argument est le nom de la variable self.
Quand vous voulez appeler une fonction dans une classe, écrivez dans l'ordre de "who.function name (argument)
", et il sera converti en "who, argument) ʻ dans la classe correspondante et appelé. .. Alors laissez le moi être le premier argument. Si vous avez un interpréteur Python3, vous pouvez l'exécuter en tapant
python tictactoe.py` à l'invite de commande.
Je voulais garder l'écriture en langage C telle qu'elle est, donc j'évite autant que possible l'écriture de type Python.
tictactoe.py
from random import randint
SPACE = '-' #Valeur quand il n'y a pas de pierre sur le plateau
class Board(list): # typedef char board_t[3][3]; (list est un tableau)
#Initialisation de la carte (nom spécial déterminé par Python)
def __init__(self):
super().__init__([ [ SPACE, SPACE, SPACE ],
[ SPACE, SPACE, SPACE ],
[ SPACE, SPACE, SPACE ] ])
#Affichage du tableau
def show(self): # void show(board_t board)
print("★ Tableau actuel ★\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]))
#Renvoie true s'il y a une place sur le plateau
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
#Renvoie les coordonnées si les trois pierres spécifiées sont alignées sur le plateau, Aucune si elles ne sont pas alignées
def line(self, stone1, stone2, stone3): #Python peut renvoyer plusieurs valeurs comme valeurs de retour>Réduction d'argument avec
for y in range(3):
for x in range(3):
if (self[y][x] == stone1 and
((self[y][(x + 1) % 3] == stone2 and #Cote à cote
self[y][(x + 2) % 3] == stone3) or
(self[(y + 1) % 3][x] == stone2 and #Verticalement
self[(y + 2) % 3][x] == stone3))):
return (y, x)
if (self[(y + 0) % 3][(y + 0) % 3] == stone1 and #En bas à droite
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 #En bas à gauche
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
#Renvoie la position si atteint, Aucun sinon
def reach(self, stone):
return self.line(SPACE, stone, stone)
#Renvoie vrai si dans l'état de bingo
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):
#Entrée de position
def input(self, target):
try:
point = int(input("%s:%s(%c)de%Entre dans:" % (self.order, self.name, self.stone, target)))
if 0 <= point <= 2:
return point
except ValueError:
pass
print("La valeur est incorrecte.\n")
return -1
#Jouer(Faites un pas)
def play(self, board):
while True:
x = self.input("côté(x)")
if x < 0: continue
y = self.input("Verticale(y)")
if y < 0: continue
if board[y][x] == SPACE:
board[y][x] = self.stone
return
print("La position spécifiée est incorrecte.\n")
class Computer(Player):
#Jouer(Faites un pas)
def play(self, board):
position = board.reach(self.stone) #Votre choix de portée
if position is None:
position = board.reach(self.opponent.stone) #Interférer avec la portée de l'autre partie
if position is None:
y, x = 1, 1 #milieu
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
#Jeu à trois yeux
def main():
player1 = Human("tu", 'A', "Premier coup")
player2 = Computer("Ordinateur", 'B', "Deuxième attaque")
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("%la victoire!" % player.name)
return
player = player.opponent
print("dessiner!")
return
if __name__ == '__main__':
main()
Recommended Posts