Pídele al maestro de Python que me dé un código de unas 200 líneas, con más comentarios, para mi tarea final.
#-*-?coding:utf-8?-*-
import?curses?#Presentamos el módulo curses, curses es una función gráfica ampliamente utilizada en la biblioteca Linux/Unix ., cuya función es dibujar interfaces de usuario y hermosos gráficos en DOS.
from?random?import?randrange,?choice?#?Introducir clases randrange y Choice del módulo aleatorio
from?collections?import?defaultdict?#Introducir desde colecciones la clase defaultdict
letter_codes?=?[ord(ch)?for?ch?in?'WASDRQwasdrq']?#ord la función es convertir caracteres en números correspondientes
acciones ?=?[ 'Arriba',?'Izquierda',?'Abajo',?'Derecha',?'Reiniciar',?'Salir']?#Arriba, izquierda, abajo, derecha, reiniciar, salir
actions_dict ?=?dict(zip(letter_codes,?actions?*?2))?# Relaciona letras con acciones. ?zip corresponde a los valores de la tupla.
############################
¿Qué?Arriba
A?Izquierda
S?Abajo
D?Derecha
R?Reiniciar
Q?Salir
w?Arriba
a?Izquierda
s?Abajo
d?Derecha
r?Reiniciar
Q?Salir
#################################### ## #######?
def?get_user_action(teclado):
char?=?"N"?#El valor inicial de char es N while?char?not ? in?actions_dict:
char?=?keyboard.getch()return?actions_dict[char]?#Bloquear + bucle hasta que se obtenga una entrada válida del usuario antes de devolver el comportamiento correspondiente def?transpose(field):return ?[lista(fila)?para?fila?en?zip(*campo)]?#La función zip agrega el signo * para convertir las filas en columnas y las columnas en filas.
Entonces, este código es una transposición de filas y columnas def?invert(field):return?[row[::-1]?for?row?in?field]?#Este código es para invertir la clase de lista?GameField(object) :?#Crear una clase llamada GameField para crear un tablero de ajedrez def?__init__(self,?height=4,?width=4,?win=2048):?Esta clase tiene tres parámetros self.height?=?height #High? self.width?=?width?#Ancho self.win_value?=?win#Puntuación de pase self.score?=?0#Puntuación actual self.highscore?=?0#Puntuación más alta self.reset()#Restablecer tablero de ajedrez def? reset(self): #Defina una función de reinicio if?self.score?>?self.highscore: #Si el puntaje actual es mayor que el puntaje más alto, asigne el puntaje actual al puntaje más alto self.highscore?=?self .scoreself .score?=?0#Restaurar la puntuación actual a 0 puntos self.field?=?[[0?for?i?in?range(self.width)]?for?j?in?range(self. altura)] #Las coordenadas horizontales y verticales se restauran a (0,0) self.spawn()#Llamar a la función de generación self.spawn()def?move(self,?direction):#Definir la función de movimiento def?move_row_left (fila):#A la izquierda Mover def?tighten(fila):?#?squeese?non-zero?elements?together?Comprime elementos dispersos distintos de cero
new_row?=?[i? for?i?in?row?if?i?!=?0]?#Si i no es igual a cero, asígnalos a la tupla new_row
new_row?+=?[0?for? i?in?range( len(row)?-?len(new_row))]#Complementar las posiciones restantes con 0 return?new_row#Devolver esta tupla def?merge(row):#Definir la función de combinación para fusionar unidades p>
par?=?False#el valor inicial del par es falso
new_row?=?[]#new_row el valor inicial está vacío for?i?in?range(len(row)):# Déjame estar en la cuadrícula Bucle if?pair: Si el par es verdadero
new_row.append(2?*?row[i])# Luego multiplica el valor de rowi por 2 y añádelo a new_row self .score?+= ?2?*?row[i]#Y la puntuación es el valor de rowi multiplicado por 2
pair?=?False#pair se reasigna a false else: si el par es verdadero if?i?+?1 ?
¿par?=?¿Verdadero?#Entonces el par es verdadero
new_row.append(0)#Agregar cero después de new_row else:
new_row.append(row[i]) #De lo contrario, agregue rowi
assert?len(new_row)?==?len(row)?#Recuerde que las dos longitudes son iguales return?new_rowreturn?tighten( merge(tighten(row)))?#Fusión repetida, hasta que sepas que no se puede fusionar
moves?=?{}
moves['Left']?=? lambda?campo:?\
p>
[move_row_left(row)?for?row?in?field]#Move
mueve['Derecha']?=?lambda?field:?\
invert(moves['Left'](invert(field)))#invert es la inversión
moves['Up']=?lambda?field:?\
transpose( mueve['Izquierda'](transpose(campo)))#transpose es transponer
mueve['Abajo']?=?lambda?field:?\
transpose(mueve [ 'Derecha'](transponer(campo)))if?dirección?in?moves:if?self.move_is_possible(dirección): #Si la dirección del movimiento es en cuatro direcciones, self.field?=?moves[dirección]( self .field) luego llame a la función de movimientos self.spawn()#generar un número aleatorio return?Trueelse:return?Falsedef?is_win(self):return?any(any(i?>=?self.win_value?for?i? ¿en? pantalla ):
help_string1?=?'(W)Arriba?(S)Abajo?(A)Izquierda?(D)Derecha'
help_string2?=?'?(R ) ¿Reiniciar?(Q)Salir'
gameover_string?=?'GAME?OVER'
win_string?=?'?YOU?WIN!'def?cast(string):
p>screen.addstr(string?+?'\n')def?draw_hor_separator():
linea?=?'+'?+?('+--- --- '?*?self.width?+?'+')[1:]
separator?=?defaultdict(lambda:?line)if?not?hasattr(draw_hor_separator,?"contador "):
draw_hor_separator.counter?=?0
cast(separator[draw_hor_separator.counter])
draw_hor_separator.counter?+=?1def?draw_row (fila) :
cast(''.join('|{:?^5}?'.format(num)?if?num?>?0?else?'|?'?for ?num? en?fila)?+?'|')
screen.clear()
cast('PUNTUACIÓN:?'?+?str(self.score)) if?0 ?=?self.highscore:
cast('HGHSCORE:?'?+?str(self.highscore))for?row?in?self.field:
draw_hor_separator ()
dibujar
_row(fila)
draw_hor_separator()if?self.is_win():
cast(win_string)else:if?self.is_gameover():
cast(gameover_string)else:
cast(help_string1)
cast(help_string2)def?spawn(self):
new_element?=?4?if? randrange(100)?>?89?else?2
(i,j)?=?choice([(i,j)?for?i?in?range(self.width)?for ?j?in?range(self.height)?if?self.field[i][j]?==?0])self.field[i][j]?=?new_elementdef?move_is_possible(self,?dirección ):def?row_is_left_movable(fila):?
def?change(i):?#?verdadero?si?habrá?cambio?en?i-ésimo?tileif?fila[i ]?==?0?y?fila[i?+?1]?=?0:?#?Movereturn?Trueif?fila[i]?=?0?y?fila[i?+?1] ?= =?fila[i]:?#?Mergereturn?Truereturn?Falsereturn?any(change(i)?for?i?in?range(len(row)?-?1))
comprobar? =?{}
check['Left']?=?lambda?field:?\
any(row_is_left_movable(row)?for?row?in?field) p>
comprobar['Derecha']?=?lambda?campo:?\ comprobar['Izquierda'](invertir(campo))
comprobar['Arriba']=?lambda ?campo :?\
marcar['Izquierda'](transponer(campo))
marcar['Abajo']?=?lambda?field:?\
comprobar['Derecha'](transponer(campo))si?dirección?en?comprobar:regresar?comprobar[dirección](self.campo)else:retorno?Falsedef?main(stdscr):def?init() :# Restablecer el tablero de juego
game_field.reset()return?'Game'def?not_game(state):#Dibuja la interfaz GameOver o Win
game_field .draw(stdscr)#Leer entrada del usuario para obtener acción y determinar si reiniciar o finalizar el juego
action?=?get_user_action(stdscr)
responses?=?defaultdict(lambda: ?state)?#The El valor predeterminado es el estado actual. Si no hay ninguna acción, siempre se repetirá en la interfaz actual
responses['Restart'],?responses['Exit']?=?'Init',?' Salir '?#Convertir a diferentes estados correspondientes a diferentes comportamientos return?responses[action]def?game(
): #Dibujar el estado actual del tablero de ajedrez
game_field.draw(stdscr)#Leer la entrada del usuario para obtener acción
action?=?get_user_action(stdscr)if?action?==? 'Reiniciar':regresar?'Init'if?action?==?'Salir':regresar?'Salir'if?game_field.move(action):?#?move?successfulif?game_field.is_win():return?' Win'if?game_field.is_gameover():return?'Gameover'return?'Game'
state_actions?=?{'Init':?init,'Win':?lambda:?not_game(' Win'),'Gameover':?lambda:?not_game('Gameover'),'Game':?game
}
curses.use_default_colors()
game_field?=?GameField(win=32)
state?=?'Init'#La máquina de estados comienza a realizar un bucle while?state?!=?'Exit':
estado ?=?state_actions[estado]()
curses.wrapper(principal)