Lo he revisado muchas veces y no encuentro error alguno!
Encontre el inconveniente. había cerrado el modulo donde no corresponde, sin embargo el test no arrojo especificamente este error. Hay forma de que lo haga?
El problema es que no es un error en la lógica del test, es un error que no encuentra unaclase, te indica la linea que es la 4 en el archivo actions.rb en la función move_snake, pero el no sabe si es que esta mal cerrado un bloque, o es que no esta importada la función o realmente no existe, el intenta importar la función no la encuentra entonces lanza el error.
¿No se va un error en el minuto 2:40? Cuando se hace CMD + v para la inicialización del estado expected_state creo que se va un error porque se vuelve a inicializar el initial_state, lo que se transforma en falsos positivos porque siempre van a ser iguales ambos estados
Bueno, en el video "Preparando el cambio de dirección" detecta el error y lo corrige :D
Al fin pude pasar ministest despues rato analizando en que me habia equivocado..
Con comentarios para ver que hace cada cosa.
actions.rb
module Actions #En este modulo se realizan las todas las acciones consecutivos a cada evento(avanzar, voltear).def self.move_snake(state) #creamos el metodo para confirmar si el movimiento sera factible.next_direction= state.next_direction #variable next_direction toma los datos de la direccion que tomara la culebra
next_position =calc_next_position(state) # # Entrega la siguiente posicion dado siguiente movimiento ingresado
if position_isvalid?(state, next_position) #Verificar que la siguiente posicion es factible.move_snake_to(state, next_position) # # Metodo asigna la nueva posicion de la serpiente actualizada
elseend_game(state) # en caso de no ser posicion factible fin del juego
end
end
private def self.calc_next_position(state) # Entrega la siguiente posicion dado siguiente movimiento ingresado
curr_position = state.snake.positions.first # curr_position toma el valor de la posicion actual de la serpiente
case state.next_direction # Evalua la posicion hacia donde ira al culebra
when Model::Direction::UP # Evalua si culebra va hacia arriba
returnModel::Coord.new(curr_position.row-1,curr_position.col) #Devuelve el calculo de la siguiente posicion dado el movimiento hacia arriba
when Model::Direction::RIGHT # Evalua si culebra va hacia la derecha
returnModel::Coord.new(curr_position.row,curr_position.col+1) #Devuelve el calculo de la siguiente posicion dado el movimiento hacia arriba
when Model::Direction::DOWN # Evalua si culebra va hacia abajo
returnModel::Coord.new(curr_position.row+1,curr_position.col) #Devuelve el calculo de la siguiente posicion dado el movimiento hacia arriba
when Model::Direction::LEFT# Evalua si culebra va hacia izquierda
returnModel::Coord.new(curr_position.row,curr_position.col-1) #Devuelve el calculo de la siguiente posicion dado el movimiento hacia arriba
end
end
def self.position_isvalid?(state, position) #Verifica si la siguiente posicion sale de la grilla o si esta repitiendo alguna posicion de la culebra ya existente.is_valid=((position.row>= state.grid.rows|| position.row<0)||(position.col>= state.grid.cols|| position.col<0)) # Verificar que este dentro en la grilla
# Verificar que no este superponiendo a la serpiente
returnfalseif is_valid # retorna falso si is_valid resulta ser truereturn!(state.snake.positions.include? position) #Si la is_valid es falso evalua si en la lista de posiciones de la culebra se repite la siguiente posicion
end
def self.move_snake_to(state,next_position) # Le asigna la nueva posicion de la serpiente actualizada
new_positions =[next_position]+ state.snake.positions[0...-1] # variable new_positions toma el valor de las posiciones de la snake menos la ultima(cola) y le agrega la siguiente
state.snake.positions= new_positions # se asigna la nueva posicion de la serpiente
return state # retorna los datos del estado con sus variables actualizadas
end
def self.end_game(state) # Metodo para verificar si se acabo el juego(si se rompieron alguna de las condiciones para seguir) state.game_fishined=true # Cambia variable a truereturn state # retorna estado actualizado
end
end
state.rb
module Model module DirectionUP=:up
RIGHT=:right
DOWN=:down
LEFT=:left
end
classCoord<Struct.new(:row,:col) # crea clase coordenadas con row y col inicializados con setters y getter
end
classFood<Coord # clase food hereda de clase coord
end
classSnake<Struct.new(:positions) # posiciones cabeza de serpiente y cola
end
classGrid<Struct.new(:rows,:cols)# crea clase coordenadas con rows y cols inicializados con setters y getter
end
classState<Struct.new(:snake,:food,:grid,:next_direction,:game_fishined) # crea clase coordenadas con snake, food y grid inicializados con setters y getter
end
def self.initial_state # definicion de estado inicial
Model::State.new(Model::Snake.new([ # coordenadas de cabeza y cola o inicio y fin
Model::Coord.new(1,1),Model::Coord.new(0,1)]),Model::Food.new(4,4), # inicializamos coordenada de comida
Model::Grid.new(8,12), # coordenada de grid
Model::Direction::DOWN, # coordenada de Gridfalse) end
end
app.rb
require_relative "view/ruby2d" # importamos los metodos del archivo state.rbrequire_relative "model/state" # importamos los metodos del archivo state.rbclassApp def Start view =View::Ruby2dView.new # variable view instancia de la clase Ruby2dView initial_state =Model::initial_state # variable initial_state que almacena los datos del estado inicial.view.render(initial_state) # se renderiza el estado inicial con los datos asignados.end
def init_timer
loop do sleep 0.5 #trigger movement
end
end
end
actions_test.rb
require "minitest/autorun"require_relative "../src/actions/actions" #
require_relative "../src/model/state"classActionsTest<Minitest::Test def test_move_snake
initial_state =Model::State.new(Model::Snake.new([ # coordenadas de cabeza y cola o inicio y fin
Model::Coord.new(1,1),Model::Coord.new(0,1)]),Model::Food.new(4,4), # inicializamos coordenada de comida
Model::Grid.new(8,12), # coordenada de grid
Model::Direction::DOWN, # coordenada de Gridfalse) expected_state = initial_state =Model::State.new(Model::Snake.new([ # coordenadas de cabeza y cola o inicio y fin
Model::Coord.new(2,1),Model::Coord.new(1,1)]),Model::Food.new(4,4), # inicializamos coordenada de comida
Model::Grid.new(8,12), # coordenada de grid
Model::Direction::DOWN, # coordenada de Gridfalse) actual_state =Actions::move_snake(initial_state) assert_equal actual_state, expected_state
end
end
Para que sirve self?
Sirve para hacer referencia al mismo contexto de la clase o el modulo, si se utiliza antes del nombre del método (como lo vemos en el video) entonces hace referencia al contexto del modulo entonces podemos llamar a la función sin necesitad de instanciarla.
Básicamente cuando se le pone self antes del nombre del método es un método de clase y de lo contrario es un método de instancia.
Se soluciona quitando los espacios en curr_position.col +1), los incrementos y decrementos deben quedar JUNTO a la col y row, es decir así:
when Model::Direction::UP #decrementar la fila
returnModel::Coord.new( curr_position.row-1, curr_position.col) when Model::Direction::RIGHT #incrementar la col
returnModel::Coord.new( curr_position.row, curr_position.col+1) when Model::Direction::DOWN #incrementar la fila
returnModel::Coord.new( curr_position.row+1, curr_position.col) when Model::Direction::LEFT #decrementar la col
returnModel::Coord.new( curr_position.row, curr_position.col-1) end
que raro que eso sea un error
Me sirvio, gracias.
Hola, esta vez si tengo estos errores tratando de correr el test:
He revisado codigo y gemas y no encuentro la vuelta! :)
Si sigues teniendo problemas te puedo compartir mi codigo, al final lo solucione cuando fui avanzando en las clases, solo avisame aunque puedes tambien encontrar el codigo completo en los links!
Si minitest viene incluído en la standard library, ¿por qué se tiene que agregar como dependencia del gem file?
Me queda una duda respecto al proceso que se sigue para comparar el movimiento.
En tu código escribes:
Ahí estás sobre escribiendo el initial state con el valor de expected state, no?, al compararlo te dará que es verdad porque es como si le estuvieras pasando el expected state a la función move, no?. Literalmente puedes borrar la definición de initial state que ahces al comienzo y sigue ejecutandose igual
Y si no haces esa igualación, el problema es que estás llamando a objetos del mismo valor pero en dos espacios de memoria diferentes, así que el mintest te arrojará error igualmente
No visible difference in the Model::State #inspect output.You should look at the implementation of #== on User or its members.
La solución que yo encontré fue alterar el método de comparación de la clase state, para que comparara los valores de sus objetos más no el objeto en sí (por que compararía la estancia en memoria). Eso está bien o no tiene sentido o por qué igualaste los states en el tutorial?
gracias ;D
No se como insentar imagenes aca n comentarios.. me ayudan?
Hola. Es muy facil solo necesitas arrastrar la imagen hasta este cuadrod e dialogo, o pegar la url . Animo, no es difícil. si es código, también puedes pegarlo directamente con su etiqueta
<code>
Me funciona arrastrando la imagen hacia el comentario que estoy haciendo.
al fin despues de tanto analizar razones, pude dar con mis errores y pasar la minitest
Al estar utilizando Symbols en lo que es Direction::UP no es necesario el recorrido completo es decir Model::Direction::UP podemos poner directamente el valor de Symbol como :up o :down etc.
¿Por qué sale el error de cannot load such file -- minitest/autorun (LoadError) y se debe agregar en el Gemfile, si en la clase "Testing con MiniTest" se dice lo contrario? Que hace parte del core de ruby y se puede hacer uso así sin más. No me queda claro :thinking:
Depende de cómo se haya instalado la gema. Aquí hay varios conceptos distintos: Ruby incluye un set de bibliotecas que son requeridas por omisión, Standard Library, es muy pequeño. Adicionalmente a eso hay otro conjunto de librerías que son empaquetadas con Ruby y tienen que ser requeridas en forma explícita, pero no requieren de instalación adicional. Y están las gemas, estas se instalan aparte, tienen que ser requeridas. Dependiendo de como instales la gema esta puede estar disponible globalmente o solo por proyecto. El Gemfile especifica las dependencias de tu proyecto y via Bundler puede hacer el require
Si corres las pruebas sin utilizar el comando bundle no se necesita añadir la dependencia de minitest