Hundir la flota en ensamblador

Hecho con un simulador MIPS en java que podéis descargar. Si alguien necesita ayuda para ejecutar el código, que deje un comentario.

El código es funcional, faltaría poner un poco de inteligencia artificial (modo difícil) y usar los nombres de los jugadores que se pueden personalizar.

Los barcos enemigos se muestran, lo dejé así para probar si funciona. Si quieres jugarlo de verdad, cambia el uno a cero en la sección del bucle de juego, en la línea 503:
li $a3, 1 #cero si no quiero que muestre los barcos enemigos

Hundir la flota: Pulsa para ver/ocultar el código
#======================================================================================
#    HUNDIR LA FLOTA
#          by Dorian Hawkmoon
# Open Source
# Estilo Callee-saved
# Iniciado en 17-6-2012 (pausado en 21-6-2012) continuado en 12-09-2012
# Finalizado en 14-09-2012
#======================================================================================



.data
 menu1: .asciiz "1. Jugar\n"
 menu2: .asciiz "2. Opciones\n"
 menu3: .asciiz "3. Salir\n"
 
 opcion1: .asciiz "1. Tamaño tablero\n"
 opcion2: .asciiz "2. Numero de barcos\n"
 opcion3: .asciiz "3. Dificultad\n"
 opcion4: .asciiz "4. Cambiar nombres jugadores\n"
 opcion5: .asciiz "5. Volver al menú\n"
 
 separacion: .asciiz "==============================================================\n"
 matrizJugador1:.space 520
 matrizJugador2: .space 520
 maximos: .byte 3, 26, 20 #máximo 3 barcos de cada tipo, 26 columnas y 20 filas de tablero
 datos: .byte 'A', 'a', '-', '_', '|', 171, '\n', ' '
 letra: .space 2 #dos para que el cero que añade al final cuando pido no pise los siguientes datos
 
 tamañoMatriz: .byte 10, 10 #columnas-filas
 numeroBarcos: .byte 1, 1, 1, 1, 1
 dificultad: .byte 0 #cero= fácil (al azar) 1=dificil (inteligencia)
 jugador1: .asciiz "Jugador1\n"
 jugador2: .asciiz "Jugador2\n"
 
 numeroCasillasFinal: .byte 0
 casillasDadasPrimerJugador: .byte 0
 casillasDadasSegundoJugador: .byte 0
 
 
 seleccionOpcion: .asciiz "Seleccione una opción:\n"
 errorOpcion: .asciiz "Opción incorrecta, vuelva a seleccionar una opción.\n"
 mensajeErrorLetraTiro: .asciiz "Error, la letra está fuera de rango\n"
 mensajeErrorNumeroTiro: .asciiz "Error, el número está fuera de rango\n"
 
 tablaPropia: .asciiz "\nSus barcos y los disparos que le hicieron:\n"
 tablaDisparos: .asciiz "\nLos disparos que ha realizado:\n"
 seleccionarColumna: .asciiz "Seleccione la columna donde disparar (letra): "
 seleccionarFila: .asciiz "\nSeleccione la fila donde disparar (número): "
 colocarColumna: .asciiz "\nSeleccione la columna donde colocarlo (letra): "
 colocarFila:.asciiz "\nSeleccione la fila donde colocarlo (número): "
 
 mensajeTocadoIA:.asciiz "¡El enemigo te ha dado!  "
 mensajeAguaIA: .asciiz "El enemigo dió en agua: "
 mensajeAgua: .asciiz "Agua: "
 yaSeleccionado: .asciiz "Casilla ya seleccionada: "
 mensajeTocado: .asciiz "Barco tocado: "
 mensajeTocadoHundido: .asciiz "Barco tocado y hundido: "
 ganar: .asciiz "¡¡Ha ganado la partida!!"
 perder: .asciiz "Ha perdido la partida... :("

 ponerBarcos: .asciiz "Coloque los barcos de tamaño "
 ponerBarcos2: .asciiz ", le quedan "
 barcoMalColocado: .asciiz "Barco mal colocado, vuelva a intentarlo.\n"
 barcoEnMedio: .asciiz "Ya hay un barco en medio, colóquelo en otro sitio.\n"
 tamanoErroneo: .asciiz "El barco es más grande, especifique un sitio más grande\n"
 dificil: .asciiz "dificil\n"
 facil: .asciiz "fácil\n"
 
 
 cambioNumeroBarcos: .asciiz " El número de barcos de tamaño 1-2-3-4-5 está establecido en: "
 cambioNumeroBarcos2: .asciiz "Introduzca el número de barcos (máx. 3) de tamaño "
 cambioDificultadModo: .asciiz "El juego está establecido en modo "
 seleccionModo: .asciiz "Introduzca el número del modo deseado:"
 seleccionModoDificultad: .asciiz "\n0.Fácil\n1.Dificil\n"
 cambioNombres: .asciiz "El nombre del jugador 1 y 2 son:\n"
 cambioNombres2: .asciiz "Introduzca el nombre del primer jugador: "
 cambioNombres3: .asciiz "Introduzca el nombre del segundo jugador:"
 cambioTablero: .asciiz "El tamaño del tablero está establecido en: "
 opcionTableroColumnas: .asciiz "Introduzca el número de columnas (máx. 26): "
 opcionTableroFilas: .asciiz "Introduzca el número de filas (máx. 20): "
 
 
 .globl main
 .text
 
main:
 mostrarMenu:
  lb $a0, datos+7
  jal mostrarCaracter #salto de linea
   
  la $a0, separacion
  jal mostrarCadena
  la $a0, menu1
  jal mostrarCadena
  la $a0, menu2
  jal mostrarCadena
  la $a0, menu3
  jal mostrarCadena
  la $a0, separacion
  jal mostrarCadena

 #pedir opción
 la $a0, seleccionOpcion
 jal mostrarCadena
 jal pedirNumero
 move $t0, $v0
 
 #comienza el switch case
 beq $t0, 1, jugar
 beq $t0, 2, mostrarOpciones
 beq $t0, 3, salir
 
 #error opción, vuelvo a mostrar menú y pedir numero
 la $a0, errorOpcion
 jal mostrarCadena
 j mostrarMenu
 
 
 
 mostrarOpciones:
  la $a0, separacion
  jal mostrarCadena
  la $a0, opcion1
  jal mostrarCadena
  la $a0, opcion2
  jal mostrarCadena
  la $a0, opcion3
  jal mostrarCadena
  la $a0, opcion4
  jal mostrarCadena
  la $a0, opcion5
  jal mostrarCadena
  la $a0, separacion
  jal mostrarCadena
 
 #pido opción
 la $a0, seleccionOpcion
 jal mostrarCadena
 jal pedirNumero
 move $t0, $v0
 
 #comienza el switch case
 beq $t0, 1, tamaño
 beq $t0, 2, numero
 beq $t0, 3, dificultadJuego
 beq $t0, 4, cambioNombresJugadores
 beq $t0, 5,  mostrarMenu
 
 #error opción, vuelvo a mostrar el menú y pedir número
 la $a0, errorOpcion
 jal mostrarCadena
 j mostrarOpciones
 
 

#==============================================================================================
#  SECCIÓN APARTADOS DEL MAIN CORRESPONDIENTES A CADA OPCIÓN DEL MENÚ  
#==============================================================================================

 #cambio del tamaño del tablero
 tamaño:
  #muestro el tamaño establecido
  #El tamaño del tablero está establecido en: 10x10
  la $a0, cambioTablero
  jal mostrarCadena #muestro mensaje (El tamaño del tablero está establecido en:)
  
  la $t0, tamañoMatriz
  lb $a0, ($t0)
  jal mostrarNumero #muestro el número de columnas
  
  lb $t1, datos+1
  addi $t1, $t1, 23
  move $a0, $t1
  jal mostrarCaracter #muestro el x
  
  lb $a0, 1($t0)
  jal mostrarNumero #muestro el número de filas
  
  lb $a0, datos+6
  jal mostrarCaracter #muestro un salto de linea
 
  #pregunto por el tamaño deseado
  lb $t0, maximos+1 #columnas máximas
  columnasTablero:
  la $a0, opcionTableroColumnas
  jal mostrarCadena
  jal pedirNumero
  bgt $v0, $t0, columnasTablero
  sb $v0, tamañoMatriz#guardo la opción
  
  #pregunto por el tamaño deseado
  lb $t0, maximos+2 #maximo de filas
  filasTablero:
  la $a0, opcionTableroFilas
  jal mostrarCadena
  jal pedirNumero
  bgt $v0, $t0, filasTablero
  sb $v0, tamañoMatriz+1#guardo la opción
  
  #vuelvo al menú
  j mostrarOpciones
  
 
 #cambio el número de barcos de cada tipo
 numero:
  #muestro el número de barcos establecido
  la $a0, cambioNumeroBarcos
  jal mostrarCadena
  
  lb $t0, datos+2 #recojo el guion (-)
  la $t1, numeroBarcos
  li $t2, 5
  bucleNumBarcosMostrar: #por cada tamaño del barco muestro el número y lo separo con el guión   
   lb $a0, ($t1) #recojo el número y lo muestro
   jal mostrarNumero

   #actualizo puntero y contador
   addi $t1, $t1, 1
   addi $t2, $t2, -1
      
   beqz $t2, finBucleNumBarcosMostrar #compruebo si acabé
   
   move $a0, $t0 #recojo el carácter y lo muestro (-)
   jal mostrarCaracter

   j bucleNumBarcosMostrar
  finBucleNumBarcosMostrar:#cuando acabo continuo
  
  lb $a0, datos+6
  jal mostrarCaracter #muestro un salto de linea
  
  la $t0, cambioNumeroBarcos2 #frase
  la $t1, numeroBarcos #lugar donde guardo el número de barcos
  li $t2, 1 #contador
  lb $t4, datos+6 #salto de línea
  lb $t5, maximos #maximo de barcos por cada tamaño
  bucleCambiarNumBarcos:
   move $a0, $t0
   jal mostrarCadena #muestro cadena de petición...
   move $a0, $t2
   jal mostrarNumero #... del barco cuyo tamaño es el del contador
   move $a0, $t4
   jal mostrarCaracter #salto de linea para mejor presentación
   
   jal pedirNumero #pido número
   bgt $v0, $t5, bucleCambiarNumBarcos #si paso el máximo vuelvo a pedir
   sb $v0, ($t1) #lo guardo
   
   #actualizo puntero y contador, condición de salida y vuelvo al bucle
   beq $t2, 5, finBucleCambiarNumBarcos #cuando ya cambió los cinco tipos de barcos
   addi $t1, $t1, 1
   addi $t2, $t2, 1
   j bucleCambiarNumBarcos

  #cuando termino vuelvo al menú
  finBucleCambiarNumBarcos:
  j mostrarOpciones

  
 
 
 #cambio el nombre de los jugadores
 cambioNombresJugadores:
  #muestro el nombre establecido a los jugadores:
  #El nombre del jugador 1 y 2 son:
  la $a0, cambioNombres
  jal mostrarCadena
  
  la $a0, jugador1
  jal mostrarCadena #nombre jugador1
  la $a0, jugador2
  jal mostrarCadena#nombre jugador2
  
  lb $a0, datos+7
  jal mostrarCaracter #espacio de separación
  
  #pido ambos nombres
  la $a0, cambioNombres2
  jal mostrarCadena
  la $a0, jugador1
  la $a1, 8
  jal pedirCadena
  
  la $a0, cambioNombres3
  jal mostrarCadena
  la $a0, jugador2
  la $a1, 8
  jal pedirCadena
  
  j mostrarOpciones

  
 #cambio la dificultad al juego (contrincante ataca al azar, o si acierta un barco, atacará la zona hasta hundirlo)
 dificultadJuego:
  #muestro el modo establecido
  la $a0, cambioDificultadModo
  jal mostrarCadena
  

  #muestro el modo establecido
  lb $t0, dificultad
  la $a0, facil
  beq $t0, 0, mostrarDificultad
  la $a0, dificil
  mostrarDificultad:
   jal mostrarCadena
  
  
  #pido la dificultad escogida
  la $a0, seleccionModo
  jal mostrarCadena
  la $a0, seleccionModoDificultad
  jal mostrarCadena
  jal pedirNumero
  
  #cualquier error, vuelvo a mostrar el modo y pedir número
  blt $v0, 0, errorOpcionDificultad
  bgt $v0, 1, errorOpcionDificultad
  
  #guardo la opción
  sb $v0, dificultad
  j mostrarOpciones
  
  #cualquier error, vuelvo a mostrar el modo y pedir número
  errorOpcionDificultad:
   la $a0, errorOpcion
   jal mostrarCadena
   j dificultadJuego
 
 
 
 
 jugar:
  #inicializo unas variables que usaré mucho
  la $s0, letra
  la $s1, datos
  la $s2, tamañoMatriz
  
  #inicializo las matrices del juego
  move $a0, $s2
  la $a1, matrizJugador1
  jal inicializarMatricesCero
  
  move $a0, $s2
  la $a1, matrizJugador2
  jal inicializarMatricesCero
  
  #poner barcos
  #pongo los del enemigo
  la $a0, matrizJugador2
  move $a1, $s2
  la $a2, numeroBarcos
  move $a3, $s1
  jal colocarBarcosEnemigo

  #pongo los del jugador
  #Muestro la matriz de barcos del jugador
  move $a0, $s1
  move $a1, $s2
  la $a2, matrizJugador1
  li $a3, 1 #uno para que muestre los barcos
  jal dibujarTablero
  
  la $s3, numeroBarcos
  li $s5, 0
  li $s6, 0
  buclePonerBarcos: #bucle para poner todos los barcos
   beq $s5, 5, finBuclePonerBarcos
   addi $s5, $s5, 1
   
   lb $s4, ($s3) #recojo el número de barcos de ese tamaño
   addi $s3, $s3, 1
   bucleNumPonerBarco: #bucle para colocar todos los barcos de un determinado tamaño
    add $s6, $s6, $s5
    lb $a0, datos+7
    jal mostrarCaracter #salto de linea
    #muestro la frase para pedir donde colocar los barcos
    la $a0, ponerBarcos #"Coloque los barcos de tamaño "
    jal mostrarCadena
    move $a0, $s5
    jal mostrarNumero # X
    la $a0, ponerBarcos2
    jal mostrarCadena # ", le quedan "
    move $a0, $s4
    jal mostrarNumero # X (barcos)
    lb $a0, 6($s1)
    jal mostrarCaracter # \n
    
    li $s7, 1 #dos iteracciones para pedir inicio y fin de barco
    bucleColocarBarco: #bucle para colocar un determinado barco
     #pido el barco: primera iteracción, principio del barco, segunda iteracción, final del barco
     la $a0, colocarColumna
     jal mostrarCadena
     move $a0, $s0
     li $a1,2
     jal pedirCadena
     la $a0, colocarFila
     jal mostrarCadena
     jal pedirNumero
     move $t3, $v0
    
     lb $a0, ($s0) #letra
     move $a1, $t3 #numero
     move $a2, $s1 #datos
     move $a3, $s2 #tamaño matriz
     jal ajustesValoresCasilla
     beqz $v0, errorLetra
     beq $v0, 1, errorNumero
     
     beq $s7, 1, segundaIteraccion
      #queda guardado en pila letra-numero
      lb $t0, ($sp)
      addi $sp, $sp, 1
      addi $sp, $sp, -4
      sw $t0, ($sp) #letra
      addi $sp, $sp, -4
      sw $v1, ($sp) #letra
      j continuarColocandoBarco
     
     segundaIteraccion:
      #queda finalmente guardado #letra-numero(final) y letra-numero(inicial)
      lb $t0, ($sp)
      addi $sp, $sp, 1
      addi $sp, $sp, -4
      sw $t0, ($sp) #letra
      addi $sp, $sp, -4
      sw $v1, ($sp) #letra
     
     continuarColocandoBarco:
      beqz $s7, finBucleColocarBarco
      addi $s7, $s7, -1
     j bucleColocarBarco
     
     errorLetra:
      la $a0, mensajeErrorLetraTiro
      jal mostrarCadena
      j bucleColocarBarco
    
     errorNumero:
      la $a0, mensajeErrorNumeroTiro
      jal mostrarCadena
      j bucleColocarBarco
     
     
    finBucleColocarBarco: #compruebo que el barco esté bien colocado
     lw $a2, ($sp) #letra final
     addi $sp, $sp, 4
     lw $a3, ($sp) #numero final
     addi $sp, $sp, 4
     lw $a0, ($sp) #letra inicial
     addi $sp, $sp, 4
     lw $a1, ($sp) #numero inicial
     addi $sp, $sp, 4
     
     addi $sp, $sp, -4
     la $t3, matrizJugador1
     sw $t3, ($sp)
     lb $t4, tamañoMatriz
     addi $sp, $sp, -1
     sb $t4, ($sp)
     addi $sp, $sp, -1
     sb $s5, ($sp)
     jal colocacionCorrecta #compruebo que se ha colocado correctamente y si es así, lo coloca en la matriz
     beq $v0, 1, errorColocacion
     beq $v0, 2, errorBarcoMedio
     beq $v0, 3, errorTamanoBarco
     
     
     #Muestro la matriz de barcos del jugador
     lb $a0, datos+7
     jal mostrarCaracter #salto de linea
     move $a0, $s1
     move $a1, $s2
     la $a2, matrizJugador1
     li $a3, 1 #uno para que muestre los barcos
     jal dibujarTablero
     addi $s4, $s4, -1 #quito un barco de ese tamaño
     beqz $s4, buclePonerBarcos #si ya terminé con ese tamaño, voy por el siguiente
     j bucleNumPonerBarco
   
     errorColocacion:
      la $a0, barcoMalColocado
      jal mostrarCadena
      j bucleNumPonerBarco
     errorBarcoMedio:
      la $a0, barcoEnMedio
      jal mostrarCadena
      j bucleNumPonerBarco
      
     errorTamanoBarco:
      la $a0, tamanoErroneo
      jal mostrarCadena
      j bucleNumPonerBarco
   
  finBuclePonerBarcos:
   #guardo las casillas de barco final para obtener la victoria
   sb $s6, numeroCasillasFinal
  
  

#==============================================================================================
#        SECCIÓN BUCLE DEL JUEGO  
#==============================================================================================
  
  li $s2, 0
  li $s3, 0
  lb $s4, numeroCasillasFinal
  #inicio el bucle del juego
  bucleJuego:
   lb $a0, datos+7
   jal mostrarCaracter #salto de linea
   la $a0, separacion
   jal mostrarCadena
   lb $a0, datos+7
   jal mostrarCaracter #salto de linea
    
   #Comienzo con el jugador 1
   la $a0, tablaDisparos
   jal mostrarCadena
   
   #Muestro la matriz de disparos del jugador
   la $a0, datos
   la $a1, tamañoMatriz
   la $a2, matrizJugador2
   li $a3, 1 #cero si no quiero que muestre los barcos enemigos (esta a uno para debug) #############################################################
   jal dibujarTablero
   
   la $a0, tablaPropia
   jal mostrarCadena
   
   #Muestro la matriz de barcos del jugador
   la $a0, datos
   la $a1, tamañoMatriz
   la $a2, matrizJugador1
   li $a3, 1 #uno para que muestre los barcos
   jal dibujarTablero
   
   #pregunto por el tiro que quiere realizar
   preguntarTiro:
   la $a0, seleccionarColumna
   jal mostrarCadena
   la $a0, letra
   la $a1,2
   jal pedirCadena
   
   la $a0, seleccionarFila
   jal mostrarCadena
   jal pedirNumero
   
   #tengo en registros los datos obtenidos
   move $s1, $v0#numero
   la $t0, letra
   lb $s0, ($t0)
   
   
   # compruebo la casilla y la marco
   move $a0, $s0 #paso letra
   move $a1, $s1 #paso numero
   la $a2, matrizJugador2 
   la $a3, datos
   addi $sp, $sp, -4 #actualizo el puntero
   la $t0, tamañoMatriz
   sw $t0, ($sp) #limites
   jal comprobarCasilla #comprueba que es correcto y lo marca
   
   #switch case
   beq $v0, 2, agua
   beq $v0, 3, tocado
   beq $v0, 4,  seleccionado
   la $a0, mensajeErrorLetraTiro #presupongo error en la letra
   beqz $v0, errorTiro #si efectivamente es error de letra, salto al errorTIro
   la $a0, mensajeErrorNumeroTiro # si no lo es, pongo error de numero y salto al errorTiro
   j errorTiro
   
   tocado:
    #incremento contador de tocados
    addi $s2, $s2, 1
    la $a0, mensajeTocado
    j coordenadasTirada
   
   agua:
    la $a0, mensajeAgua
    j coordenadasTirada
    
   seleccionado:
    la $a0, yaSeleccionado
    j coordenadasTirada
    
    
   coordenadasTirada:
    jal mostrarCadena
    move $a0, $s0
    jal mostrarCaracter
    move $a0, $s1
    jal mostrarNumero
    lb $a0, datos+6
    jal mostrarCaracter
    beq $s2, $s4, partidaGanada  
    
   tiroIA:
    lb $s0, tamañoMatriz #limite columna
    lb $s1, tamañoMatriz+1 #limite fila
    
    move $a0, $s0
    jal generarNumero
    move $s0, $v0#escojo columna
    
    move $a0, $s1 
    jal generarNumero
    move $s1, $v0 #escojo fila 
    
    # compruebo la casilla y la marco
    move $a0, $s0 #paso letra
    addi $a0,$a0, 97
    move $a1, $s1 #paso numero
    addi $a1, $a1, 1
    la $a2, matrizJugador1
    la $a3, datos
    addi $sp, $sp, -4 #actualizo el puntero
    la $t0, tamañoMatriz
    sw $t0, ($sp) #limites
    jal comprobarCasilla #comprueba que es correcto y lo marca
   
    #switch case
    beq $v0, 2, aguaIA
    beq $v0, 3, tocadoIA
    j tiroIA  
    
   tocadoIA:
    #incremento contador de tocados
    addi $s3, $s3, 1
    la $a0, mensajeTocadoIA
    j tiradaIA
   
   aguaIA:
    la $a0, mensajeAguaIA
    j tiradaIA
    
   tiradaIA:
    jal mostrarCadena
    move $a0, $s0
    addi $a0, $a0, 97
    jal mostrarCaracter
    move $a0, $s1
    addi $a0, $a0, 1
    jal mostrarNumero
    lb $a0, datos+6
    jal mostrarCaracter
    beq $s3, $s4, partidaPerdida
    j bucleJuego
       
   
   
 errorTiro:
  jal mostrarCadena
  j preguntarTiro
  
 partidaGanada:
  lb $a0, datos+7
  jal mostrarCaracter #salto de linea
  la $a0, ganar
  jal mostrarCadena
  lb $a0, datos+7
  jal mostrarCaracter #salto de linea
  j mostrarMenu
  
  
 partidaPerdida:
  lb $a0, datos+7
  jal mostrarCaracter #salto de linea
  la $a0, perder
  jal mostrarCadena
  lb $a0, datos+7
  jal mostrarCaracter #salto de linea
  j mostrarMenu
 
 salir:
  li $v0, 10
  syscall
 
 
 

#==================================================================================================
#   MÉTODOS
#==================================================================================================

# Muestra la cadena pasada por parámetro
# parametros pasados: $a0 -> la cadena a mostrar
mostrarCadena:
 li $v0, 4
 syscall
 jr $ra
 
# Pide un número y lo devuelve
pedirNumero:
 li $v0, 5
 syscall
 jr $ra
 
# Muestra el número
# $a0, el número
mostrarNumero:
 li $v0, 1
 syscall
 jr $ra

#Muestra el caracter dado
# $a0, el carácter
mostrarCaracter:
 li $v0, 11
 syscall
 jr $ra
 
# Pide una cadena
#$a0, cadena a mostrar
# $a1, maximo caracteres
pedirCadena:
 li $v0, 8
 syscall
 jr $ra
 
 
# Genera un número aleatorio
# $a0 limite superior del rango de números (no incluido)
# $v0 el número aleatorio
generarNumero:
 li $v0, 42
 move $a1, $a0
 li $a0, 5
 syscall
 move $v0, $a0
 jr $ra
 
 
 
# Coloca los barcos del enemigo
# $a0 -> matriz del enemigo
# $a1 -> puntero a los tamaños de la matriz
# $a2 -> puntero al número de barcos
# $a3 -> puntero Datos
colocarBarcosEnemigo:
 #guardo retorno
 addi $sp, $sp, -4
 sw $ra, ($sp)
 
 #guardo $sX
 addi $sp, $sp, -4
 sw $s0,($sp)
 addi $sp, $sp, -4
 sw $s1,($sp)
 addi $sp, $sp, -4
 sw $s2,($sp)
 addi $sp, $sp, -4
 sw $s3, ($sp)
 addi $sp, $sp, -4
 sw $s4,($sp)
 addi $sp, $sp, -4
 sw $s5,($sp)
 addi $sp, $sp, -4
 sw $s6,($sp)
 addi $sp, $sp, -4
 sw $s7,($sp)
 
 move $s0, $a0 # matriz
 move $s6, $a1
 lb $s2, ($s6) #numero de columnas
 lb $s1, 1($s6) #numero de filas
 move $s3, $a2 #tamaños
 move $s7, $a3 #Datos
 
 li $s4, 0 #contador tamaño barcos
 bucleBarcosEnemigos:
  beq $s4, 5, finBucleBarcosEnemigos
  addi $s4, $s4, 1
  lb $s5, ($s3) #numero barcos de ese tamaño
  addi $s3, $s3, 1 #incremento contador
  
  bucleBarcoEnemigo:
   beqz $s5, bucleBarcosEnemigos
    
    #genero aleatoriamente una casilla
    move $a0, $s2
    addi $a0, $a0, 1
    jal generarNumero
    move $t0, $v0 # columna
    move $a0, $s1
    addi $a0, $a0, 1
    jal generarNumero
    move $t1, $v0 # fila
    
    # selecciono aleatoriamente si horizontal o vertical
    li $a0, 2
    jal generarNumero
    beqz $v0, enemigoVertical
    
   # enemigoHorizontal:
   move $t2, $t0
   add $t3, $t1, $s4
   j colocacionBarcoEnemigo
   
    enemigoVertical:
   move $t3, $t1
   add $t2, $t0, $s4
    
    colocacionBarcoEnemigo:
    #compruebo un momento que la segunda casilla esté dentro del rango
    bge $t2, $s2 , bucleBarcoEnemigo
    bge $t3, $s1, bucleBarcoEnemigo
    
   move $a0, $t0
   move $a1, $t1
   move $a2, $t2
   move $a3, $t3
   addi $sp, $sp, -4
   sw $s0, ($sp)
   addi $sp, $sp, -1
   sb $s2, ($sp)
   addi $sp, $sp,-1
   sb $s4, ($sp)
   jal colocacionCorrecta
   bnez $v0, bucleBarcoEnemigo #si no es correcto, salto al bucle a que genere de nuevo la casilla
    
     #es correcto y ya lo ha colocado
   addi $s5, $s5, -1
   j bucleBarcoEnemigo
   
  finBucleBarcosEnemigos:
  #recupero los datos de la pila y regreso
  lw $s7,($sp)
  addi $sp, $sp, 4
  lw $s6,($sp)
  addi $sp, $sp, 4
  lw $s5,($sp)
  addi $sp, $sp, 4
  lw $s4, ($sp)
  addi $sp, $sp, 4
  lw $s3,($sp)
  addi $sp, $sp, 4
  lw $s2,($sp)
  addi $sp, $sp, 4
  lw $s1,($sp)
  addi $sp, $sp, 4
  lw $s0,($sp)
  addi $sp, $sp, 4

  lw $ra, ($sp)
  addi $sp, $sp, 4
  jr $ra 
 
# Comprueba que el barco esté bien colocado y entonces lo coloca
# Parámetros que recibe:
# $a0, letraInicio (valor ajustado)
# $a1, numeroInicio (valor ajustado)
# $a2, letra final (valor ajustado)
# $a3, numero final (valor ajustado)
# word en pila, puntero a la matriz del jugador donde se está colocando
# byte en pila, numero de columnas máximas
# byte en pila, tamaño del barco
# Devuelve:
# $v0: 0-> correcto
# 1 -> mal colocado (solo se puede horizontal o vertical y no se pueden cortar con nada)
# 2 -> mal colocado (hay otro barco en medio)
# 3 -> no cabe el barco
colocacionCorrecta:
 li $v0, 1 #presupongo mala colocación horizontal/vertical
 move $t0, $a0 #letra inicio
 move $t1, $a1 #numero inicio
 move $t2, $a2 #letra final
 move $t3, $a3 #letra final
 lb $t9, ($sp) #tamaño barco 
 addi $sp, $sp, 1
 lb $t5, ($sp) #columnas máximas
 addi $sp, $sp, 1
 lw $t4, ($sp) #matriz jugador
 addi $sp, $sp, 4
 
 #guardo en pila el retorno
 addi $sp, $sp, -4
 sw $ra, ($sp)
 
 #me faltan registros $tx, por lo que dejo este en $sx y guardo en pila el valor anterior
 addi $sp, $sp, -4
 sw $s0,($sp)
 addi $sp, $sp, -4
 sw $s1,($sp)
 move $s0, $t9 #en $s0 está el tamaño del barco
 move $s1, $t9
 
 beq $t0, $t2, incrementoNumero #están en la misma columna...
 beq $t1, $t3 incrementoColumna #están en la misma fila....
 j establecerSX
 
 incrementoColumna: 
  li $v0, 2 #presupongo barcos por el medio
  bgt $t2, $t0, continuoIncrementoColumna
  #intercambio los registros
  move $t6, $t2
  move $t2, $t0
  move $t0, $t6
  
  continuoIncrementoColumna:
  #fórmula para hallar la posición dada en la matriz (Ncolumnas*fila+columna)
  mul $t7, $t5, $t3#hallo la posición final que dará la condición de salida del bucle errónea (debe salir con el contador)
  add $t7, $t7, $t2
  
  bucleCruceBarcos2:
   addi $s1, $s1, -1
   mul $t6, $t5,$t1
   add $t6, $t6, $t0
   
   add $t8, $t4, $t6 #obtengo la posición del puntero en la matriz
   lb $t9, ($t8) #obtengo el valor de la casilla
   #comparo valores
   beq $t9, 3, establecerSX #si es igual a tres, entonces ya hay un barco ahí
   beqz $s1, finBucleCruceBarcos
   beq $t7, $t6, errorTamano #si esa casilla ya era la última salgo del ciclo con error porque el barco es más grande
   #incremento el número de la columna
   addi $t0, $t0, 1
   j bucleCruceBarcos2
 
 incrementoNumero:
  li $v0, 2 #presupongo barcos por el medio
  bgt $t3, $t1, continuoIncrementoNumero
  #intercambio los registros
  move $t6, $t3
  move $t3, $t1
  move $t1, $t6
  
  continuoIncrementoNumero:
  #fórmula para hallar la posición dada en la matriz (Ncolumnas*fila+columna) $t5*$t1+$t0
  mul $t7, $t5, $t3#hallo la posición final que dará la condición de salida del bucle
  add $t7, $t7, $t2
  
  bucleCruceBarcos:
   addi $s1, $s1, -1
   mul $t6, $t5,$t1
   add $t6, $t6, $t0
   
   add $t8, $t4, $t6 #obtengo la posición del puntero en la matriz
   lb $t9, ($t8) #obtengo el valor de la casilla
   #comparo valores
   beq $t9, 3, establecerSX #si es igual a tres, entonces ya hay un barco ahí
   beqz $s1, finBucleCruceBarcos
   beq $t7, $t6, errorTamano #si esa casilla ya era la última salgo del ciclo con error porque el barco es más grande
   #incremento el número de la fila
   addi $t1, $t1, 1
   j bucleCruceBarcos
   
  finBucleCruceBarcos:
   li $v0, 0
   #no hay errores, coloco el barco, asignando los mismos parámetros que la colocación correcta
   #las $ax ya están correctamente seteadas al no hacer ninguna llamada en este método
   addi $sp, $sp, -4
   sw $t4, ($sp) #matriz jugador
   addi $sp, $sp, -1
   sb $t5, ($sp) #columnas máximas
   addi $sp, $sp, -1
   sb $s0, ($sp) #tamaño del barco
   jal ponerBarco
   j establecerSX
   
  finColocacionCorrecta:
   #recupero el retorno de pila
   lw $ra, ($sp)
   addi $sp, $sp, 4
   jr $ra
   
  errorTamano:
   li $v0, 3
   j establecerSX
  
  establecerSX:
   lw $s1, ($sp)
   addi $sp, $sp, 4
   lw $s0, ($sp)
   addi $sp, $sp, 4
   j finColocacionCorrecta
   
   
#Coloca el barco en la matriz 
# Parámetros que recibe:
# $a0, letraInicio (valor ajustado)
# $a1, numeroInicio (valor ajustado)
# $a2, letra final (valor ajustado)
# $a3, numero final (valor ajustado)
# word en pila, puntero a la matriz del jugador donde se está colocando
# byte en pila, numero de columnas máximas
# byte en pila, tamaño del barco
ponerBarco:
 move $t0, $a0 #letra inicio
 move $t1, $a1 #numero inicio
 move $t2, $a2 #letra final
 move $t3, $a3 #letra final
 lb $t9, ($sp) #tamaño barco 
 addi $sp, $sp, 1
 lb $t5, ($sp) #columnas máximas
 addi $sp, $sp, 1
 lw $t4, ($sp) #matriz jugador
 addi $sp, $sp, 4
 
 #me faltan registros $tx, por lo que dejo este en $sx y guardo en pila el valor anterior
 addi $sp, $sp, -4
 sw $s0,($sp)
 move $s0, $t9 #en $s0 está el tamaño del barco
 
 li $t9, 3 #valor a guardar de barco puesto
 
 #fórmula para hallar la posición dada en la matriz (Ncolumnas*fila+columna) $t5*$t1+$t0
 mul $t7, $t5, $t3#hallo la posición final que dará la condición de salida del bucle
 add $t7, $t7, $t2
 
 beq $t0, $t2, incrementoNumero2 #están en la misma columna...
 beq $t1, $t3 incrementoColumna2 #están en la misma fila....
 
 incrementoColumna2: 
  bgt $t2, $t0, continuoIncrementoColumna2
  #intercambio los registros
  move $t6, $t2
  move $t2, $t0
  move $t0, $t6
  
  continuoIncrementoColumna2:
   addi $s0, $s0, -1
   mul $t6, $t5,$t1
   add $t6, $t6, $t0
   
   add $t8, $t4, $t6 #obtengo la posición del puntero en la matriz
   sb $t9, ($t8) #guardo el valor de la casilla
   beqz $s0, finBuclePonerBarcos2
   beq $t7, $t6, finBuclePonerBarcos2 #si esa casilla ya era la última salgo del ciclo sin errores
   #incremento el número de la columna
   addi $t0, $t0, 1
   j continuoIncrementoColumna2
 
 incrementoNumero2:
  bgt $t3, $t1, continuoIncrementoNumero2
  #intercambio los registros
  move $t6, $t3
  move $t3, $t1
  move $t1, $t6
  
  continuoIncrementoNumero2:
   addi $s0, $s0, -1
   mul $t6, $t5,$t1
   add $t6, $t6, $t0
   
   add $t8, $t4, $t6 #obtengo la posición del puntero en la matriz
   sb $t9, ($t8) #guardo el valor de la casilla
   beqz $s0, finBuclePonerBarcos2
   beq $t7, $t6, finBuclePonerBarcos2 #si esa casilla ya era la última salgo del ciclo sin errores
   #incremento el número de la fila
   addi $t1, $t1, 1
   j continuoIncrementoNumero2
   
  finBuclePonerBarcos2:
   lw $s0, ($sp)
   addi $sp, $sp, 4
   jr $ra


#recoje la letra y número, comprueba que esté dentro del rango y ajusta los valores para ser usados directamente a la matriz
# Parametros que recibe 
# $a0 letra
# $a1, numero
# $a2, Datos (puntero)
# $a3 limites (puntero)
# Devuelve:
# $v0: código de error
# 0 -> error de rango en letra
# 1 -> error de rango en número
# 2 -> correcto
# $v1: valor letra
# byte pila: valor numero
ajustesValoresCasilla:
 move $t0, $a0 #letra
 move $t1, $a1 #numero
 lb $t2, ($a2) #A
 lb $t3, 1($a2) #a
 lb $t4, ($a3) #limite columna
 lb $t5, 1($a3) #limite fila
 add $t6, $t2, $t4 #obtengo la letra máxima referente a las mayúsculas
 addi $t6, $t6, -1
 li $v0, 0 #inicializo el estado de la celda en error, lo guardo directamente a devolver
 
 #hago comprobaciones con la letra y ajusto el número
 bge $t0, $t3, rangoMinus #compruebo si x>=a
 bge $t0, $t2, rangoMayus #compruebo si x>=A
 j finAjustarCasilla
 rangoMayus: 
  bgt $t0, $t6, finAjustarCasilla #compruebo si X>letra máxima
  addi $t0, $t0, 32 #de mayuscula a minuscula
  addi $t0, $t0, -96 #lo paso a número
  li $v0, 1 #cambio el código de error
  j contenidoCasilla
   
 rangoMinus: 
  addi $t6, $t6, 32 #ajusto el límite para las letras pequeñas
  bgt $t0, $t6, finAjustarCasilla #compruebo si x>letra máxima
  addi $t0, $t0, -96 #lo paso a número
  li $v0, 1 #cambio el código de error
 
 contenidoCasilla: 
  #compruebo que el número no supere el máximo o mínimo
  blez $t1, finAjustarCasilla #supera maximo
  bgt $t1, $t5, finAjustarCasilla #supera minimo
  li $v0, 2 #cambio el código de error
  
  #resto ambos valores para ajustar a la matriz (que empieza en 0 y no en 1) y los devuelvo
  addi $v1, $t0, -1
  addi $t1, $t1, -1
  addi $sp, $sp, -1
  sb $t1, ($sp)
  
 finAjustarCasilla:
 jr $ra


# Comprueba la casilla en la matriz a ver si es agua, tocado, ya está dado... y devuelve el número correspondiente
# $a0 columna (letra)
# $a1 fila (numero)
# $a2 matriz
# $a3, datos
# word en pila, límites
# Devuelve un código de estado:
# 0 -> si error letra fuera de rango
# 1 -> si error, número fuera de rango
# 2 -> si agua
# 3 -> si tocado
# 4 -> casilla ya seleccionada
comprobarCasilla:
 lw $t0, ($sp) #limites
 #guardo los $sx que voy a usar y $ra
 sw $s0, ($sp)
 addi $sp, $sp, -4
 sw $s1, ($sp)
 addi $sp, $sp, -4
 sw $ra, ($sp)
 
 move $s0, $a2 #matriz
 move $s1, $t0 #limites
 

 #los parametros $a0 y $a1 ya están correctamente establecidos
 move $a2, $a3
 move $a3, $s1
 jal ajustesValoresCasilla
 
 beqz $v0, finComprobarCasilla
 beq $v0, 1, finComprobarCasilla
 
 #recojo los returns
 move $t0, $v1 #letra
 lb $t1, ($sp) #numero
 addi $sp, $sp, 1
 
 
 lb $t2, ($s1) #limite columna
 #fórmula para hallar la posición dada en la matriz (Ncolumnas*fila+columna) $t2*$t1+$t0
 mul $t3, $t2, $t1
 add $t3, $t3, $t0
 add $s0, $s0, $t3 #obtengo la posición del puntero en la matriz
 lb $t0, ($s0) #obtengo el valor de la casilla
 #comparo valores
 beqz $t0, cero #si es cero
 beq $t0, 3, tres #si es igual a tres
 #si es uno o dos, casilla ya usada, error
  li $v0, 4
  j finComprobarCasilla
 tres:
  li $t3, 2
  sb $t3, ($s0) #guardo un "tocado"
  li $v0, 3 #casilla libre y tocado
  j finComprobarCasilla
 cero:
  li $t3, 1
  sb $t3, ($s0) #guardo un disparado y agua
  li $v0, 2 #casilla libre/agua
   
 finComprobarCasilla:
  #reestablezco los $sx y $ra
  lw $ra, ($sp)
  addi $sp, $sp, 4
  lw $s1, ($sp)
  addi $sp, $sp, 4
  lw $s0, ($sp)
  addi $sp, $sp, 4
 
  jr $ra
 
 

#Dibuja el tablero con los barcos puestos del jugador y los disparos que le han hecho
#paso de parámetros:
# $a0 -> Tamaño matriz
# $a1 -> matriz del jugador 
inicializarMatricesCero:
 lb $t0, ($a0) #tamaño columna
 lb $t1, 1($a0) #tamaño fila
 move $t3, $a1
 move $t2, $t0 #contador columnas
 
 bucleInicializarFilas:
  beqz $t1, finBucleInicializarFilas #si acabé con las filas, acabé con la matriz
  addi $t1, $t1, -1 #decremento el contador
  bucleInicializarColumnas:
   beqz $t2, finBucleInicializarColumna #si acabé las columnas, fuera
   addi $t2, $t2, -1 #decremento el contador
   sb $zero, ($t3) #guardo un cero en la celda
   addi $t3, $t3, 1 #me situo en la siguiente columna, 
   #si es la última columna, se sitúa en la primera columna de la siguiente fila
   j bucleInicializarColumnas
  
  finBucleInicializarColumna:
  move $t2, $t0
  j bucleInicializarFilas
  
 finBucleInicializarFilas:
 jr $ra
 
#Dibuja el tablero
#paso de parámetros:
# $a0 -> Datos (guion bajo, 'A'...)
# $a1 -> Tamaño matriz
# $a2 -> matriz del jugador
# $a3 -> muestro los barcos o no (0 si no los muestro, 1 si los muestro)
#guardo y saco en pila todos los registros $sx que uso
dibujarTablero: #TODOS LOS REGISTROS $tx Y $sx USADOS!!!!menos t3
 #guardo en pila los registros
 addi $sp, $sp, -4
 sw $s0, ($sp)
 addi $sp, $sp, -4
 sw $s1, ($sp)
 addi $sp, $sp, -4
 sw $s2, ($sp)
 addi $sp, $sp, -4
 sw $s3, ($sp)
 addi $sp, $sp, -4
 sw $s4, ($sp)
 addi $sp, $sp, -4
 sw $s5, ($sp)
 addi $sp, $sp, -4
 sw $s6, ($sp)
 addi $sp, $sp, -4
 sw $s7, ($sp)
 
 #guardo en pila el retorno
 addi $sp, $sp, -4
 sw $ra, ($sp)

 lb $t4, 6($a0) #salto de linea
 lb $t6, 7($a0) #espacio
 lb $s0, 3($a0) #guion bajo
 lb $s1, 4($a0) #barra vertical
 lb $s2, 5($a0) #simbolo de agua (<<)
 lb $s3, ($a0) #A
 #si no muestro los barcos, la B se queda con el guión bajo
 move $t9, $s0 #guion bajo
 beqz $a3, continuoInicializando
 addi $t9, $s3, 1 #B (de barco)
 
 continuoInicializando:
 addi $s7, $s3, 23 #X de disparo dado
 move $s4, $a2 #matriz propia
 
 lb $s5, ($a1) #columnas
 lb $s6, 1($a1) #filas
 
 li $t0, 0 #contador columnas
 li $t1, 0 #contador filas
 
 
 li $t7, 2 #contador para la presentación del marco superior de la tabla
 move $t8, $s3 #caracter a imprimir A
 bucleInicio:#muestra el marco superior
  beq $t0, $s5, finBucleInicio
  move $a0, $t6 #muestro un espacio
  jal mostrarCaracter
  move $a0, $t8 #muestro el caracter a imprimir
  jal mostrarCaracter
  addi $t0, $t0, 1 #incremento contador
  beq $t8, $s0, bucleInicio #si el caracter a imprimir es el guion, no le sumo un uno (para la siguiente letra)
  addi $t8, $t8, 1
  j bucleInicio
 finBucleInicio:
 move $a0, $t4
 jal mostrarCaracter #muestro un salto de linea
 
 addi $t7, $t7, -1
 beqz $t7, bucleFilas
 #establezco una linea de guiones
 move $t8, $s0 #establezo el guión para la siguiente fila
 li $t0, 0 #reinicializo contador de columnas
 j bucleInicio
 
 bucleFilas: #por cada fila...
  beq $t1, $s6, finBucleFilas
  li $t0, 0 #contador columnas, reinicializo
  
  move $a0, $s1
  jal mostrarCaracter #mostramos la barra del marco izquierdo
  
  bucleColumnas: #por cada columna, mostramos el guion bajo o X o B según corresponda y la barra vertical derecha
   beq $t0, $s5, finColumnas
   
   lb $t2, ($s4) #obtengo de la matriz información sobre la celda
   addi $s4, $s4, 1 #actualizo el puntero para la siguiente celda
   
   move $a0, $s0 #presupongo guión bajo (valor de la celda=0)
   beqz $t2, mostrarCelda #si es igual a cero, directamente a mostrar la celda
   move $a0, $s2 #presupongo disparo y agua (celda=1)
   beq $t2, 1, mostrarCelda #si es agua, directamente a mostrar la celda
   move $a0, $t9 #presupongo B de barco (valor=3)
   beq $t2, 3, mostrarCelda #si es igual a 3, es barco y muestro celda
   move $a0, $s7 #si no es ninguna de las anteriores es un barco tocado
   
   mostrarCelda:
   jal mostrarCaracter #muestro el caracter que corresponde
   move $a0, $s1
   jal mostrarCaracter
   addi $t0, $t0, 1
   j bucleColumnas
  finColumnas:
  addi $t1, $t1, 1 #incremento contador filas
  #mostramos el número de fila precedido de un espacio
  move $a0, $t6
  jal mostrarCaracter
  move $a0, $t1
  jal mostrarNumero
  
  move $a0, $t4
  jal mostrarCaracter#muestro un salto de linea
  j bucleFilas
  
 finBucleFilas:
 move $a0, $t4
 jal mostrarCaracter #muestro un salto de linea
 #recupero el retorno
 lw $ra, ($sp)
 addi $sp, $sp, 4
 
 #recupero los registros
 #guardo en pila el retorno
 lw $s7, ($sp)
 addi $sp, $sp, 4
 lw $s6, ($sp)
 addi $sp, $sp, 4
 lw $s5, ($sp)
 addi $sp, $sp, 4
 lw $s4, ($sp)
 addi $sp, $sp, 4
 lw $s3, ($sp)
 addi $sp, $sp, 4
 lw $s2, ($sp)
 addi $sp, $sp, 4
 lw $s1, ($sp)
 addi $sp, $sp, 4
 lw $s0, ($sp)
 addi $sp, $sp, 4

 jr $ra

Etiquetas: ,,. Guarda el enlace permanente.

Deja un comentario ^^