Il gioco di Nim. Si tratta di un gioco con un certo numero di varianti: utilizzeremo la versione seguente, che ha una strategia interessante per arrivare alla vittoria. Due giocatori prelevano a turno biglie da un mucchio. In ciascun turno, il giocatore sceglie quante biglie prendere: deve prenderne almeno una, ma non oltre la metà del mucchio. Perde chi è costretto a prendere l'ultima biglia. Scrivere il (programma-)GIOCO nim.py con cui un giocatore umano possa giocare a Nim contro il computer. Si genera un numero intero casuale, compreso fra 10 e 100, per indicare il numero iniziale di biglie. Si decide casualmente se la prima mossa tocca al computer o al giocatore umano. Si decide casualmente se il computer giocherà in modo intelligente o stupido. Nel modo stupido, quando è il suo turno, il computer si limita a sottrarre dal mucchio un numero casuale di biglie, purché sia una quantità ammessa. Nel modo intelligente, il computer preleva il numero di biglie sufficiente affinché il numero di quelle rimanenti sia uguale a una potenza di due diminuita di un'unità, ovvero 1, 3, 7, 15, 31 o 63: si tratta sempre di una mossa valida, eccetto quando il numero delle biglie è uguale a una potenza di due diminuita di un'unità, nel qual caso il computer preleverà una quantità di biglie casuale, purché ammessa. Quando il programma gestisce il turno del giocatore umano, chiede quante biglie si vogliono prendere (segnalando quante ce ne sono) e verifica se la scelta è valida: se non lo è, ripete (indefinitamente) la domanda. Si noti che, nel modo intelligente, il computer non può essere sconfitto quando ha la prima mossa, a meno che il mucchio non contenga inizialmente 15, 31 o 63 biglie. Nelle medesime condizioni, un giocatore umano che abbia la prima mossa e che conosca tale strategia vincente, può ovviamente vincere contro il computer. Il programma deve giocare una partita dopo l'altra, fino a quando l'utente non introduce un opportuno comando che interrompe il gioco. Ogni partita è completamente indipendente dalle precedenti, sia per numero di biglie iniziali, sia per stupidità/intelligenza del computer, sia per assegnazione della prima mossa. Attenzione alle specifiche incomplete: occorre definire bene il "dialogo" tra il programma e l'utente. Attenzione: questo esercizio è un po' "al limite" per il livello di preparazione raggiunto nel corso, ma provateci, un po' come se fosse una "sfida"... Per risolvere un problema articolato come questo, occorre procedere "per gradi", individuando soluzioni di problemi intermedi che si possano collaudare, in modo da aggiungere funzionalità a uno schema già funzionante, altrimenti, se si collauda il programma soltanto alla fine, diventa ESTREMAMENTE difficile diagnosticare i problemi che si manifestano (e che ci saranno senz'altro...). Un possibile schema da seguire potrebbe essere questo: impostare un ciclo (virtualmente) infinito, il cui corpo conterrà tutto ciò che serve per giocare una partita, ma che per il momento abbia soltanto il compito di chiedere all'utente se vuole giocare un'altra partita, gestendo accuratamente tutti i casi ("Vuoi giocare ancora?": risposta S, risposta N, risposta diversa); questa fase di input richiede, a sua volta, un ciclo, che termini soltanto quando l'utente risponde S o N; risolto il problema, collaudare il programma in tutti i casi possibili e verificare che il comportamento sia sempre corretto arricchire il corpo del ciclo principale (quello impostato al passo precedente), aggiungendo la fase di inizializzazione dei parametri di gioco (chi giocherà per primo? il computer sarà "intelligente" oppure no? quante biglie saranno inizialmente in gioco?), con temporanea visualizzazione di tali parametri, procedendo a un loro collaudo con più esecuzioni, verificando anche che i parametri cambino di partita in partita se il giocatore chiede di giocare di nuovo (senza eseguire di nuovo il programma) concludere la soluzione del problema inserendo nel corpo del ciclo principale, tra la fase di inizializzazione dei parametri e la fase di richiesta "Vuoi giocare ancora?", un ciclo che gestisca i turni (alternando i due giocatori, umano e computer), tenendo conto della quantità di biglie rimaste nel mucchio e decidendo quando la partita è finita, decretando il vincitore; collaudare il programma completo mediante molteplici esecuzioni from random import * def main() : finish = True while finish : print("Benvenuto nel gioco di Nim.") count = 0 player = randomBoolean() numBalls = randint(10,100) master = randint(1, 2) computerPlayerIsExpert = False if master == 1: computerPlayerIsExpert = True print("Computer intelligente") else : print("Computer stupido") print("Le biglie totali sono: ", numBalls) while numBalls >1 : rimaste = 0 if player : print("Tocca al giocatore") newnumBalls = askUserBalls(numBalls) else: print("Tocca al computer") newnumBalls = takeComputerBalls(computerPlayerIsExpert,numBalls) rimaste = numBalls - newnumBalls numBalls = newnumBalls print("Sono state prese:" , rimaste ,"biglie. Ora le biglie sono:" , numBalls) player = not player if player : print("Hai perso") else : print("Hai vinto") finish = playAgain() def askUserBalls(numBalls) : repeat = True while repeat : balls = int(input("Quante biglie vuoi prendere? ")) if balls < 1 or balls > numBalls//2 : print("Errore! Il valore delle biglie deve essere compreso tra uno e la metà del totale delle biglie esclusa. Riprova!") else : numBalls -= balls repeat = False return numBalls def takeComputerBalls(computerPlayerIsExpert,numBalls) : if computerPlayerIsExpert : if numBalls == 3 or numBalls == 7 or numBalls == 15 or numBalls == 31 or numBalls == 63: balls = randint(1, numBalls // 2) numBalls -= balls elif numBalls > 63: balls = numBalls - 63 elif numBalls > 31: balls = numBalls - 31 elif numBalls > 15: balls = numBalls - 15 elif numBalls > 7: balls = numBalls - 7 elif numBalls > 3: balls = numBalls - 3 else: balls = 1 else : balls = randint(1, numBalls // 2) numBalls -= balls return numBalls def playAgain() : playagain = input("Vuoi giocare ancora? ""s"" per il sì oppure ""n"" per il no: ") if playagain == "n" : return False elif playagain == "s" : return True def randomBoolean() : x = randint(1,2) if x == 1 : return True else : return False main()