[Python] Abbozzo algoritmo Tris

Alberto Abate alberto.abate a gmail.com
Gio 14 Maggio 2015 14:26:09 CEST


Un saluto a tutti.
Leggendo qualche 3rd sulla lista, ho preso spunto per un piccolo esercizio
di codice.

Ho preso spunto da:
http://en.wikipedia.org/wiki/Tic-tac-toe
http://ostermiller.org/calc/tictactoe.html

Consigli e suggerimenti sono ben accetti.
Come vedete ho implementato solo alcune delle regole ;-))

# INIZIO SCRIPT *******************************************************
#!/usr/bin/python
# coding: utf-8

from random import randint


# SETUP
---------------------------------------------------------------------
player = ['X','O']  # giocatore
level = [2,1]       # 1=Novice,2=Intermediate,3=Experienced,4=Expert
diz_level={1:'NOVICE',2:'INTERMEDIATE',3:'EXPERIENCED',4:'EXPERT'}
blank = '.'         # carattere blank per griglia
cur_p =  0          # imposta current player (cur_p) e current level (cur_l)
cur_nr = 1          # contatore numero mossa
dim_b = 3           # imposta dimensione board (dim_b)
#
---------------------------------------------------------------------------

def make_board(dim,val):
  # crea diz griglia di dimensioni dim con valore val
  diz = {}
  for x in range(dim):
    for y in range(dim):
      diz[x,y]=val
  return diz


def print_board(g,dim):
  # visualizza griglia g di dimensione dim
  for y in range(dim):
    for x in range(dim):
      print g[x,y],
    print


def celle_libere(g,dim,blank):
  ris = []
  for y in range(dim):
    for x in range(dim):
      if g[x,y] == blank:
        ris.append((x,y))
  return ris


def best_move(g,dim_b,p,nr,blank):
  # sceglie una possibile posizione (x,y)
  # per il giocatore p di livello l alla mossa nr
  celle = celle_libere(g,dim_b,blank)
  dim = len(celle)
  if dim:
    if level[p] == 1:  # Livello NOVICE
      state = 'RANDOM'
      i = randint(0,dim-1)  # sceglie random cella da quelle libere
      x = celle[i][0]
      y = celle[i][1]
      return x,y,state

    if level[p] == 2:  # Livello INTERMEDIATE
      for (x,y) in celle:
           # 1) Win: If the player has two in a row, they can place a third
to get three in a row.
           if check_win(g,dim_b,dim_b-1,x,y,p):
             state = 'WIN'
             return x,y,state
           # 2) Block: If the opponent has two in a row, the player must
play the third themselves to block the opponent.
           elif check_win(g,dim_b,dim_b-1,x,y,not(p)):
             state = 'BLOCK'
             return x,y,state
      state = 'RANDOM'
      i = randint(0,dim-1)  # sceglie random cella da quelle libere
      x = celle[i][0]
      y = celle[i][1]
      return x,y,state

    if level[p] == 4:
      if nr == 1: return 1,1 # prima mossa CENTER
      #if nr == 2: return -1,-1 #cella non valida
      for (x,y) in celle:
           # 1) Win: If the player has two in a row, they can place a third
to get three in a row.
           if check_win(g,dim_b,dim_b-1,x,y,p): return x,y,state

           # 2) Block: If the opponent has two in a row, the player must
play the third themselves to block the opponent.
           elif check_win(g,dim_b,dim_b-1,x,y,not(p)): return x,y,state

           # 3) Fork: Create an opportunity where the player has two
threats to win (two non-blocked lines of 2).

           # 4) Blocking an opponent's fork:
           # Option 1: The player should create two in a row to force the
opponent into defending, as long as it doesn't result in them creating a
fork.
           # For example,  if "X" has a corner, "O" has the center, and "X"
has the opposite corner as well,
           #                 "O" must not play a corner in order to win.
(Playing a corner in this scenario creates a fork for "X" to win.)
           # Option 2: If there is a configuration where the opponent can
fork, the player should block that fork.

           # 5) Center: A player marks the center.
           #   (If it is the first move of the game, playing on a corner
gives "O" more opportunities to make a mistake and may therefore be the
better choice;
           #    however, it makes no difference between perfect players.)

           # 6) Opposite corner: If the opponent is in the corner, the
player plays the opposite corner.

           # 7) Empty corner: The player plays in a corner square.

           # 8) Empty side: The player plays in a middle square on any of
the 4 sides.




  else:
    return -1,-1,state # non ci sono celle libere quindi imposto coordinate
per pareggio


def check_win(g,dim,dim_win,x,y,p):
  # controlla se ho dim elementi di player p
  # in riga, colonna, diagonali
  col=row=diag=rdiag=0
  ris=False
  for i in range(dim):
    if g[x,i]==player[p]: col += 1
    if g[i,y]==player[p]: row += 1
    if g[i,i]==player[p]: diag += 1
    if g[i,dim-i-1]==player[p]: rdiag +=1
  if row==dim_win or col==dim_win or diag==dim_win or rdiag==dim_win:
ris=True
  return ris



if __name__ == '__main__':


  board = make_board(dim_b,blank)

  while True:

    x,y,state = best_move(board,dim_b,cur_p,cur_nr,blank)
    print 'nr_mossa: '+ str(cur_nr),'cur_p: ' + player[cur_p],'cur_l: ' +
str(level[cur_p])+':'+diz_level[level[cur_p]],'state: '+state

    if x == y == -1: # se non ci sono celle vuote
      print 'PAREGGIO'
      break
    else:
      board[x,y] = player[cur_p] # metto il simbolo di cur_p in posizione
x,y
      cur_nr += 1                # incremento il numero della mossa
      print_board(board,dim_b)   # visualizzo la griglia

      if check_win(board,dim_b,dim_b,x,y,cur_p): #controlla se cur_p ha
vinto
        print 'VITTORIA DI ' + player[cur_p]
        break
      cur_p = not cur_p  # seleziono l'altro giocatore
      print '-'*20

# FINE SCRIPT *******************************************************
-------------- parte successiva --------------
Un allegato HTML è stato rimosso...
URL: <http://lists.python.it/pipermail/python/attachments/20150514/61b39965/attachment.html>


Maggiori informazioni sulla lista Python