Java: Tres En Raya

Continuando con la senda del reciente post sobre el juego del ahorcado, esta vez vengo a compartir mi versión del tres en raya.
Está desarrollado sin muchas florituras a nivel de algoritmo; pero puede valer para repasar conceptos ya vistos.

La clase Tres En Raya
Al principio definiremos algunas cosas que vamos a necesitar. Nuestro tablero de juego no es más que un vector de 9 caracteres. Esas nueve casillas que representa pueden estar vacías (un espacio en blanco) o ocupadas por el carácter con el que juega el usuario (charUsuario=’x’) o la máquina (charMáquina=’o’). También aquí tenemos los contadores de victorias y derrotas.

Por otra parte, el método main es prácticamente calcado al visto en el juego del ahorcado. Simplemente muestra un menú y ejecuta las acciones pertinentes:

Por supuesto importaremos las clases necesarias para el Scanner y el tratamiento de excepciones.

El tablero
Para mostrar el tablero a lo largo del juego voy a desarrollar tres métodos. Al empezar una partida, quiero que se le muestre al jugador un tablero con los números de cada casilla (del 1 al 9), que son los números de casilla que introducirá por teclado para saber dónde quiere colocar sus fichas.
Después, ese tablero deberá estar vacío (introduciendo caracteres ‘ ‘) para poder empezar y se mostrará su estado paso a paso conforme se vayan realizando movimientos hasta terminar la partida.

No hay nada especial en estos tres métodos salvo convertir un número a un carácter mediante la concatenación de dos métodos: Integer.toString(numero).charAt(0). Prácticamente auto-explicativo.

Desarrollo
He tratado el desarrollo del juego en dos métodos para hacerlo más legible. Sigo un modelo Top-Down así que el primero que veremos es “jugar()”, que es el que se invoca desde la opción 1 del menú. Básicamente cuando el usuario escoge jugar, se le muestra el tablero numerado y se vacía.

Este método a su vez invoca a “partida()”, donde se desarrolla la partida, y que devuelve un char correspondiente a quien haya obtenido la victoria o en caso de empate. Aquí se actualizan los contadores si es el caso.
Ahora bien, para decidir quien empieza a colocar sus fichas he creado un método auxiliar “turnoInicial()” muy sencillo donde se sortea de forma más o menos aleatoria el turno. Requiere importar la clase Random.

Y ya estamos listos para comenzar la partida.
El bucle de jugadas se ejecutará mientras no haya un ganador y mientras el numero de fichas introducidas en el tablero sea menor que 10.
Primero mostramos el estado actual del tablero, preguntamos si aún no se han introducido todas las fichas posibles y según de quien sea el turno, introduciremos una ficha del jugador o de la máquina. En el caso de que sea turno del jugador, simplemente comprobamos que la posición indicada está vacía y le preguntamos de nuevo si no lo está. Si es el turno de la máquina, llamamos al método “ocuparCasilla()”, del que hablaré más tarde.
Una vez colocada la ficha, cambiamos el turno, comprobamos si hay un ganador con el método “victoria()” y aumentamos el contador de fichas ya introducidas.
Una vez que el bucle acabe, mostramos el estado final del tablero y devolvemos el char correspondiente al ganador (o un carácter vacío si ha sido empate).

Casillas y victorias
No hablo de estadísticas del Real Madrid ni de la Selección Española. ¿Como decide la máquina qué casillas ocupar para buscar la victoria? Hay varias formas sencillas de hacer esto pero me temo que ninguna satisfactoria. Buscando información en internet llegué al algoritmo minimax, pero no quería complicarme mucho para implementarlo.
De modo que la máquina hará una serie de comprobaciones para que parezca que juega de forma inteligente cuando en realidad no lo hace.
La primera y más evidente se trata de comprobar la casilla central (posición 4 del vector). Si está libre, la ocupa.
Si ya estaba ocupada por una ficha suya, la máquina tratará entonces de buscar las casillas 1, 3, 5 y 7 para formar la línea central vertical u horizontal. Si después de comprobarlas, no las ha podido ocupar, entonces buscará cualquiera de las restantes simplemente iterando a lo largo de todo el vector.
Si la posición central pertenece al jugador, no obstante, la máquina realiza un proceso análogo buscando jugar en los vértices del tablero, es decir, las posiciones 0, 2, 6 y 8, para formar una de las dos líneas diagonales.

No se trata, ni mucho menos, de una “inteligencia artificial”. Más bien se trata de un “primitivo artificio intelectual”.

Como después de introducir una ficha, hay que comprobar si tenemos un ganador, lo que he hecho es el método “victoria()”, que simplemente aglutina una serie de comprobaciones para verificar si existen tres fichas en raya en alguna de las verticales, horizontales u oblicuas.

De nuevo, es un mecanismo muy rudimentario, pero suficiente.

Jugando
Compilamos con:
$ javac TresEnRaya.java
Y ejecutamos con:
$ java TresEnRaya
Dejo a continuación tres capturas de como se comporta el programa así como del código completo. Si quieres descargarlo puedes hacerlo desde éste enlace y como siempre, los comentarios del blog están a vuestra disposición para cualquier duda o sugerencia 🙂



Java: El Ahorcado

Hace mucho que no pongo por aquí nada de programación en Java y hoy traigo el juego del ahorcado, que es un ejercicio propuesto en clase y que resulta bastante interesante.
Queremos desarrollar un programa que ejecute el juego del ahorcado. En cada partida presenta la palabra secreta escrita con “_” y se van revelando las letras que el usuario acierta. Se permite cometer hasta 5 fallos como máximo. Las letras que no formen parte de la palabra secreta cuentan como fallos; y si se introduce una letra correcta que ya había sido revelada con anterioridad, también. La partida solo termina si el usuario acierta la palabra o si se han cometido el número máximo de fallos.
Además, he introducido tres elementos extra:
– Un menú con tres opciones: jugar partida, ver estadísticas y salir. El programa se ejecuta hasta que el usuario selecciona la última opción.
– Las estadísticas de partidas ganadas y partidas perdidas.
– El programa cuenta con un conjunto de palabras para jugar. Se escogerán de forma aleatoria pero tratando de evitar que se produzcan repeticiones en la medida de lo posible.
Vamos allá!

El programa principal
Vamos a empezar creando la clase Ahorcado y dos variables que serán el numero de victorias y el de derrotas. En el método main() es donde creo el bucle que muestra el menú, lee la opción que introduce el usuario y la ejecuta.
Para leer texto por teclado estoy empleando la clase Scanner, que pertenece al paquete java.util y que he importado al principio. Es muy cómodo hacerlo de esta manera aunque existen otras, pero tengo a mi disposición el método Scanner.nextInt(), que me devuelve el primer número entero que el usuario teclea.
Hay la posibilidad de que el usuario introduzca algo que no sea un número, por lo que debo encerrar la lectura de la variable opción entre try-catch. No es mi forma favorita de manejar excepciones pero es un caso muy sencillo y se puede hacer aquí directamente. La excepción que debemos controlar es que los tipos no coincidan, o lo que es lo mismo, InputMismatchException, que también pertenece al paquete java.util y debo importar al principio.
Si el try-catch no detecta ninguna excepción, se lee el número que introduce el usuario. Si la detecta pone un número cualquiera, en mi caso el 100.
Es importante que una vez leída la opción (o controlada la excepción), vaciemos el resto del buffer de entrada, simplemente leyendo hasta el final de línea con el método input.nextLine();.

En la sentencia switch(opcion) es donde esa opción se transforma en realidad. Si el usuario ha introducido el número 1, arrancará el método partida(). Debo pasarle el objeto input de la clase Scanner para poder leer las letras que vaya introduciendo, y esperaré a que el método retorne FALSE si el usuario ha perdido o TRUE si ha adivinado la palabra. Dependiendo de ese valor, aumento un contador u otro.
La opción 2 simplemente muestra el valor de éstos y la 0 anuncia el final del programa. La opción default informa de que la opción introducida no es válida. Se llega a este punto tanto si el usuario mete un número incorrecto (p. ej el 5) o cualquier carácter que provoque la excepción que controlaba el try-catch, ya que la variable opción valdría 100.
Por último, cuando el programa termina, invocamos input.close() para cerrar el buffer de entrada.

Las palabras
Durante las partidas vamos a necesitar unas cuantas palabras con las que jugar. Yo he decidido almacenar unas cuantas en un array de Strings al que llamo vPalabrasSecretas. La variable maxIntentos, marcada como final para evitar que se cambie accidentalmente durante el juego, establece el numero máximo de intentos fallidos que tiene un jugador para adivinar la palabra secreta. Si se quiere hacer más fácil el juego, se aumenta este número y listo, no es preciso ningún otro cambio.


También tengo otro array de índices para controlar la repetición de las palabras. La idea es muy sencilla: el tamaño de vIndices es el mismo que el de Strings; si ya he jugado con una palabra, el valor del índice correlativo lo marco como TRUE. Si un índice tiene valor FALSE entonces es que la palabra correlativa en vPalabrasSecretas aun no ha sido seleccionada para jugar.
Por ejemplo: Si juego con la palabra vPalabrasSecretas[0] (“cámara”), pongo TRUE en vIndices[0]. Si después, juego con la palabra “terminal” (que está en la posición 9), pongo vIndices[9] a TRUE.
¿Podría esto resolverse con un único array bidimensional? Sí, perfectamente; pero lo he hecho así para no enrevesarlo mucho. Si se quiere apostar por esa solución, no se requieren grandes cambios.

Con esto definido, voy a crear un método que devuelva una palabra secreta nueva y si es posible con la que no se haya jugado hasta el momento. La forma de hacerlo es calcular el módulo de partidas ya jugadas entre el número de palabras disponibles para jugar. Cuando el juego empieza (0 % vPalabrasSecretas.length = 0) o cuando ya se ha jugado con todas, pondremos todos los valores de vPalabrasJugadas a FALSE.
Después, se pide un numero entero aleatorio (Random().nextInt()) que va de 0 hasta el número de palabras que hay en el vector. Esto se repite todas las veces que sea necesario mientras el índice correspondiente sea TRUE (es decir, mientras las palabras en ese índice ya hayan salido) hasta que encuentre un índice que vale FALSE (una palabra con la que aún no se ha jugado). Cuando hemos encontrado ese índice, se sale del bucle. Lo marcamos como TRUE y devolvemos la palabra en esa posición.

La clase Random debe ser importada, también forma parte del paquete java.util.

Otras operaciones
Dentro del método partida hay dos secuencias de instrucciones que, sin ser complejas, nos conviene programar en métodos aparte. Así facilitamos la limpieza y la comprensión del código del método partida() cuando lleguemos a él.
La primera operación, por obvia, es leerLetra(). Debe recibir el input en los parámetros parámetros de la llamada y devolver un único carácter. Por supuesto, controlaremos las excepciones correspondientes, tal y como hicimos al leer las opciones del menú principal.


Como la clase Scanner no proporciona un método para leer el primer carácter, lo que hacemos es leer toda una línea (nextLine()), convertirla a minúsculas (toLowerCase()), y de ahí tomar el carácter en la posición 0 (charAt());
En la clase Character tenemos un método llamado isLetter() que comprueba si un carácter dado es una letra, y no terminaremos el bucle de pedir letras mientras no obtengamos una.

El siguiente método que he escrito es el que mostrarEstadoPartida(). Básicamente lo que hace es escribir en pantalla tantos “_” como caracteres componen la palabra secreta, o la letra si ésta ya ha sido revelada por el jugador.
A continuación, escribe las letras que no forman parte de la palabra o las que ya se revelaron previamente, porque contarán como fallos, y tantos “_” como intentos restantes de los que disponga.
Tanto la palabra como las letras son arrays de char, lo que nos evita tener que andar construyendo nuevas cadenas a partir de subcadenas en cada sustitución.

La partida
Y finalmente, vamos al método partida(), que es el que desarrolla el juego. Para empezar, debo recordar que devuelve TRUE si el usuario gana la partida y FALSE si pierde. Podría hacerlo también como int porque hay juegos donde existe la posibilidad de empate, o por si quiero programar que el jugador pueda abandonar una partida sin que se contabilice como victoria o derrota.
El método debe recibir el argumento Scanner desde main(), para poder pasárselo a su vez al método leerLetra().


He estructurado el método en cuatro bloques que son:
1. Preparación de las variables
Solicito la palabra secreta al método nuevaPalabra(), creo un array de char palabra[] con la misma longitud para almacenar la letras que el jugador acierta y otro con el tamaño maxIntentos para las letras falladas vLetras[].
2. Muestro el estado de la partida y los intentos restantes, y leo una letra. Si esa letra forma parte de palabraSecreta y no de palabra[] entonces la revelo.
3. Siempre que se haya acertado una letra, se compara palabraSecreta con palabra[] (podemos convertir el contenido del array a String con el método String.copyValueOf()). Si son iguales, la palabra ha sido revelada y ponemos fin a TRUE.
Si no se ha acertado la letra, la apuntamos en vLetras y aumentamos el contador de fallos.
4. El último bloque verifica si la partida ha terminado porque la variable fin era TRUE, lo que significaría una victoria. Si hemos llegado hasta ahí y todavía vale false, es una derrota. Mostramos los mensajes adecuados y devolvemos el valor de fin.

Compilación y ejecución

El código completo
Y nada más 🙂 Espero que os haya servido para divertiros un poco programando en Java. Podéis descargaros el código fuente desde aquí y si queréis sugerir algún cambio, por favor indicádmelo en los comentarios.

Actualizar MacBook 2,1 a OS X Mavericks


Hoy he conseguido actualizar el MacBook (mid 2007) a OS X Mavericks 10.9.5 con éxito y más o menos el equipo es plenamente funcional con un par de ajustes extra. Es posible hacerlo por varios métodos pero el único con el que he obtenido resultados es con SFOTT, que además es un método muy transparente y al mismo tiempo fácil de seguir.

Consideraciones
Hasta 2006 los Macs basados en procesadores PowerPC e Intel (32 bits) disponían de un EFI, un Kernel y unos controladores de 32 bits.
Con la llegada de los Core 2 Duo de 64-bits se iniciaba una transición: se podían correr aplicaciones de 64 bits con el Kernel y los controladores de 32 bits mediante tecnologías de traducción de llamadas y direcciones.
Y por otro lado, si el hardware disponía de controladores de 64 bits, se podía ejecutar un Kernel del mismo tipo de forma que las aplicaciones de 64 bits ya no necesitaban esas tecnologías extra y sus llamadas al sistema se podían realizar de forma nativa y transparente. El arranque EFI no obstante, seguía siendo un sistema de 32 bits.

En 2008 Apple introdujo nuevos ordenadores con sistemas de arranque EFI de 64 bits manteniendo la compatibilidad de Mac OS X con los EFI de 32 bits para los ordenadores anteriores, aunque se cargase un Kernel y drivers de 64 bits según el tipo de procesador de la máquina.
Y finalmente en 2012 se culminaba la transición con la publicación de Mountain Lion, descartando el soporte a EFI, Kernel y drivers de 32 bits.
Por eso los Macs anteriores a 2008 cuya EFI era de 32 bits (como mi MacBook) no pudieron actualizarse más allá de Lion.

Podemos saltarnos esta restricción si intervenimos el sistema, cargamos un EFI de 32 bits e instalamos controladores para el hardware obsoleto, si disponemos de ellos.
Por desgracia para mi MacBook, oficialmente no hay drivers de 64 bits para su tarjeta gráfica integrada, una Intel GMA 950. Si conseguimos actualizar, el rendimiento gráfico será bastante pobre, pero se han podido rescatar unos controladores Beta de 64 bits que existieron en su momento en una Developer Preview de Snow Leopard; e instalarlos es mejor que nada. Hay otras cosas que no funcionan:

  • El brillo de pantalla no se puede ajustar ni mediante las teclas de función ni desde las preferencias del sistema
  • El ordenador no es capaz de despertar del estado de reposo
  • La retroiluminación de la pantalla no se apaga cuando conectas un monitor externo (por DisplayPort) y cierras la tapa del portátil
  • La cámara iSight va muchísimo peor que en OS X 10.7.5, así que no la considero funcional

Vamos a necesitar:

  • El Mac que queremos actualizar
  • El archivo “Install OS X Mavericks.app”
  • Descargar SFOTT desde aquí
  • Descargar estos Ketxs desde aquí

“Install OS X Mavericks.app” es el instalador que te puedes descargar de la Mac App Store y debe estar en la carpeta /Aplicaciones. Si no lo tienes en tu pestaña de aplicaciones compradas de la tienda (porque en su momento no lo adquiriste), deberás localizarlo por otros medios.
Las versiones de Mavericks lanzadas por Apple van desde la 10.9.0 hasta la 10.9.5. Si tienes el instalador de esta última, perfecto. Si no es así y quieres actualizar a posteriori, ojo porque tendrás que reparchear el sistema.

Procedimiento
Usaremos SFOTT para crear un disco de instalación y cambiar su Bootloader EFI por uno que permita instalar el SO en un ordenador oficialmente no soportado. Una vez que lo tengamos corriendo, podremos instalar los drivers. No te preocupes si no tienes un pendrive a mano: haré el proceso utilizando una partición del disco duro y la borraré una vez que ya no la necesite.
Desde la Utilidad de discos del Mac, prepararemos el equipo. Como yo quiero conservar OS X Lion por si surgen problemas he reducido el tamaño de su partición y he añadido dos particiones con formato MacOS Plus (con registro): una de 40 GB para Mavericks y otra de 8 GB para el instalador (“SETUP”).

Instalamos SFOTT y lo ejecutamos. Nos pedirá la contraseña de nuestro usuario (que debe tener permisos de administrador) y se abrirá en el terminal. Voy a enumerar brevemente los pasos que hay que hacer, pero puedes verlos en varias capturas aquí y también en este video.
Primero debemos escoger idioma y aceptar las condiciones antes de llegar al menú principal.
Allí selecciona la opción 3) Settings
En el submenú que se muestra debes seleccionar:

  • 2) Choose USB/media for the sfott key
    La partición o disco donde crear el instalador parcheado, en mi caso la partición “Setup” de 8 GB
  • 3) Select the computer to use
    Si estás haciendo esto en el propio Mac que quieras actualizar, simplemente selecciona la opción 1) Choose current computer
    En caso contrario necesitas conocer el modelo exacto y el ID de placa del ordenador en cuestión
  • 4) Select OS X System Version
    Obviamente seleccionamos Mavericks si esa es la versión que vamos a parchear
  • 5) Select OS X Installer
    Al haber copiado el archivo “Install OS X Mavericks.app” en tu carpeta de aplicaciones, bastará con seleccionar la primera opción para que el script localice el instalador de forma automática. También hay una opción que acepta Drag&Drop por si te resulta más cómodo teniéndolo en otra ubicación.

Ahora volvemos al menú principal (1). Seleccionamos la opción 4) Create / Patch SFOTT Key y a continuación la 2) Create a New key in Autorun
Confirmaremos los siguientes pasos hasta terminar el proceso.
Es el momento de reiniciar el Mac mientras pulsamos la tecla Opción (alt) para arrancar desde la partición Setup, que ha sido renombrada a SFOTT. Realiza la instalación del sistema operativo y acuérdate de seleccionar que se instale en la partición que quieras, en mi caso la que creé antes de 40 GB de espacio.
Si todo ha ido bien, tu sistema se reiniciará para que termines de configurar el sistema y llegarás a tu flamante nuevo escritorio.

Actualizaciones menores
Si te encuentras en la versión 10.9.5 del sistema, enhorabuena, ya has terminado. Puedes ponerte a instalar los controladores, actualizar las aplicaciones a través del App Store y añadir los programas que quieras a tu ordenador.
Sin embargo, en mi caso solo pude encontrar un instalador apropiado para la versión 10.9.1; y se sabe que en la 10.9.2 Apple modificaba el cargador de arranque EFI, por lo que me tocará re-parchear el sistema. El proceso no es complicado, pero tampoco es que esté fantásticamente documentado, así que…
Abre la Mac App Store y haz clic en la pestaña de actualizaciones. Ha pasado tanto tiempo que podemos decir con toda seguridad que te aparecerá la actualización a la versión 10.9.5 como la última disponible para Mavericks. También puede que aparezcan otras actualizaciones (iTunes, Remote Desktop, etc.). En cuanto se haya descargado la actualización del sistema operativo, el ordenador te pedirá que lo reinicies para completar el proceso.
Reinicié y me encontré con que el ordenador había vuelto a arrancar con la partición de OS X Lion. Lo que hay que hacer es apagar, volver a encender pulsando la tecla Opción (alt) y volver a cargar la partición (o disco) SFOTT, con la que instalamos el SO.
Una vez cargue y vuelvas a ver la pantalla de bienvenida de la instalación, haz clic en el menú Utilidades y abre una ventana de Terminal.
En primer lugar recuperaremos el permiso de escritura ejecutando:
$ sfott
Y a continuación ejecutamos SFOTT:
$ /Applications/Utilities/Scripts/SFOTT.sh
El proceso es similar a la creación del instalador. Escogemos idioma, aceptamos los términos de uso y ya estamos de vuelta en el menú principal. Accedemos a la opción 3) Settings y esta vez establecemos:

  • 3) Select the computer to add
    Al tratarse del propio ordenador, escogemos 1) Choose Current Computer
  • 4) Select OS X System Version
    Seleccionamos 1) OS X Mavericks
  • 9) Choose Target System to re-Patch
    Aquí escogemos la partición donde tenemos instalado Mavericks ya actualizado

Volvemos al menú principal (1) y escogemos la opción 6) Re-Patch Existing System y confirmamos los pasos restantes. Por último, el propio script de SFOTT nos ofrecerá reiniciar el equipo. Aceptamos y en el reinicio mantenemos pulsado de nuevo la tecla Opción (alt) para asegurarnos de que seleccionamos arrancar con la partición donde tenemos instalado el SO con la última actualización. Bingo!

Bug de Spotlight
En determinados casos (generalmente después de aplicar alguna actualización) un bug impedirá que Spotlight indexe el disco correctamente, pero lo puedes solucionar de una forma muy sencilla. En el Finder, dirígete a tu carpeta de Aplicaciones/Utilidades y abre una terminal. Hay un archivo oculto en el disco evitando el funcionamiento del buscador que debes borrar con permisos de administrador, así que:
$ sudo rm -f /.metadata_never_index
Y a continuación reiniciamos el indexado:
$ sudo mdutil -i on /

Bug de AirDrop
En algunos modelos tampoco podrás utilizar AirDrop. Podemos reactivarlo con dos comandos sencillos:
$ defaults write com.apple.NetworkBrowser BrowseAllInterfaces 1
$ defaults write com.apple.NetworkBrowser DisableAirDrop -boolean NO
$ killall Finder

Bug de IPv6
Cuando compré el equipo, su anterior propietario me comentó que el ordenador ya no funcionaba, que se conectaba a internet y se congelaba. Supuse que se trataría de algún problema de software o en el peor de los casos de que la tarjeta AirPort se habría estropeado, así que decidí apostar por la compra igualmente y tratar de solucionar el error. Sucedió como ya comenté en aquel post que simplemente OS X Leopard se negaba a seguir funcionando una vez se negociaba una conexión inalámbrica si el protocolo IPv6 estaba habilitado en el equipo, y una vez deshabilitado todo volvía a funcionar con normalidad.
No he vuelto a ver este problema, así que supongo que es algo propio de OS X 10.6.x; pero en fin, que si te lo encuentras, simplemente arranca el equipo con el router WiFi apagado o fuera del alcance de tu red, abre las Preferencias de Sistema, en el apartado de red selecciona la conexión Wi-Fi y haz clic en “Avanzado”. En la pestaña TCP/IP, cambia el modo IPv6 a “Solo enlace local” y listo.

Audio y video
Además verás que no tienes audio y que el rendimiento gráfico es pésimo. Descomprime el archivo de los drivers. Encontrarás una utilidad llamada “Kext Utility.app” y el sistema pedirá tu contraseña para continuar.

También encontrarás la carpeta “Extensiones” con varios archivos kext en su interior. Arrástralos a la ventana de Kext Utility para que los procese y los instale. Son los drivers de audio y video para el MacBook 2,1 (mid 2007), pero necesitarás los correspondientes a tu modelo de ordenador si es diferente. Cuando la aplicación termine, basta con reiniciar el equipo.

Rendimiento en Mac OS X 10.9.5
Mavericks fue una versión que se centró mucho en mejorar el rendimiento de los Mac y la duración de la batería. Lástima que no tengamos el soporte para poner el ordenador a dormir porque en este sentido hubiese ganado un montón de autonomía.
Inevitablemente una máquina así tiene unas capacidades muy limitadas hoy en día: reproducir video en resolución 720p desde Youtube no es imposible, pero supone un esfuerzo; la mayoría de páginas web se toman unos segundos más de la cuenta para cargar, debido a la ingente cantidad de datos y procesos que llevan por debajo; los juegos… bueno, un mac nunca ha sido una máquina idónea para jugar, etc etc.
Sin embargo, merece la pena dedicarle algo de cariño para devolverle mucha vida a un equipo con trece años de antigüedad y poder seguir sacándole provecho para tareas ofimáticas, responder a tus emails, navegación ligera, bloguear, escuchar música (local o en streaming), etc.
Para mi caso, incluso es factible seguir empleando Logic Pro X (en una versión con un par de años a sus espaldas) y aprovechar mucho más la interfaz de audio M-Audio Fast Track Ultra 8R que dejó de ser compatible a partir de macOS Sierra 10.12.

Mac OS X 10.10 Yosemite
He visto a varios usuarios que han conseguido llevar el MacBook 2,1 (mid 2007) un poco más allá e instalar la siguiente versión también mediante este procedimiento. Lo cierto es que se puede, pero en mi caso no quería “forzar la máquina” y decidí quedarme en Mavericks.

Windows 7
En una partición Boot Camp con Windows, también es una máquina bastante capaz pues dispones de drivers apropiados y puedes instalar versiones actuales de tu navegador favorito, Office 365, etc. Reproducir video en 720p desde Youtube sigue siendo un esfuerzo pero parece más asequible para las posibilidades del MacBook, y en general el desempeño del SO es un poco más fluido.
También puedes controlar el brillo de la pantalla, poner el ordenador en suspensión o hibernación sin problemas, conectar y utilizar monitores externos…
Incluso he podido ejecutar juegos antiguos, por ejemplo: Max Payne 2 (2003), Grand Theft Auto Vice City (2002), Portal (2007), etc. El rendimiento no es para echar cohetes, pero puede mover estos títulos y ofrecer un grado de detalle muy razonable.

Conclusión
En definitiva, creo que si eres usuario de OS X y tienes este equipo, merece mucho la pena tomarse la molestia de actualizar el sistema operativo pues podrás aprovechar aún más tu ordenador. Desde luego podríamos decir que estaban hechos de otra pasta (badum tss) y su longevidad no deja de asombrarme.
Si las aplicaciones de tu día a día no te atan a OS X, incluso te recomendaría instalar Windows 7 y, a continuación, actualizarte a Windows 10 porque así conseguirás compatibilidad con software moderno y actualizaciones de seguridad.
Me queda pendiente para otra ocasión probar Ubuntu 20.04, que acaba de ser publicado y me imagino que podrá correr en esta máquina, abriendo las puertas a las ventajas de GNU/Linux.

Referencias

Importar notas de voz antiguas en MacOS e iOS

Cuando actualicé a MacOS 10.14 (Mojave) me pareció genial que por fin Apple permitiese almacenar las notas de voz del iPhone (o para el caso del iPad) en iCloud y mantenerlas así sincronizadas con la recién estrenada aplicación para MacOS. Bueno, me pareció genial y que había tardado siglos en implementarse.

Hasta ese momento, todo pasaba por conectar el iPhone al Mac y hacer la sincronización con iTunes, pero los resultados eran desastrosos: notas que se duplicaban, nefasta catalogación mediante etiquetas, etc.
Y aunque nada de esto ha cambiado, sí he encontrado una forma de recuperar todas las notas de voz antiguas que tenía almacenadas en una carpeta (cerca de 100), transferirlas al iPhone e importarlas en la aplicación Notas de Voz.
De esta forma, puedo tenerlas ordenadas cronológicamente, además de poder cambiarles los títulos, editarlas y que se sigan manteniendo sincronizadas en todos los dispositivos. Te cuento cómo.

Vamos a crear una carpeta en la que tener todos los archivos de notas de voz en formato m4a. Ojo, si vienes de otro formato, necesitarás convertirlo a audio AAC. Cualquier bitrate está bien, aunque una nota de voz propia del iPhone se graba en estéreo, tasa de bits variable (en torno a 64 kbps) y 48 Khz de frecuencia de muestreo. Puedes utilizar una tasa superior sin problemas.
Por supuesto, voy a aprovechar que las notas de voz que tenía almacenadas vienen nombradas por fecha y hora siguiendo el esquema:
YYYYMMDD hhmmss.m4a
Donde:
YYYY = año, MM = mes, DD = dia, hh = hora (en formato 24h), mm = minutos; y ss = segundos

Lo mejor será acceder a la carpeta en una terminal y mantenerla abierta también en el Finder en vista de listado. Hagamos esta prueba a mano. El comando touch nos permite modificar las fechas de modificación de un archivo bajo el siguiente formato:
$ touch -mt YYYYMMDDhhmm.ss nombre_del_fichero
Aunque no es obligatorio especificar los segundos, los aprovecharé también ya que a veces he creado varias notas de voz en menos de un minuto y quiero mantenerlas en un estricto orden cronológico. Los segundos deben ir separados por un punto.
Tras hacer varias pruebas, la vista del Finder (ordenando por fecha de modificación) nos permite corroborar que el comando está haciendo bien su trabajo, o también la ventana de información del fichero (Cmd+i).

Ahora que tenemos la carpeta con las notas de voz bien ordenadas según su fecha original (tanto por el nombre de fichero como por las fechas de sus metadatos), movemos la carpeta a alguna ubicación accesible desde iCloud, por ejemplo el escritorio, y pasamos al iPhone.
Desde el teléfono, vamos a esa carpeta y abrimos uno por uno cada archivo, tocamos en la opción de compartir y ahí nos saldrá la aplicación Notas de voz. Si la seleccionamos, el iPhone importará el audio y desde ese momento se sincronizará a través de iCloud dentro de la app con el resto de dispositivos, permitiéndonos alterar su título si así lo queremos pero conservando su fecha original y un orden cronológico.
 

Algo que sería ahora de enorme utilidad es desarrollar un script para poder procesar un lote de ficheros mayor y, al menos, ahorrar tiempo en el terminal; ya que en la parte del iPhone las posibilidades de automatización son menores. ¿Alguien se anima?

MacOS: Desinstalar Developer Tools


Hay algunos comandos que a veces echo en falta en MacOS. No porque no existan sino porque no vienen instalados por defecto en el sistema.
Un caso claro es el uso de Makefiles o de un compilador como gcc (en realidad Clang), que no es posible sin las Command Line Developer Tools. La propia terminal te sugiere instalarlas a través de un cuadro de diálogo pero no basta porque para otras cosas necesitarás definitivamente instalarte Xcode.
Como por lo general no me gusta tener instalado en el sistema nada más que lo imprescindible y soy muy celoso del espacio libre en mi SSD, quise instalar las Developer Tools y Xcode para hacer un build de una App, y desinstalarlos a continuación.
Para instalar, basta con aceptar el cuadro de diálogo que te sugiere la terminal o, si necesitas toda la suite Xcode, instalar el IDE desde la Mac App Store.

Para desinstalar todo puedes hacer una de estas dos cosas:
– Si has instalado Xcode, desinstálalo por completo, por ejemplo a través de AppCleaner o de CleanMyMac X
– Si sólo has instalado las Command Line Developer Tools abre un terminal y borra el directorio donde se almacenan:
    $ sudo rm -rf /Library/Developer/CommandLineTools
    y resetea los PATH del sistema con:
    $ sudo xcode-select -r
Así podremos devolver nuestro equipo a su estado anterior.