PDA

View Full Version : [Python] Nuovo problema


Heretic Curse
13-05-2013, 19:15
Fare questo gioco di carte virtuale mi sta davvero mettendo in difficoltà

# !/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import random

class Carta:

ListaSemi = ["Fiori", "Quadri", "Cuori", "Picche"]
ListaRanghi = ["impossibile", "Asso", "2", "3", "4", "5", "6", \
"7", "8", "9", "10", "Jack", "Queen", "King"]

def __init__(self, Seme = 0, Rango = 0):
self.Rango = Rango
self.Seme = Seme

def __str__(self):
return str(self.ListaRanghi[self.Rango]) + " di " + str(self.ListaSemi[self.Seme])

def __cmp__(self, Altro):
if self.Seme > Altro.Seme: return 1
if self.Seme < Altro.Seme: return -1

if self.Rango == 1 and self.Rango != Altro.Rango: return 1
if self.Rango > Altro.Rango: return 1
if self.Rango < Altro.Rango: return -1
return 0

class Mazzo:

def __init__(self):
self.Carte = []
for Seme in range(4):
for Rango in range(1, 14):
self.Carte.append(Carta(Seme, Rango))

def __str__(self):
s = ""
for i in range(len(self.Carte)):
s = s + " "*i + str(self.Carte[i]) + "\n"
return s

def Mescola(self):
NumCarte = len(self.Carte)
for i in range(NumCarte):
j = random.randrange(i, NumCarte)
x = 0
self.Carte[x] = self.Carte[i]
self.Carte[i] = self.Carte[j]
self.Carte[j] = self.Carte[x]



def RimuoviCarte(self, Carta):
if Carta in self.Carte:
self.Carte.remove(Carta)
return 1
else:
return 0

def PrimaCarta(self):
return self.Carte.pop()

def EVuoto(self):
return (len(self.Carte) == 0)

def Distribuisci(self, ListaMani, NumCarte=999):
NumMani = len(ListaMani)
for i in range(NumCarte):
if self.EVuoto(): break
Carta = self.PrimaCarta()
Mano = ListaMani[i%NumMani]
Mano.AggiungeCarta(Carta)


class Mano(Mazzo):

def __init__(self, Nome=""):
self.Carte = []
self.Nome = Nome

def __str__(self):
s = "La mano di " + self.Nome
if self.EVuoto():
s = s + " è vuota\n"
else:
s = s + " contiene tali carte:\n"
return s + Mazzo.__str__(self)

def AggiungeCarta(self, Carta):
self.Carte.append(Carta)

class GiocoDiCarte:
def __init__(self):
self.Mazzo = Mazzo()
self.Mazzo.Mescola()

class GiocoOldMaid(GiocoDiCarte):

def TrovaVicino(self, Giocatore):
NumMani = len(self.Mani)
for Prossimo in range(1, NumMani):
Vicino = (Giocatore + Prossimo) % NumMani
if not self.Mani[Vicino].EVuoto():
return Vicino

def GiocaUnTurno(self, Giocatore):
if self.Mani[Giocatore].EVuoto:
return 0
Vicino = self.TrovaVicino(Giocatore)
CartaScelta = self.Mani[Vicino].PrimaCarta()
self.Mani[Giocatore].AggiungeCarta(CartaScelta)
print "Mano di", self.Mani[Giocatore].Nome, ": scelta", CartaScelta
Conteggio = self.Mani[Giocatore].RimuoveCoppie()
self.Mani[Giocatore].Mescola()
return Conteggio

def StampaMani(self):
for Mano in self.Mani:
print Mano


def RimuoveTutteLeCoppie(self):
Conteggio = 0
for Mano in self.Mani:
Conteggio = Conteggio + Mano.RimuoveCoppie()
return Conteggio

def Partita(self, Nomi):
self.Mazzo.RimuoviCarte(Carta(0, 12))

self.Mani=[]
for Nome in Nomi:
self.Mani.append(ManoOldMaid(Nome))

self.Mazzo.Distribuisci(self.Mani)
print "---------- Le carte sono state distribuite"
self.StampaMani()

NumCoppie = self.RimuoveTutteLeCoppie()
print "---------- Coppie scartate, inizia la partita"
self.StampaMani

Turno = 0
NumMani = len(self.Mani)
while NumCoppie < 25:
NumCoppie = NumCoppie + self.GiocaUnTurno(Turno)
Turno = (Turno + 1) % NumMani

print "---------- La partita è finita"
self.StampaMani()

class ManoOldMaid(Mano):

def RimuoveCoppie(self):
Conteggio = 0
CarteOriginali = self.Carte[:]
for CartaOrig in CarteOriginali:
CartaDaCercare = Carta(3-CartaOrig.Seme, CartaOrig.Rango)
if CartaDaCercare in self.Carte:
self.Carte.remove(CartaOrig)
self.Carte.remove(CartaDaCercare)
print "Mano di %s : %s elimina %s" % (self.Nome, CartaOrig, CartaDaCercare)
Conteggio = Conteggio + 1
return Conteggio

import Carta
Gioco = GiocoOldMaid()
Gioco.Partita(["Howard", "Sheldon", "Leonard"])

Ora viene il bello: Sublime Text non mi restituisce alcun errore, ne mi scrive "Finished in x seconds with exit code y", semplicemente me lo esegue fino a stamparmi "---------- Coppie scartate, inizia la partita", poi più nulla. Eppure non riesco seriamente a trovare errori in ciò che segue (anche se ovviamente ci saranno).

Volevo inoltre chiedervi, le prime 2 righe di codice che ho scritto cosa significano? Perché il codice presentava un errore e ho trovato googolando di usare quelle righe come soluzione, ma non ne ho compreso il "senso".

Spero l'indentazione vi vada bene, è quella che mi mette in automatico l' IDE.

pabloski
13-05-2013, 20:30
Le prime due righe indicano:

1. l'eseguibile dell'interprete python da usare per far girare lo script
2. l'encoding usato per i file sorgente del tuo programma ( nel tuo caso è la codifica nostrana con l'aggiunta del simbolo € )

Heretic Curse
13-05-2013, 21:12
Le prime due righe indicano:

1. l'eseguibile dell'interprete python da usare per far girare lo script
2. l'encoding usato per i file sorgente del tuo programma ( nel tuo caso è la codifica nostrana con l'aggiunta del simbolo € )

ok grazie ;)

Heretic Curse
14-05-2013, 13:10
Qualcuno riesce ad aiutarmi con l'altro problema?
Magari è anche una buona occasione perché io cominci ad usare un debugger, consigli?

pabloski
14-05-2013, 13:23
Pdb è un buon debugger. Non si trova/trovava roba per neofiti, ma sono incappato in questo post http://pythonconquerstheuniverse.wordpress.com/2009/09/10/debugging-in-python/ che spiega le cose in maniera adatta ai neofiti.

cdimauro
14-05-2013, 15:52
Qualcuno riesce ad aiutarmi con l'altro problema?
Magari è anche una buona occasione perché io cominci ad usare un debugger, consigli?
Magari è un'ottima occasione per cominciare a usare unit-testing e/o Test Driven Development. Così ti scordi pure cos'è un debugger. ;)

Heretic Curse
14-05-2013, 18:23
Ti ringrazio per il BTD :) in realtà non l'ho ancora appreso, lo farò di sicuro (quante cose da imparare per programmare :Prrr: ), ma leggendo un esempio sul web ho scoperto che mi sono dimenticato di utilizzare import. Il problema tuttavia è che non so cosa devo importare: sul libro "Pensare in Python " riportavano import Carta (come ho scritto in rosso nel topic principale), ma ovviamente mi riporta un errore:
ImportError: No module named Carta
Il fatto è che non ho mai usato import se non per importare i soliti moduli come string, random e math, e provando a mettere al posto di Carta le classi che ho definito nel codice, ancora non ottengo risultati (com'era da aspettarsi, ma non sapevo che tentare :/).

kwb
14-05-2013, 18:56
Non vorrei dire blasfemie ma, se il tuo codice è tutto dentro un unico file ( come mi pare di capire ) non c'è bisogno di importare niente..

Heretic Curse
14-05-2013, 19:04
Lo avevo intuito pure io, eppure se non importo nulla mi si blocca ad un certo punto, senza restituire errori D:
Se volete, questo è esattamente ciò che produce:

---------- Le carte sono state distribuite
La mano di Howard contiene tali carte:
Queen di Quadri
2 di Cuori
4 di Picche
10 di Fiori
3 di Fiori
9 di Picche
5 di Fiori
2 di Picche
5 di Quadri
9 di Cuori
6 di Cuori
3 di Cuori
6 di Fiori
3 di Picche
5 di Cuori
8 di Cuori

La mano di Sheldon contiene tali carte:
7 di Cuori
5 di Picche
10 di Cuori
6 di Picche
Asso di Cuori
10 di Picche
2 di Fiori
3 di Quadri
Jack di Quadri
7 di Picche
Asso di Quadri
Queen di Cuori
6 di Quadri
Jack di Fiori
Queen di Picche
Queen di Quadri

La mano di Leonard contiene tali carte:
10 di Quadri
9 di Fiori
Asso di Picche
7 di Quadri
8 di Quadri
9 di Quadri
8 di Fiori
Jack di Cuori
7 di Fiori
2 di Quadri
4 di Fiori
4 di Cuori
Jack di Picche
4 di Quadri
8 di Picche

Mano di Howard : 3 di Fiori elimina 3 di Picche
Mano di Howard : 5 di Quadri elimina 5 di Cuori
Mano di Sheldon : Asso di Cuori elimina Asso di Quadri
Mano di Sheldon : Queen di Cuori elimina Queen di Quadri
Mano di Leonard : 8 di Fiori elimina 8 di Picche
Mano di Leonard : 4 di Cuori elimina 4 di Quadri
---------- Coppie scartate, inizia la partita

cdimauro
14-05-2013, 19:44
Carta è una classe, non un modulo, quindi non puoi importarla.

Il tuo programmino è diventato più complesso e una veloce occhiata non è sufficiente per capire dove potrebbe essere il problema. Se avrò un po' di tempo, vedrò quale potrebbe essere la causa.

Comunque anche se hai ancora molto da imparare, e quindi roba come unit-testing o TDD al momento ti sono aliene, nulla t'impedisce di usare un approccio di tipo "divide et impera". Controlla se le singole classi si comportano come dovrebbero, partendo da quelle "di base" (cioé quelle che non usano altre classi, e che verranno usate dalle altre classi).

Heretic Curse
14-05-2013, 19:54
Carta è una classe, non un modulo, quindi non puoi importarla.

Il tuo programmino è diventato più complesso e una veloce occhiata non è sufficiente per capire dove potrebbe essere il problema. Se avrò un po' di tempo, vedrò quale potrebbe essere la causa.

Comunque anche se hai ancora molto da imparare, e quindi roba come unit-testing o TDD al momento ti sono aliene, nulla t'impedisce di usare un approccio di tipo "divide et impera". Controlla se le singole classi si comportano come dovrebbero, partendo da quelle "di base" (cioé quelle che non usano altre classi, e che verranno usate dalle altre classi).

Ok grazie, buona idea :)

Heretic Curse
15-05-2013, 05:35
Mio dio, pare che funzioni tutto :/ in sostanza il mio programma non si avvia da Turno = 0 in poi, quindi non posso verificare alcuni metodi come GiocaUnTurno, ma controllando queste mentalmente e controllando gli altri metodi che richiamano pare tutto ok :muro:

cdimauro
15-05-2013, 19:37
Qualunque metodo è verificabile, specialmente in Python (dove non ci sono membri privati). Devi cercare di sforzarti di più.

Il mio consiglio è di cercare di riprodurre con un piccolo pezzo di codice le condizioni che "sfuggono", testando così i singoli casi particolari. Vedrai che te ne esci, e sarai pure a un passo dalle basi dello unit-testing e TDD, che ti faranno cambiare completamente il modo di concepire il codice (ma è ancora prematuro).

Heretic Curse
16-05-2013, 04:30
Sisi, infatti poi mi ero messo a fare così e hanno cominciato a saltare fuori gli errori :D vi dirò come andrà alla fine ;)

Heretic Curse
16-05-2013, 16:36
Ok, ho scoperto che il metodo Mescola non funziona :/ anche se effettivamente alla fine le mani dei giocatori sembrano casuali. Eppure se faccio un codice con solo la classe Carta e solo la classe Mazzo (+ import random), facendo così:
T = Mazzo()
T.Mescola
print Til mazzo mi rimane in ordine. Ovviamente Mescola l'ho scritto esattamente uguale a com'è sul libro :( tutti i metodi di Carta funzionano, e anche init e str di Mazzo producono gli esiti corretti.
Sinceramente non credo la motivazione dell'insuccesso finale sia dovuta a questo, ma ho trovato questa falla e direi che è meglio se viene corretta :)

The_ouroboros
16-05-2013, 18:05
Dai un occhio qui (http://docs.python.org/2/library/unittest.html ) a me, quando imparavo python, ha molto aiutato...

cdimauro
16-05-2013, 21:27
Ok, ho scoperto che il metodo Mescola non funziona :/ anche se effettivamente alla fine le mani dei giocatori sembrano casuali. Eppure se faccio un codice con solo la classe Carta e solo la classe Mazzo (+ import random), facendo così:
T = Mazzo()
T.Mescola
print Til mazzo mi rimane in ordine. Ovviamente Mescola l'ho scritto esattamente uguale a com'è sul libro :( tutti i metodi di Carta funzionano, e anche init e str di Mazzo producono gli esiti corretti.
Sinceramente non credo la motivazione dell'insuccesso finale sia dovuta a questo, ma ho trovato questa falla e direi che è meglio se viene corretta :)
La falla è nel tuo codice: Mescola è un metodo e quindi va richiamato con la coppia di parentesi tonde () subito dopo il nome. Tu le hai omesse, quindi hai semplicemente preso (l'indirizzo del) il metodo, e poi l'hai buttato.

Heretic Curse
16-05-2013, 21:37
Beh, quest'ultimo è stato davvero imbarazzante :doh:

Btw sto ricontrollando il codice, e ho scoperto che avevo omesso le parantesi dopo uno StampaMani! Ora il codice va un po' oltre, poi si blocca di nuovo, ma è già un gran passo avanti! della mancanza di queste parentesi me ne ero già accorto anche prima di leggere la tua risposta :P comunque grazie, perché ci stavo ancora pensando visto che non mi è venuto in mente di aver potuto commettere lo stesso errore due volte.
Ora vado a dormire, poi controllerò GiocaUnTurno, siccome ormai sono pressocché certo che l'errore stia lì.

Ho dato un'occhiata di nuovo ad unittest. Dovrò proprio impararlo, ma non credo sia il momento.

kwb
16-05-2013, 22:15
La domanda mi sorge spontanea: ma hai scritto un intero programma così lungo ( e non-banale ) dall'inizio alla fine senza averlo mai provato lungo il percorso? :mbe:

Heretic Curse
17-05-2013, 04:14
Non ho provato solo i metodi di GiocoOldMaid e ManoOldMaid, ora che ci penso, però mi ero rimesso a riguardare tutto dall'inizio :muro:

Heretic Curse
17-05-2013, 05:22
RISOLTO COMPLETAMENTE!

Avevo dimenticato le parentesi pure dopo un EVuoto :D

cdimauro
17-05-2013, 06:21
http://www.dgrin.com/images/smilies/Whip.gif

Heretic Curse
17-05-2013, 13:38
Haha, in effetti ho fatto tanto casino per un'idiozia :D