Con la clase 
BufferedWriter se puede ir añadiendo líneas de texto a un fichero.
Hay que tener en cuenta que en este programa, estamos publicando líneas desde distintas clases, no solo desde la clase main.
Cuando un personaje ataca, lo que sale en pantalla se está publicando desde la clase 
PersonajeO si un mago usa el hechizo de sanación, esto se publica desde la clase 
MagoAsí que habría que añadir un objeto 
BufferedWriter a todas las clases.
Aunque, si somos 
un poco listos  
, en lugar de eso, lo que haremos será crear una nueva clase que incluya ese objeto 
BufferedWriter y un método estático que se encargue de escribir en fichero el mensaje String que le indiquemos.
Así podemos llamar a esta clase desde las otras, sin tener que ir una por una declarando y configurando un 
BufferedWriterEso si solo somos 
un poco listos, pero si resulta que 
somos muy listos  
, lo que además vamos hacer es que esta nueva clase, también se encargue de mostrar el mensaje en pantalla.
Porque si no, vamos a tener que estar repitiendo dos veces cada mensaje que queramos publicar, una para el fichero y otra para la pantalla.
Pues en lugar de eso, que esta nueva clase se encargue de publicar el mensaje en ambos sitios.
Así que en el resto de clases, ya no usaremos la instrucción System.out.println(), a no ser que se trate de algún mensaje destinado únicamente para pantalla.
Para los que queramos publicar en ambos medios, se los pasaremos a la nueva clase, que podemos llamar 
Publicadorimport java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Publicador {
	
	public static void publicar(String mensaje) {
		
		//Publicamos en pantalla
		System.out.println(mensaje);
		//Publicamos en fichero
		try {
			BufferedWriter escritor = new BufferedWriter(new FileWriter("d:/log/combate.txt", true));
			escritor.write(mensaje);
			escritor.newLine();
			escritor.close();
		} catch (IOException e) {
			System.err.println("No se pudo escribir en fichero");
		}
	}
}Importante escoger una ruta de archivo donde sepamos que no vamos a tener problemas de permisos de escritura y tal.
Ahora, en el resto de clases, vamos sustituyendo los system.out por llamadas al 
PublicadorPor ejemplo, en el método atacar() de 
Personaje, lo que antes publicábamos en pantalla:
   public int atacar() {
      System.out.println(nombre + " ataca.");
      Random azar = new Random();
      //Ataque mínimo: 1, Maximo: según nivel de ataque
      int puntosAtaque = azar.nextInt(ataque) + 1;
      
      //Damos un 10% de posibilidad de obtener un "Ataque Crítico"
      int valor = azar.nextInt(100);
      if (valor%10 == 0) { //Comprobamos si es multiplo de 10
         System.out.println("¡" + nombre + " consigue un Ataque Crítico!");
         //Un "Ataque Crítico" duplica el daño del ataque
         return puntosAtaque * 2;
      }
      else
         return puntosAtaque;
   }
Ahora lo hacemos con el 
Publicador en ambos soportes:
   public int atacar() {
      Publicador.publicar(nombre + " ataca.");
      Random azar = new Random();
      //Ataque mínimo: 1, Maximo: según nivel de ataque
      int puntosAtaque = azar.nextInt(ataque) + 1;
      
      //Damos un 10% de posibilidad de obtener un "Ataque Crítico"
      int valor = azar.nextInt(100);
      if (valor%10 == 0) { //Comprobamos si es multiplo de 10
         Publicador.publicar("¡" + nombre + " consigue un Ataque Crítico!");
         //Un "Ataque Crítico" duplica el daño del ataque
         return puntosAtaque * 2;
      }
      else
         return puntosAtaque;
   }
En las clases 
Personaje, Caballero y 
Mago, cambiaremos todos los system.out por el "publicador".
En la clase 
Combate, puede que no queramos sustituirlos todos.
Por ejemplo, los del método para crearPersonaje() donde nos sale un menú para elegir personaje, nombre, nivel de ataque, etc... pues eso no hace falta que salga reflejado en el fichero de texto.
Aunque eso ya va a gusto de cada uno.
Una cosa necesaria que sí vamos a tener que hacer en 
Combate es añadir un método para "preparar el fichero".
Más que prepararlo, en realidad lo que hará será comprobar si ya existe. Si existe, lo elimina y creará uno nuevo.
Esto es para que cada vez que ejecutemos el juego, el fichero se renueve y solo salgan los datos de la última partida.
	private static void prepararFichero() {
		File fichero = new File("d:/log/combate.txt");
		if (fichero.exists()) {
			fichero.delete();
			try {
				fichero.createNewFile();
			} catch (IOException e) {
				System.err.println("No se pudo crear fichero: " + "d:/log/combate.txt");
			}
		}
	}Y es al primer método que llamaremos en el main()
	public static void main(String[] args) {
		
		prepararFichero();
		
		crearPersonaje();
		
		elegirDificultad();
		
		//Comienza el combate...
		while(jugador.getVida() > 0 && CPU.getVida() > 0) {A no ser que quieras que se guarden TODAS las partidas.
En ese caso, se podría cambiar y hacer que por ejemplo se añada una línea con la fecha y hora actuales, para separar las líneas de cada partida.
En fin, si se ha hecho todo esto bien, podemos ver que ahora los mensajes de la terminal, quedan reflejados también en un fichero de texto

Y eso es todo, cualquier duda, solo hay que preguntar.
Un saludo