RETROGICIEL
TIC TAC TOE
RETROGICIEL
TIC TAC TOE
⇩. Présentation
Le tic-tac-toe, morpion ou OXO, est un jeu de stratégie simple qui se joue sur une grille de 3 x 3 cases où deux joueurs s'affrontent. Chaque joueur choisit une marque, en général O et X. A tour de role les joueurs place son symbole sur un case vide, en essayant d'aligner 3 de ses symboles, horizontalement, verticalement ou diagonalement. Si toutes les cases sont remplies sans alignement gagnant, la partie se termine par un match nul.
Bien qu'il existe pas de suite mathématiquement logique des coups, on s'aperçoit, après quelques parties, que les coups sont pratiquement tous logiques et forcés.
- le joueur 1 jouera au centre, pour avoir une espérance de 8 lignes possibles ;
- l'autre joueur, se placera dans un coin (NO, NE, SE ou NW) pour avoir 2 lignes possibles ;
- le joueur 1 mettra son symbole sur une des 2 cases voisines de la marque du joueur 2 ;
- le joueur 2 devra alors bloquer cet alignement ;
- le joueur 1 jouera occupera la case voisine sur la diagonale de ce coup ;
- le joueur 2 devra encore bloquer cet alignement ;
- le joueur 1 jouera fera sa marque une des cases de la dernière ligne encore possible ;
- le joueur 2 sera encore obligé de bloquer cet alignement ;
- le joueur 1 occupera la dernière case libre.
Ce qui pourrait donner la suite : centre, nord-ouest, nord, sud, sud-ouest, nord-est, est, ouest, sud-est.
Notez que si le deuxième coup est nord-est, il suffit de faire une rotation virtuelle de 45° et ainsi de suite.
⇩. Consignes
Le programme doit :
demander si l'utilisateur veut jouer en premier ;
attendre le choix de l'utilisateur, s'il joue en premier ou ;
analyser le contenu de la grille ;
faire un choix pour la machine ;
afficher la grille avec les marques des joueurs ;
rechercher s'il y a un improbable gagnant ;
afficher le résultat de la partie, nul ou gagnant ;
recommencer s'il reste des cases à occuper ;
proposer de faire une autre partie.
D'abord, faite-le fonctionner. Ensuite, faite-le beau. Enfin, faite-le performant.
Amusez-vous bien !
Télécharger RETROGICIEL - Tic tac toe.
Cette présentation nécessite que Python 3 soit installé sur votre machine.
Après avoir téléchargé le fichier Tic tac toe.7z, décompressez-le dans le répertoire de votre choix.
Ouvrez le répertoire qui vient d'être créé.
Lancez le fichier Retrogiciel.py.
Cliquez sur l'onglet RUN et testez le programme.
Créez votre propre script dans un des langages proposés ou un autre de votre choix.
Le répertoire contient aussi :
- Python.py, l'exemple en PYTHON sans tkinter ;
- Tkinter.py, l'exemple en PYTHON avec tkinter ;
- Qb84.bas, l'exemple en QBASIC avec qb64 ;
- Bbc.bas, l'exemple en BBC BASIC avec bbc sdl.
# --- Origine Nerd ---
# --- RETROGICIEL - PYTHON ---
# --- Tic tac toe ---
# -*- coding: utf-8 -*-
# --- IMPORTATION DES MODULES ---
import random
# --- INITIALISATION GÉNÉRALE ---
LST_Cases = [ ]
TPL_Regions = ( ( 0 , 1 , 2 ) , ( 3 , 4 , 5 ) , ( 6 , 7 , 8 ) , ( 0 , 3 , 6 ) , ( 1 , 4 , 7 ) , ( 2 , 5 , 8 ) , ( 0 , 4 , 8 ) , ( 2 , 4 , 6 ) )
DCT_Donnees = { "joueur" : None , "tour" : 0 , "humain" : None , "machine" : 0 }
# --- DÉFINITION DES FONCTIONS PERSONNALISÉES ---
# --- Analyse de la grille pour le choix de la machine ---
def FNC_Analyse ( ) :
klibre , kposition = "?" , "?"
for kregion in TPL_Regions :
kmachine , khumain = 0 , 0
for kcase in kregion :
ksymbole = LST_Cases [ kcase ]
if ksymbole == DCT_Donnees [ "machine" ] : kmachine += 1
elif ksymbole == DCT_Donnees [ "humain" ] : khumain += 1
elif ksymbole not in "OX" : klibre = ksymbole
if kmachine == 2 and khumain == 0 : return LST_Cases.index ( klibre )
if khumain == 2 and kmachine == 0: kposition = klibre
return LST_Cases.index ( kposition ) if kposition != "?" else LST_Cases.index ( klibre )
# --- Choix du premier joueur, et de sa marque, par l'humain ---
def FNC_Debut ( ) :
print ( "Voulez-vous jouer : " )
print ( "en premier avec les O ;")
print ( "en deuxième avec les X ?" )
while True :
kchoix = input ( "votre choix (O ou X) ... " ).upper ( )
if len ( kchoix ) == 1 and kchoix in "OX" : break
DCT_Donnees [ "humain" ] = kchoix
DCT_Donnees [ "machine" ] = "X" if kchoix == "O" else "O"
DCT_Donnees [ "joueur" ] = "humain" if kchoix == "O" else "machine"
FNC_Grille ( )
# --- Recherche si un des juoeurs a fait une ligne ---
def FNC_Gain ( ) :
for kregion in TPL_Regions :
ksymboles = LST_Cases [ kregion [ 0 ] ] + LST_Cases [ kregion [ 1 ] ] + LST_Cases [ kregion [ 2 ] ]
if ksymboles.count ( "O" ) == 3 or ksymboles.count ( "X" ) == 3 : return True
return False
# --- Affichage de la grille actuelle ---
def FNC_Grille ( ) :
print ( "\u250f\u2501\u2501\u2501\u2533\u2501\u2501\u2501\u2533\u2501\u2501\u2501\u2513" )
print ( f"\u2503 { LST_Cases [ 0 ] } \u2503 { LST_Cases [ 1 ] } \u2503 { LST_Cases [ 2 ] } \u2503" )
print ( "\u2523\u2501\u2501\u2501\u254B\u2501\u2501\u2501\u254B\u2501\u2501\u2501\u252b" )
print ( f"\u2503 { LST_Cases [ 3 ] } \u2503 { LST_Cases [ 4 ] } \u2503 { LST_Cases [ 5 ] } \u2503" )
print ( "\u2523\u2501\u2501\u2501\u254B\u2501\u2501\u2501\u254B\u2501\u2501\u2501\u252b" )
print ( f"\u2503 { LST_Cases [ 6 ] } \u2503 { LST_Cases [ 7 ] } \u2503 { LST_Cases [ 8 ] } \u2503" )
print ( "\u2517\u2501\u2501\u2501\u253b\u2501\u2501\u2501\u253b\u2501\u2501\u2501\u251b" )
# --- Le joueur (humain) doit jouer ---
def FNC_Humain ( ) :
kpossibles = FNC_Possibles ( )
print ( "A vous de jouer..." )
while True :
kchoix = input ( f"Votre choix parmi { kpossibles } ? " )
if kchoix == "" : continue
if kchoix.lower ( ) in kpossibles : break
kindex = LST_Cases.index ( kchoix.lower ( ) )
LST_Cases [ kindex ] = DCT_Donnees [ "humain" ]
# --- Choix du coup de la machine ---
def FNC_Machine ( ) :
if LST_Cases [ 4 ] == "e" : kcase = 4 # choisir la case centrale si elle est libre
elif DCT_Donnees [ "tour" ] == 2 : kcase = random.choice ( ( 0 , 2 , 6 , 8 ) ) # choisir un coin au deuxième tour
else : kcase = FNC_Analyse ( )# sinon analyse la grille pour le meuilleur coup possible
print ( f"La machine choisi la case { LST_Cases [ kcase ] }." )
LST_Cases [ kcase ] = DCT_Donnees [ "machine" ]
FNC_Grille ( )
# --- Recherche les cases qui n'ont pas encore été selectionné ---
def FNC_Possibles ( ) :
kpossibles = ""
for kcase in LST_Cases :
if kcase not in "OX" : kpossibles += kcase + " "
return kpossibles
# --- PRESENTATION ---
print ( "Faisons une partie de TIC TAC TOE.\n" )
# --- BOUCLE PRINCIPALE ---
while True :
# --- Intialisation d'une nouvelle partie ---
LST_Cases [ : ] = [ klettre for klettre in "abcdefghi" ]
DCT_Donnees [ "tour" ] = 0
kresultat = f"\nMatch nul.\n"
FNC_Debut ( )
# --- Déroulent de la partie ---
while DCT_Donnees [ "tour" ] < 9 :
DCT_Donnees [ "tour" ] += 1
print ( f"\nTour : { DCT_Donnees [ 'tour' ] }." )
if DCT_Donnees [ "joueur" ] == "humain" : FNC_Humain ( )
else : FNC_Machine ( )
if FNC_Gain ( ) :
kresultat = f"\n{ DCT_Donnees [ 'joueur' ] } a gagné.\n"
break
DCT_Donnees [ "joueur" ] = "machine" if DCT_Donnees [ "joueur" ] == "humain" else "humain"
# --- Fin de la partie ---
print ( kresultat )
kchoix = input ( "Voulez-vous faire une autre partie (O ou N) ? " )
if kchoix.upper ( ) == "N" : break
# --- FIN DU PROGRAMME ---
print ( "Au revoir" )
# --- Programme : JFB ---
# --- Novembre 2025 ---
# --- Fin ---
Pour mieux comprendre l'exemple en PYTHON sans tkinter.
# --- Origine Nerd ---
# --- RETROGICIEL - TKINTER ---
# --- Tic tac toe ---
# -*- coding: utf-8 -*-
# --- IMPORTATION DES MODULES ---
import tkinter
import random
# --- INITIALISATION GÉNÉRALE ---
LST_Cases = [ ]
TPL_Regions = ( ( 0 , 1 , 2 ) , ( 3 , 4 , 5 ) , ( 6 , 7 , 8 ) ,
( 0 , 3 , 6 ) , ( 1 , 4 , 7 ) , ( 2 , 5 , 8 ) ,
( 0 , 4 , 8 ) , ( 2 , 4 , 6 ) )
DCT_Donnees = { "humain" : None , "machine" : None , "tour" : None }
# --- DÉFINITION DES FONCTIONS PERSONNALISÉES ---
# --- Analyse de la grille pour le choix de la machine ---
def FNC_Analyse ( ) :
klibre , kposition = "?" , "?"
for kregion in TPL_Regions :
kmachine , khumain = 0 , 0
for kcase in kregion :
ksymbole = LST_Cases [ kcase ] [ "text" ]
if ksymbole == DCT_Donnees [ "machine" ] : kmachine += 1
elif ksymbole == DCT_Donnees [ "humain" ] : khumain += 1
elif ksymbole not in "OX" : klibre = kcase
if kmachine == 2 and khumain == 0 : return klibre
if khumain == 2 and kmachine == 0: kposition = klibre
return kposition if kposition != "?" else klibre
# --- Mise en évidence de la case sélectionnée ---
def FNC_Case ( Qcase , Qsymbole ) :
LST_Cases [ Qcase ] [ "state" ] = "disabled"
if Qsymbole == "O" :
LST_Cases [ Qcase ] [ "text" ] = "O"
LST_Cases [ Qcase ] [ "background" ] = "aqua"
LST_Cases [ Qcase ] [ "foreground" ] = "blue"
LST_Cases [ Qcase ] [ "font" ] = font = ( None, 18 , "bold" )
else :
LST_Cases [ Qcase ] [ "text" ] = "X"
LST_Cases [ Qcase ] [ "background" ] = "pink"
LST_Cases [ Qcase ] [ "foreground" ] = "red"
LST_Cases [ Qcase ] [ "font" ] = font = ( None, 18 , "bold" )
# --- Choix du premier joueur, et de sa marque, par l'humain ---
def FNC_Choix ( Q ) :
DCT_Donnees [ "tour" ] = 0
BUT_PrendreO [ "state" ] = "disabled"
BUT_PrendreX [ "state" ] = "disabled"
DCT_Donnees [ "humain" ] = "O" if Q == "O" else "X"
DCT_Donnees [ "machine" ] = "X" if Q == "O" else "O"
for kindex in range ( 9 ) :
LST_Cases [ kindex ] [ "text" ] = chr( 97 + kindex )
LST_Cases [ kindex ] [ "background" ] = "white"
LST_Cases [ kindex ] [ "foreground" ] = "black"
LST_Cases [ kindex ] [ "font" ] = font = ( None, 18 , "normal" )
LST_Cases [ kindex ] [ "state" ] = "normal"
if Q == "X" : FNC_Machine ( )
else : LAB_Message [ "text" ] = "A vous de jouer ..."
# --- Recherche si un des joueurs a fait une ligne ___
def FNC_Gain ( ) :
kpossibles = ""
for kindex in range ( 9 ) :
if LST_Cases [ kindex ] [ "text" ] in "abcdefghi" : kpossibles += LST_Cases [ kindex ] [ "text" ]
if len ( kpossibles ) < 1 : return "nul"
for kregion in TPL_Regions :
ksymboles = ""
for kcase in kregion : ksymboles += LST_Cases [ kcase ] [ "text" ]
if ksymboles.count ( "O" ) == 3 or ksymboles.count ( "X" ) == 3 : return "gagne"
return "suivant"
# --- Le joueur (humain) doit jouer ---
def FNC_Humain ( Q ) :
DCT_Donnees [ "tour" ] += 1
FNC_Case ( Q , DCT_Donnees [ "humain" ] )
match FNC_Gain ( ) :
case "gagne" : FNC_Termine ( "humain" )
case "nul" : FNC_Termine ( "nul" )
case _ : FNC_Machine ( )
# --- Choix du coup de la machine ---
def FNC_Machine ( ) :
DCT_Donnees [ "tour" ] += 1
if LST_Cases [ 4 ] [ "text" ] == "e" : kcase = 4 # choisir la case centrale si elle est libre
elif DCT_Donnees [ "tour" ] < 3 : kcase = random.choice ( ( 0 , 2 , 6 , 8 ) ) # choisir un coin au premier tour
else : kcase = FNC_Analyse ( ) # sinon analyse la grille pour le meilleur coup possible
LAB_Message [ "text" ] = f"Je chosis { LST_Cases [ kcase ] [ 'text' ]}.\nA vous de jouer ..."
FNC_Case ( kcase , DCT_Donnees [ "machine" ] )
match FNC_Gain ( ) :
case "gagne" : FNC_Termine ( "machine" )
case "nul" : FNC_Termine ( "nul" )
# --- Partie terminée - affichage du résultat ---
def FNC_Termine ( Q ) :
for kindex in range ( 9 ) : LST_Cases [ kindex ] [ "state" ] = "disabled"
match Q :
case "humain" : kmessage = "Vous avez gagné.\nUne autre partie ?"
case "machine" : kmessage = "J'ai a gagné.\nUne revanche ?"
case _ : kmessage = "Match nul.\nUne autre partie ?"
LAB_Message [ "text" ] = kmessage
BUT_PrendreO [ "state" ] = "normal"
BUT_PrendreX [ "state" ] = "normal"
# --- CRÉATION DE L'INTERFACE GRAPHIQUE ---
# --- Création de la fenêtre principale ---
TKI_Principal = tkinter.Tk ( )
TKI_Principal.title ( "RETROGICIEL - TIC TAC TOE" )
# --- Création des controles nommées ---
BUT_PrendreO = tkinter.Button ( TKI_Principal , text = "Prendre O" , command = lambda : FNC_Choix ( "O" ) )
BUT_PrendreX = tkinter.Button ( TKI_Principal , text = "Prendre X" , command = lambda : FNC_Choix ( "X" ) )
FRM_Grille = tkinter.Frame ( TKI_Principal )
for kcase in "abcdefghi" :
kbouton = tkinter.Button ( FRM_Grille , relief = "flat" , bd = 1 , command = lambda k = ord ( kcase ) - 97 : FNC_Humain ( k ) )
match kcase :
case "a" | "b" | "c" : kligne = 0
case "d" | "e" | "f" : kligne = 1
case "g" | "h" | "i" : kligne = 2
match kcase :
case "a" | "d" | "g" : kcolonne = 0
case "b" | "e" | "h" : kcolonne = 1
case "c" | "f" | "i" : kcolonne = 2
kbouton.grid ( row = kligne , column = kcolonne , sticky = "nesw" )
LST_Cases.append ( kbouton )
LAB_Message = tkinter.Label ( TKI_Principal , text = "..." , width = 16 , height = 3 )
# --- Mise en place des controles (anonymes et nommés) dans la fenêtre principale ---
LAB_Message.grid ( row = 0 , column = 0 , sticky = "nesw" )
FRM_Grille.grid ( row = 1 , column = 0 , padx = 5 , pady = 5 , sticky = "n" )
BUT_PrendreO.grid ( row = 2 , column = 0 , sticky = "nesw" )
BUT_PrendreX.grid ( row = 3 , column = 0 , sticky = "nesw" )
tkinter.Button ( TKI_Principal , text = "Quitter" , command = TKI_Principal.destroy ).grid ( row = 4 , column = 0 , sticky = "nesw" )
# --- DEBUT DU PROGRAMME ---
TKI_Principal.mainloop ( )
# --- Programme : JFB ---
# --- Novembre 2025 ---
# --- Fin ---
Pour mieux comprendre l'exemple en PYTHON avec tkinter.
' --- Origine Nerd propose pour ---
' --- RETROGICIEL - QB64 ---
' --- Tic tac toe ---
' --- INITIALISATION GENERALE ---
' --- Definition des types de variables personnalisees ---
TYPE PER_Dictionnaire
marques AS STRING
joueur AS STRING
humain AS STRING
machine AS STRING
tour AS INTEGER
END TYPE
' --- Declarations des variables globales ---
DIM SHARED LST_Regions$(8)
DIM SHARED DCT_Donnees AS PER_Dictionnaire
' --- Initialisation des valeurs ---
LST_Regions$(0) = "123"
LST_Regions$(1) = "456"
LST_Regions$(2) = "789"
LST_Regions$(3) = "147"
LST_Regions$(4) = "258"
LST_Regions$(5) = "369"
LST_Regions$(6) = "159"
LST_Regions$(7) = "357"
' --- Initialisation des nombres speudo-aleatoire ---
RANDOMIZE TIMER
' --- DEBUT DU PROGRAMME ---
LOCATE 2, 31: PRINT "--- TIC TAC TOE ---"
VIEW PRINT 4 TO 25
' --- BOUCLE PRINCIPALE ---
DO
' ---Initialisation d'une la nouvelle partie ---
FNC_Debut
DCT_Donnees.marques = "abcdefghi"
DCT_Donnees.tour = 1
CLS
FNC_Grille
' --- D�roulement de la partie ---
DO
LOCATE 4, 36: PRINT "Tour n�"; DCT_Donnees.tour
IF DCT_Donnees.joueur = "humain" THEN FNC_Humain ELSE FNC_Machine
FNC_Grille
kgagnant$ = FNC_Gain$
IF kgagnant$ <> "aucun" THEN EXIT DO
LOOP UNTIL DCT_Donnees.tour = 10
' --- Fin de la partie ---
LOCATE 15, 32: PRINT SPACE$(20)
LOCATE 16, 30: PRINT SPACE$(20)
LOCATE 16, 36
IF kgagnant$ = "aucun" THEN PRINT "Match nul." ELSE PRINT kgagnant$; " gagne."
' --- Bouclage du programme ---
LOCATE 18, 19: INPUT "Voulez-vous faire une autre partie (O ou N)"; kchoix$
LOOP UNTIL UCASE$(kchoix$) = "N"
' --- FIN DU PROGRAMME ---
PRINT "Au revoir."
END
' --- DEFINITION DES FONCTIONS PERSONNALISEES ---
' --- Analyse de la grille pour le meilleur choix de la machine ---
FUNCTION FNC_Analyse
kposition = 0
klibre = 0
FOR kregion = 0 TO 7
kmachine = 0
khunain = 0
FOR kcase = 1 TO 3
krang = VAL(MID$(LST_Regions$(kregion), kcase, 1))
ksymboles$ = MID$(DCT_Donnees.marques, krang, 1)
IF ksymboles$ = DCT_Donnees.machine THEN kmachine = kmachine + 1
IF ksymboles$ = DCT_Donnees.humain THEN khunain = khunain + 1
IF ksymboles$ <> "O" AND ksymboles$ <> "X" THEN klibre = krang
NEXT kcase
IF kmachine = 2 AND khunain = 0 THEN FNC_Analyse = klibre: EXIT FUNCTION
IF khunain = 2 AND kmachine = 0 THEN kposition = klibre
NEXT kregion
IF kposition = 0 THEN kposition = klibre
FNC_Analyse = kposition
END FUNCTION
' --- Choix du premier joueur par l'utilisateur ---
SUB FNC_Debut
CLS
LOCATE 7, 30: PRINT "Voulez-vous jouer en:"
LOCATE 8, 30: PRINT "premier avec les O ou"
LOCATE 9, 30: PRINT "deuxieme avec les X ?"
LOCATE 12, 30: PRINT "Votre choix (O ou X) ?"
DO
kchoix$ = INKEY$
LOOP UNTIL UCASE$(kchoix$) = "O" OR UCASE$(kchoix$) = "X"
DCT_Donnees.humain = UCASE$(kchoix$)
IF UCASE$(kchoix$) = "O" THEN DCT_Donnees.machine = "X" ELSE DCT_Donnees.machine = "O"
IF UCASE$(kchoix$) = "O" THEN DCT_Donnees.joueur = "humain" ELSE DCT_Donnees.joueur = "machine"
END SUB
' --- Recherche si un des joueurs a fait une ligne ---
FUNCTION FNC_Gain$
FOR kregion = 0 TO 7
kmachine = 0
khunain = 0
FOR kcase = 1 TO 3
krang = VAL(MID$(LST_Regions$(kregion), kcase, 1))
ksymboles$ = MID$(DCT_Donnees.marques, krang, 1)
IF ksymboles$ = DCT_Donnees.machine THEN kmachine = kmachine + 1
IF ksymboles$ = DCT_Donnees.humain THEN khunain = khunain + 1
NEXT kcase
IF kmachine = 3 THEN FNC_Gain$ = "La machine": EXIT FUNCTION
IF khunain = 3 THEN FNC_Gain$ = " L'humain": EXIT FUNCTION
NEXT kregion
FNC_Gain$ = "aucun"
END FUNCTION
' --- Affichage de la grilles ---
SUB FNC_Grille
' --- Affichage des bordures de la grilles ---
LOCATE 8, 34: PRINT CHR$(201) + STRING$(3, 205) + CHR$(203) + STRING$(3, 205) + CHR$(203) + STRING$(3, 205) + CHR$(187)
LOCATE 9, 34: PRINT CHR$(186) + STRING$(3, 32) + CHR$(186) + STRING$(3, 32) + CHR$(186) + STRING$(3, 32) + CHR$(186)
LOCATE 10, 34: PRINT CHR$(204) + STRING$(3, 205) + CHR$(206) + STRING$(3, 205) + CHR$(206) + STRING$(3, 205) + CHR$(185)
LOCATE 11, 34: PRINT CHR$(186) + STRING$(3, 32) + CHR$(186) + STRING$(3, 32) + CHR$(186) + STRING$(3, 32) + CHR$(186)
LOCATE 12, 34: PRINT CHR$(204) + STRING$(3, 205) + CHR$(206) + STRING$(3, 205) + CHR$(206) + STRING$(3, 205) + CHR$(185)
LOCATE 13, 34: PRINT CHR$(186) + STRING$(3, 32) + CHR$(186) + STRING$(3, 32) + CHR$(186) + STRING$(3, 32) + CHR$(186)
LOCATE 14, 34: PRINT CHR$(200) + STRING$(3, 205) + CHR$(202) + STRING$(3, 205) + CHR$(202) + STRING$(3, 205) + CHR$(188)
' --- Affichage du contenu des cases ---
FOR klettre = 1 TO 9
klettre$ = MID$(DCT_Donnees.marques, klettre, 1)
kligne = (((klettre - 1) \ 3) * 2) + 9
kcolonne = (((klettre - 1) MOD 3) * 4) + 36
LOCATE kligne, kcolonne: PRINT klettre$
NEXT klettre
END SUB
' --- Choix du coup de l'utilsateur (humain) ---
SUB FNC_Humain
' --- Recherche et affichage des coups possibles pour l'humain ---
LOCATE 7, 33: PRINT "A vous de jouer"
kpossibles$ = ""
FOR krang = 1 TO 9
klettre$ = MID$(DCT_Donnees.marques, krang, 1)
IF klettre$ <> "O" AND klettre$ <> "X" THEN kpossibles$ = kpossibles$ + klettre$
NEXT krang
LOCATE 15, 32: PRINT "Votre choix parmi :"
LOCATE 16, 30: PRINT SPACE$(20)
LOCATE 16, ((80 - LEN(kpossibles$)) / 2): PRINT kpossibles$
' --- Saisie et validation du choix du joueur humain ---
DO
kchoix$ = INKEY$
IF kchoix$ <> "" THEN kposition = INSTR(DCT_Donnees.marques, LCASE$(kchoix$))
LOOP UNTIL kposition <> 0
MID$(DCT_Donnees.marques, kposition) = DCT_Donnees.humain
DCT_Donnees.joueur = "machine"
DCT_Donnees.tour = DCT_Donnees.tour + 1
END SUB
' --- La machine choisi une case ---
SUB FNC_Machine
' --- Occuper la case centrale si elle est libre ---
kposition = 0
IF MID$(DCT_Donnees.marques, 5, 1) = "e" THEN kposition = 5
' --- Occuper la case dans un coin si c'est le 2e tour ---
IF DCT_Donnees.tour = 2 AND kposition = 0 THEN
SELECT CASE INT(RND * 4)
CASE 0: kposition = 1
CASE 1: kposition = 3
CASE 2: kposition = 7
CASE 3: kposition = 9
END SELECT
END IF
' --- Analyser la grille pour trouver la meilleure solution ---
IF kposition = 0 THEN kposition = FNC_Analyse
' --- Validation du choix de la machine ---
LOCATE 6, 26: PRINT "La machine a choisi la case "; MID$(DCT_Donnees.marques, kposition, 1); "."
MID$(DCT_Donnees.marques, kposition) = DCT_Donnees.machine
DCT_Donnees.joueur = "humain"
DCT_Donnees.tour = DCT_Donnees.tour + 1
END SUB
' --- Programme : JFB ---
' --- Novembre 2025 ---
' --- Fin ---
Pour mieux comprendre l'exemple en QB64.
REM --- Origine Nerd propose pour ---
REM --- RETROGICIEL - BBC BASIC ---
REM --- Tic tac toe ---
REM --- INITIALISATION GENERALE ---
DIM LST_Regions$( 8 ) : LST_Regions$() = "123" , "456" , "789" , "147" , "258" , "369" , "159" , "357"
DIM DCT_Donnees{ marques$ , joueur$ , humain$ , machine$ , tour& }
REM --- DEBUT DU PROGRAMME ---
PRINT TAB( 31 , 1 ) "--- TIC TAC TOE ---"
VDU 28 , 0 , 25 , 80 , 3
REM --- BOUCLE PRINCIPALE ---
REPEAT
CLS : PROC_Debut : CLS
DCT_Donnees{}.marques$ = "abcdefghi"
DCT_Donnees{}.tour& = 1
LINE 612 , 380 , 612 , 620
LINE 678 , 380 , 678 , 620
LINE 548 , 460 , 744 , 460
LINE 548 , 540 , 744 , 540
PROC_Grille
REM --- Deroulement de la partie ---
REPEAT
PRINT TAB( 36 , 1 ) "Tour n : " ; STR$( DCT_Donnees{}.tour& )
IF DCT_Donnees{}.joueur$ = "humain" THEN PROC_Humain ELSE PROC_Machine
PROC_Grille
kgagnant$ = FN_Gain$
IF kgagnant$ <> "aucun" THEN EXIT REPEAT
UNTIL DCT_Donnees{}.tour& = 10
REM --- Fin de la partie ---
PRINT TAB( 26 , 3 ) SPC( 30 )
PRINT TAB( 32 , 13 ) SPC( 20 )
PRINT TAB( 30 , 14 ) SPC( 20 )
PRINT TAB( 37 , 14 ) ;
IF kgagnant$ = "aucun" THEN PRINT "Match nul." ELSE PRINT kgagnant$ ; " gagne."
REM --- Bouclage du programme ---
INPUT TAB( 19 , 18 ) "Voulez-vous faire une autre partie (O ou N)" ; kchoix$
UNTIL kchoix$ = "N" OR kchoix$ = "n"
REM --- FIN DU PROGRAMME ---
PRINT "Au revoir."
END
REM --- DEFINITION DES FONCTIONS PERSONNALISEES ---
REM --- Analyse de la grille pour le meilleur choix de la machine ---
DEF FN_Analyse
kposition = 0
klibre = 0
FOR kregion = 0 TO 7
kmachine = 0
khunain = 0
FOR kcase = 1 TO 3
krang = VAL( MID$( LST_Regions$( kregion ) , kcase , 1 ) )
ksymboles$ = MID$( DCT_Donnees.marques$ , krang , 1 )
IF ksymboles$ = DCT_Donnees.machine$ THEN kmachine += 1
IF ksymboles$ = DCT_Donnees.humain$ THEN khunain += 1
IF ksymboles$ <> "O" AND ksymboles$ <> "X" THEN klibre = krang
NEXT kcase
IF kmachine = 2 AND khunain = 0 THEN = klibre
IF khunain = 2 AND kmachine = 0 THEN kposition = klibre
NEXT kregion
IF kposition = 0 THEN kposition = klibre
= kposition
REM --- Choix et validation du premier joueur par l'utilisateur ---
DEF PROC_Debut
PRINT TAB( 30 , 7 ) "Voulez-vous jouer en:"
PRINT TAB( 30 , 8 ) "premier avec les O ou"
PRINT TAB( 30 , 9 ) "deuxieme avec les X ?"
PRINT TAB( 30 , 11 ) "Votre choix (O ou X) ?"
REPEAT
WAIT( 15 ) : kchoix$ = GET$
IF kchoix$ = "o" THEN kchoix$ = "O"
IF kchoix$ = "x" THEN kchoix$ = "X"
UNTIL kchoix$ = "O" OR kchoix$ = "X"
DCT_Donnees{}.humain$ = kchoix$
IF kchoix$ = "O" THEN DCT_Donnees{}.machine$ = "X" ELSE DCT_Donnees{}.machine$ = "O"
IF kchoix$ = "O" THEN DCT_Donnees{}.joueur$ = "humain" ELSE DCT_Donnees{}.joueur$ = "machine"
ENDPROC
REM --- Recherche si un des joueurs a fait une ligne ---
DEF FN_Gain$
FOR kregion = 0 TO 7
kmachine = 0
khunain = 0
FOR kcase = 1 TO 3
krang = VAL( MID$( LST_Regions$( kregion ) , kcase , 1 ) )
ksymboles$ = MID$( DCT_Donnees.marques$, krang , 1 )
IF ksymboles$ = DCT_Donnees.machine$ THEN kmachine = kmachine + 1
IF ksymboles$ = DCT_Donnees.humain$ THEN khunain = khunain + 1
NEXT kcase
IF kmachine = 3 THEN = "La machine"
IF khunain = 3 THEN = " L'humain"
NEXT kregion
= "aucun"
REM --- Affichage du contenu des cases de la grille ---
DEF PROC_Grille
FOR klettre = 1 TO 9
klettre$ = MID$( DCT_Donnees{}.marques$ , klettre , 1 )
kligne = ( ( ( klettre - 1 ) DIV 3 ) * 2 ) + 7
kcolonne = ( ( ( klettre - 1 ) MOD 3 ) * 4 ) + 36
PRINT TAB( kcolonne , kligne ) klettre$
NEXT klettre
ENDPROC
REM --- Choix et validation du houeur humain ---
DEF PROC_Humain
REM --- Recherche et affichage des coups possibles pour l'humain ---
PRINT TAB( 33 , 5 ) "A vous de jouer"
kpossibles$ = ""
FOR krang = 1 TO 9
klettre$ = MID$(DCT_Donnees{}.marques$, krang, 1)
IF klettre$ <> "O" AND klettre$ <> "X" THEN kpossibles$ = kpossibles$ + klettre$
NEXT krang
PRINT TAB( 32 , 13 ) "Votre choix parmi :"
PRINT TAB( 30 , 14 ) SPC( 20 )
PRINT TAB( ( ( 80 - LEN( kpossibles$ ) ) / 2 ) , 14 ) kpossibles$
REM --- Saisie et validation du choix du joueur humain ---
REPEAT
WAIT( 15 ) : kchoix$ = GET$
IF kchoix$ <> "" THEN kposition = INSTR( DCT_Donnees{}.marques$ , kchoix$ ) ELSE kposition = 0
UNTIL kposition <> 0
MID$( DCT_Donnees{}.marques$, kposition ) = DCT_Donnees{}.humain$
DCT_Donnees{}.joueur$ = "machine"
DCT_Donnees{}.tour& += 1
ENDPROC
REM --- Choix de la machine ---
DEF PROC_Machine
REM --- Occuper la case centrale si elle est libre ---
IF MID$( DCT_Donnees{}.marques$ , 5 , 1 ) = "e" THEN kposition = 5 ELSE kposition = 0
REM --- Occuper la case dans un coin si c'est le 2e tour ---
IF DCT_Donnees{}.tour& = 2 AND kposition = 0 THEN
CASE RND(4) OF
WHEN 1 : kposition = 1
WHEN 2 : kposition = 3
WHEN 3 : kposition = 7
WHEN 4 : kposition = 9
ENDCASE
ENDIF
REM --- Analyser la grille pour trouver la meilleure solution ---
IF kposition = 0 THEN kposition = FN_Analyse
REM --- Validation du choix de la machine ---
PRINT TAB( 26 , 3 ) "La machine a choisi la case "; MID$( DCT_Donnees{}.marques$ , kposition , 1 ); "."
MID$( DCT_Donnees{}.marques$, kposition ) = DCT_Donnees{}.machine$
DCT_Donnees{}.joueur$ = "humain"
DCT_Donnees{}.tour& += 1
ENDPROC
REM --- Programme : JFB ---
REM --- Novembre 2025 ---
REM --- Fin ---
Pour mieux comprendre l'exemple en BBC BASIC.