Ejercicio clases Dungeons & Dragons

Vamos a hacer una especie de juego antiguo de dragones y mazmorras. Tendremos un tablero y en medio estará nuestro héroe. Puede moverse en todas las direcciones y en principio no sabe lo que se va a encontrar. Hay tesoros (que sirven para incrementar nuestra potencia) y monstruos (con los que peleamos). Si derrotamos a todos los monstruos hemos ganado.

Antes de empezar nos pedirá el tamaño del tablero (ancho y alto) aunque tendremos valores por defecto. También el número de monstruos y de tesoros. Se crea el tablero se coloca al héroe y se piden movimientos hasta que el usuario escriba ‘FIN’, se derroten a todos los monstruos o nos muramos.

Cada vez que proporcionamos un movimiento (U,D,L,R) movemos al héroe a esa posición. Las posiciones que no se han visitado se muestran con asterisco, las visitadas se dejan en blanco.

Cuando el héroe encuentra un tesoro se le da el mensaje, las monedas que ha ganado y cuanto se ha incrementado la potencia. Se le pide que pulse una tecla para continuar.

Cuando el héroe encuentra un monstruo se le avisa, se calcula quien ha ganado (un porcentaje respecto a la potencia) y pueden pasar dos cosas:
1.- Gana el héroe: se incrementa su potencia
2.- Pierde el héroe: Se acaba el juego y se le pregunta si quiere volver a empezar.

Esto sería lo básico. Posibles mejoras:

1.- Poción de vida. Si el usuario las encuentra y lo mata un monstruo puede seguir la partida.
2.- Poción de visión: Si el usuario la usa cuando le toca su movimiento puede ver lo que tiene a su alrededor.
3.- Modificar el enfrentamiento para que sea por turnos y que reste ‘vida’ dependiendo de la potencia. Esto nos permitiría tener monstruos con más personalidad (mucha vida pero poca potencia, poca vida pero mucha potencia)
4.- Que las monedas no te den automáticamente potencia, sino que te permitan comprar más vida o más potencia (u otras cosas que se nos puedan ocurrir)
5.- Modo automático: el héroe se mueve a través del tablero aleatoriamente y nos va mostrando los mensajes sin que tengamos que intervenir.
6.- Mundo infinito: Poner puertas en los lados del tablero que nos permitan ir a otras habitaciones que se irán generando.

Ejercicios Java

Escribir una función que invierta el orden de los caracteres de una cadena dada.

Escribir una función que cuente el número de veces que se repite un carácter específico en una cadena dada.

Escribir una función que elimine los espacios en blanco al principio y al final de una cadena dada.

Escribir una función que compruebe si una cadena es un palíndromo (una palabra o frase que se lee igual de izquierda a derecha y de derecha a izquierda).

Escribir una función que elimine todas las ocurrencias de una subcadena específica de una cadena dada.

Escribir una función que reemplace todas las ocurrencias de un carácter específico en una cadena dada con otro carácter.

https://github.com/juanpfuentes/Java/blob/main/src/java/strings.md

Mini ejercicio react

Descargar el código de la cesta de la compra:

https://github.com/PacktPublishing/React—The-Complete-Guide-includes-Hooks-React-Router-and-Redux-Second-Edition/tree/main/Section%2011/code/12-finished

Y añadimos las siguientes mejoras:

1.- Botón en la cesta para eliminar completamente un producto
2.- Si la compra es superior a 1000 que se muestre un aviso de que se puede pagar en tres plazos
3.- Poder filtrar las carnes por el nombre.

Truco para eliminar listeners de funciones flechas

Básicamente cambiar el prototype para que internamente guarde un Symbol (id única) y nos permita eliminarlas:

(function()
{
    let target = EventTarget.prototype;
    let functionName = 'addEventListener';
    let func = target[functionName];

    let symbolHidden = Symbol('hidden');

    function hidden(instance)
    {
        if(instance[symbolHidden] === undefined)
        {
            let area = {};
            instance[symbolHidden] = area;
            return area;
        }

        return instance[symbolHidden];
    }

    function listenersFrom(instance)
    {
        let area = hidden(instance);
        if(!area.listeners) { area.listeners = []; }
        return area.listeners;
    }

    target[functionName] = function(type, listener)
    {
        let listeners = listenersFrom(this);

        listeners.push({ type, listener });

        func.apply(this, [type, listener]);
    };

    target['removeEventListeners'] = function(targetType)
    {
        let self = this;

        let listeners = listenersFrom(this);
        let removed = [];

        listeners.forEach(item =>
        {
            let type = item.type;
            let listener = item.listener;

            if(type == targetType)
            {
                self.removeEventListener(type, listener);
            }
        });
    };
})();

document.addEventListener("DOMContentLoaded", event => { console.log('event 1'); });
document.addEventListener("DOMContentLoaded", event => { console.log('event 2'); });
document.addEventListener("click", event => { console.log('click event'); });

document.dispatchEvent(new Event('DOMContentLoaded'));
document.removeEventListeners('DOMContentLoaded');
document.dispatchEvent(new Event('DOMContentLoaded'));

Ejercicio useReducer

Vamos a crear un formulario con dos inputs de type number y cuatro botones para sumar, restar, dividir y multiplicar. El resultado se mostrará en un div.

Para la lógica usaremos useReducer

React router

En una aplicación de React, el enrutamiento es la habilidad de mostrar diferentes componentes según la URL actual. Puedes usar una librería de enrutamiento como React Router para manejar el enrutamiento en tu aplicación de React.

Para usar React Router, primero debes instalarlo mediante npm o yarn:

npm install react-router-dom

Una vez que hayas instalado React Router, puedes importar los componentes BrowserRouter, Route y Link y usarlos en tu aplicación.

BrowserRouter es un componente que proporciona un contexto de enrutamiento para tu aplicación. Debe ser el componente padre de todos los componentes de enrutamiento.

import { BrowserRouter } from 'react-router-dom';

Route es un componente que se usa para definir una ruta. Cada Route tiene un atributo path que indica qué URL debe mostrar el componente correspondiente.

import { Route } from 'react-router-dom';

Link es un componente que se utiliza para crear enlaces entre diferentes rutas de tu aplicación. A diferencia de los enlaces tradicionales , los enlaces de React Router no recargan la página completa cuando se hacen clic.

import { Link } from 'react-router-dom';

Aquí hay un ejemplo de cómo utilizar estos componentes para configurar el enrutamiento en una aplicación de React:

import React from 'react';
import { BrowserRouter, Route, Link } from 'react-router-dom';

import Home from './Home';
import About from './About';
import Contact from './Contact';

function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/about">About</Link>
        <Link to="/contact">Contact</Link>
      </nav>
      <Route path="/" exact component={Home} />
      <Route path="/about" component={About} />
      <Route path="/contact" component={Contact} />
    </BrowserRouter>
  );
}

export default App;

En este ejemplo se tiene un componente principal App que envuelve toda la aplicación en un BrowserRouter componente. Dentro de éste se tiene un navegador con tres links, cada uno apuntando a una ruta diferente, el componente Route se usa para definir las rutas y se le especifica que componente se tiene que cargar.

https://www.w3schools.com/react/react_router.asp
https://pablomonteserin.com/curso/react/react-router/
https://guias.makeitreal.camp/react/react-router

React useMemo y useCallback

useMemo es una función de React Hooks que te permite memorizar el resultado de un cálculo y evitar recalcularlo si los argumentos no han cambiado. Esto es útil para mejorar el rendimiento de tu aplicación, especialmente en casos en los que un cálculo puede ser costoso o el componente depende de un gran número de valores.

La función useMemo toma dos argumentos: la primera es una función que realiza el cálculo y la segunda es una matriz de dependencias. La función se ejecutará sólo si alguna de las dependencias ha cambiado desde la última vez que se ejecutó.

Aquí hay un ejemplo de un componente de React que utiliza useMemo para mejorar el rendimiento de una función que devuelve una lista de números primos:

import { useMemo } from 'react';

function isPrime(num) {
  for (let i = 2; i < num; i++) {
    if (num % i === 0) {
      return false;
    }
  }
  return num !== 1;
}

function getPrimes(count) {
  const primes = [];
  for (let i = 2; primes.length < count; i++) {
    if (isPrime(i)) {
      primes.push(i);
    }
  }
  return primes;
}

function PrimeList({ count }) {
  const primes = useMemo(() => getPrimes(count), [count]);
  return (
    <ul>
      {primes.map((prime) => (
        <li key={prime}>{prime}</li>
      ))}
    </ul>
  );
}

En este ejemplo, el componente PrimeList recibe una propiedad count y utiliza useMemo para memorizar el resultado de la función getPrimes(count). Esto significa que si count no ha cambiado, getPrimes no será llamada de nuevo y se devolverá el resultado memorizado.

useMemo es útil cuando se tiene un componente que realiza un gran número de cálculos costosos para actualizar un estado o una propiedad cada vez que se renderiza. Esto ayuda a mejorar el rendimiento de la aplicación al evitar hacer cálculos innecesarios.

useCallback es una función de React Hooks que es similar a useMemo, pero en lugar de memorizar el resultado de un cálculo, memoriza una función. La función devuelta por useCallback siempre será la misma mientras sus dependencias no cambien. Esto es útil para mejorar el rendimiento de tu aplicación cuando se utilizan funciones como controladores de eventos o funciones pasadas a componentes hijos.

La función useCallback toma dos argumentos: la primera es la función que se quiere memorizar y la segunda es una matriz de dependencias. La función se devolverá sólo si alguna de las dependencias ha cambiado desde la última vez que se devolvió.

Aquí hay un ejemplo de un componente de React que utiliza useCallback para mejorar el rendimiento de una lista de nombres:

import { useCallback } from 'react';

function NamesList({ names }) {
  const handleClick = useCallback((name) => {
    alert(`Hello, ${name}!`);
  }, []);

  return (
    <ul>
      {names.map((name) => (
        <li key={name} onClick={() => handleClick(name)}>
          {name}
        </li>
      ))}
    </ul>
  );
}

En este ejemplo, el componente NamesList recibe una propiedad names y utiliza useCallback para memorizar la función handleClick. La función recibirá un argumento con el nombre y mostrará una alerta con ese nombre cuando sea llamada. Al pasar handleClick como un controlador de evento para cada uno de los elementos de la lista

  • , se garantiza que la función no sea re-creada cada vez que se renderiza el componente.

    useCallback es útil cuando se tiene un componente que pasa funciones como propiedades a componentes hijos y se quiere asegurar de que estas funciones no son re-creadas cada vez que el componente principal se renderiza. Esto ayuda a mejorar el rendimiento de la aplicación al evitar recrear funciones innecesariamente.

    https://www.w3schools.com/react/react_usememo.asp
    https://www.w3schools.com/react/react_usecallback.asp
    https://beta.reactjs.org/reference/react/useMemo
    https://developero.io/blog/react-hook-usememo

    https://beta.reactjs.org/reference/react/useCallback
    https://latteandcode.medium.com/el-hook-usecallback-y-react-memo-87f761733c35

  • React useReducer

    useReducer es una función de React Hooks que te permite manejar el estado de tu aplicación de manera similar a como lo harías con un reducer en una aplicación Redux. A diferencia de useState, que sólo te permite guardar y actualizar un único valor de estado, useReducer te permite manejar estado complejo y encapsular la lógica relacionada con ese estado en un solo lugar.

    useReducer toma dos argumentos: el primer argumento es una función reducer y el segundo argumento es el estado inicial. La función reducer toma el estado actual y una acción, y devuelve el nuevo estado. El estado inicial es el valor inicial que se usará cuando se monta el componente.

    Aquí hay un ejemplo de un componente de React que utiliza useReducer para manejar el estado de un contador:

    import { useReducer } from 'react';
    
    function reducer(state, action) {
      switch (action.type) {
        case 'increment':
          return { count: state.count + 1 };
        case 'decrement':
          return { count: state.count - 1 };
        default:
          throw new Error();
      }
    }
    
    function Counter() {
      const [state, dispatch] = useReducer(reducer, { count: 0 });
    
      return (
        <>
          <h1>{state.count}</h1>
          <button onClick={() => dispatch({ type: 'increment' })}>+</button>
          <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
        </>
      );
    }
    

    En este ejemplo, el componente Counter utiliza la función useReducer para inicializar el estado con un objeto { count: 0 }. Luego, el componente utiliza unos botones para incrementar o decrementar el contador. Cada vez que el usuario hace clic en un botón, el componente llama a dispatch con una acción específica, que es manejada por el reducer para actualizar el estado. El estado actualizado es entonces pasado al componente para renderizar.

    Al igual que useState, useReducer devuelve un par de valores, el estado actual y una función dispatch para actualizarlo. Al tener toda la lógica relacionada con el estado en un solo lugar, es más fácil entender cómo se actualiza el estado y resolver cualquier problema relacionado con eso.

    useReducer es útil en aplicaciones de React de mayor tamaño y complejidad, ya que te permite manejar estado complejo y encapsular la lógica relacionada con este.

    https://www.w3schools.com/react/react_usereducer.asp
    https://beta.reactjs.org/reference/react/useReducer
    https://ewebik.com/react-js/usereducer
    https://developero.medium.com/react-hooks-usereducer-4d7b68ce22e2
    https://devtrium.com/posts/how-to-use-react-usereducer-hook