---
# System prepended metadata

title: <a name="nothing"></a>MANUAL TECNICO

---

# <a name="nothing"></a>MANUAL TECNICO
Programa desarrollado en Arduino que permite la simulacion de un juego de Tetris utilizando 2 matrices Led  8x8 usando compilacion en C que contiene datos de instrucciones a ejecutar simulando un compilador muy básico.

>“El manual técnico es el que proporciona todas las pautas de configuración y la lógica con la que se ha desarrollado en el programa, con el objetivo de que cualquier programador entienda la idea propia y su estructura; por lo que se considera necesario ser documentada.”
## <a name="intro" ></a>ÍNDICE

| Topico | Link |
| ------ | ------ |
| Introducción | [Ir](#intro) |
| Objetivos y alcances del sistema | [Ir](#ob) |
| Especificaciones Técnicas | [Ir](#specs) |
| Requisitos de Hardware | [Ir](#req) |
| Requisitos de software | [Ir](#req2) |
| Sistema operativo | [Ir](#sisop) |
| Lenguaje de Programación e IDE | [Ir](#lengprog) |
| Tecnologías utilizadas (Lógica del programa) | [Ir](#tech) |
| Funciones utilizadas   | [Ir](#func) |
| Flujo del programa | [Ir](#flujo) |
| Conclusiones | [Ir](#Conclu) |

## <a name="intro" ></a>INTRODUCCIÓN
El presente manual técnico tiene como finalidad describir la estructura y diseño del programa analizador de escritorio de un archivo lfp, así como dar explicación de los métodos, clases y procesos de cada apartado del programa y la modificación que se le podría dar para cualquier finalidad como el de mejorar el sistema o cambiar algunos atributos propios del analizador. El sistema cuenta con implementación de varias librerías propias de python como re, ios, pathlab, entre otros, como parte del conocimiento adquirido en los laboratorios de programación de computadoras en base a ello trataré de explicar en que métodos se fueron utilizando y como hacen funcionar el programa en los distintos sistemas operativos.
La implementación de librerías externas a python también fueron una opción para poder pedir y abrir ventanas para elegir los archivos necesarios, también se explicará paso a paso cual es el camino para entender perfectamente la arquitectura del programa. Resulta ser bastante fácil de implementar los ciclos y condiciones, también los métodos de interfaces gráficas puesto que es una función que viene integrada con la paquetería por defecto de Tkinter de python y así solo instanciarlos importando las librerías y utilizarlas.  

## <a name="ob"></a>Objetivos y alcances del sistema

### Objetivo General
- Que el estudiante interactúe con el microcontrolador Arduino.
### Objetivos Específicos
- Comprender el funcionamiento de las entradas y salidas con las que cuenta el microcontrolador.
- Aprender y aplicar el funcionamiento del lenguaje y las funciones disponibles para programar el microcontrolador.
- Aprender y aplicar el funcionamiento de las matrices led (8x8) e implementar algorimos complejos a su uso.
- Aprender y aplicar el funcionamiento de botones para proporcionar acción a una solución.
- Aprender y aplicar el funcionamiento de potenciómetros (como dispositivo análogo) para proporcionar acción a una solución.

## <a name="specs"></a>Especificaciones Técnicas


### <a name="req"></a>Requisitos de Hardware
|  |  |
| ------ | ------ |
|Memoria mínima|	512 MB|
|Memoria recomendada |	1 GB|
|Espacio en disco mínimo|	250 MB de espacio libre  |
|Espacio en disco recomendado	|  500 MB de espacio libre|
|MVP	|Proteus y Arduino instalados |

### <a name="req2"></a>Requisitos de software
## <a name="sisop"></a>Sistema operativo 
Windows
•	Windows 10 (8u51 y superiors)
•	Tener instalado el programa de Proteus y Librerias de Arduino Code u otro editor
•	RAM: 128 MB
•	Espacio en disco: 124 MB 
•	Procesador: Mínimo Pentium 2 a 266 MHz 
•	Algún explorador de internet
Mac OS X 
•	Tener instalado el programa Proteus Code u otro editor
•	Explorador de 64 bits 
•	Se requiere un explorador de 64 bits (Safari, Firefox, por ejemplo) para ejecutar Oracle Java en Mac OS X.
Linux
•	Oracle Linux 5.5+1 
•	Oracle Linux 6.x (32 bits), 6.x (64 bits)2 
•	Exploradores: Firefox
•	Arduino
•	Proteus

## <a name="lengprog"></a>Lenguaje de Programación e IDE
Para el desarrollo del programa se utilizó el lenguaje de Programación C y el IDE Arduino y Visual Studio Code para el desarrollo de interfaz se utilizo Proteus 8.10

## <a name="tech"></a>Tecnologías utilizadas (Lógica del programa)
- Arduino es una plataforma de creación de electrónica de código abierto, la cual está basada en hardware y software libre, flexible y fácil de utilizar para los creadores y desarrolladores. Esta plataforma permite crear diferentes tipos de microordenadores de una sola placa a los que la comunidad de creadores puede darles diferentes tipos de uso.

- Proteus es una aplicación para la ejecución de proyectos de construcción de equipos electrónicos en todas sus etapas: diseño del esquema electrónico, programación del software, construcción de la placa de circuito impreso, simulación de todo el conjunto, depuración de errores, documentación y construcción.

## <a name="func"></a>Funciones utilizadas 




## <a name="flujo"></a>Flujo del programa


## <a name="Conclu"></a>Conclusiones


Los diferentes módulos que componen Proteus se pueden adquirir de forma  independiente añadiendo nuevas funcionalidades esto nos ayuda a realizar nuestra PRACTICA 1 y a medida que aumentan nuestras necesidades de desarrollo y producción. Además, la capacidad de simular cada una de las  familias de microprocesadores también es objeto de adquisición por separado. De esta manera podemos empezar adquiriendo unas funcionalidades básicas e ir adquiriendo prograsivamente nuevas características aprovechando al máximo nuestras inversiones en la herramienta y asegurar al máximo los costes de inversión en el software.
 
En el mundo de la formación, Proteus se muestra como una hereramienta magnífica porque permite al alumno realizar modificaciones tanto en el circuito como en el  programa, experimentando y comprobando de forma inmediata los resultados y permitiéndole de esta forma aprender de forma práctica y sin riesgos de estropear materiales de elevado coste.

## <a name="Conclu"></a>Anexos

//!MATRIZ DE LETRAS
int figura[132][8]={
                      //^PRAC1-GRUPO02-SECC A^ 
  {0,0,0,1,0,0,0,0},
  {0,0,0,0,1,0,0,0},
  {0,0,0,0,0,1,0,0}, //^
  {0,0,0,0,0,1,0,0},
  {0,0,0,0,1,0,0,0},
  {0,0,0,1,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  
  {0,1,1,1,1,1,1,0},
  {0,0,0,1,0,0,1,0},
  {0,0,0,1,0,0,1,0},//P
  {0,0,0,0,1,1,0,0},
  {0,0,0,0,0,0,0,0}, 
   
  {0,1,1,1,1,1,1,0},
  {0,0,0,1,0,0,1,0},
  {0,0,1,1,0,0,1,0},//R
  {0,1,0,0,1,1,0,0},
  {0,0,0,0,0,0,0,0}, 
 
  {0,1,1,0,0,0,0,0},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,0,1,1,0},//A
  {0,0,0,1,1,0,0,0},
  {0,1,1,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
   
  {0,0,1,1,1,1,0,0},
  {0,1,0,0,0,0,1,0},
  {0,1,0,0,0,0,1,0},//C
  {0,1,0,0,0,0,1,0},
  {0,1,0,0,0,0,1,0},
  {0,0,0,0,0,0,0,0},

  {0,1,0,0,1,0,0,0},
  {0,1,0,0,0,1,0,0},
  {0,1,1,1,1,1,1,0},//1
  {0,1,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
                          
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},//-
  {0,0,0,1,1,0,0,0}, 

  {0,0,0,0,0,0,0,0},
  {0,0,1,1,1,1,0,0},
  {0,1,0,0,0,0,1,0},
  {0,1,0,1,1,0,1,0},//G
  {0,1,0,0,1,0,1,0},
  {0,0,1,1,0,0,0,0},
  {0,0,0,0,0,0,0,0},

  {0,1,1,1,1,1,1,0},
  {0,0,0,1,0,0,1,0},
  {0,0,1,1,0,0,1,0},//R
  {0,1,0,0,1,1,0,0},
  {0,0,0,0,0,0,0,0}, 

  {0,0,1,1,1,1,1,0},
  {0,1,0,0,0,0,0,0},
  {0,1,0,0,0,0,0,0},//U
  {0,1,0,0,0,0,0,0},
  {0,0,1,1,1,1,1,0},
  {0,0,0,0,0,0,0,0}, 
                      
  {0,1,1,1,1,1,1,0},
  {0,0,0,1,0,0,1,0},
  {0,0,0,1,0,0,1,0},//P
  {0,0,0,0,1,1,0,0},
  {0,0,0,0,0,0,0,0}, 

  {0,0,1,1,1,1,0,0},
  {0,1,0,0,0,0,1,0},
  {0,1,0,0,0,0,1,0},//O
  {0,1,0,0,0,0,1,0},
  {0,0,1,1,1,1,0,0},
  {0,0,0,0,0,0,0,0}, 

  {0,1,1,1,1,1,1,0},
  {0,1,0,0,0,0,1,0},
  {0,1,0,0,0,0,1,0},//0
  {0,1,1,1,1,1,1,0},
  {0,0,0,0,0,0,0,0},
 
  {0,1,1,0,0,1,0,0},
  {0,1,0,1,0,0,1,0},
  {0,1,0,0,1,0,1,0},//2
  {0,1,0,0,0,1,0,0},
  {0,0,0,0,0,0,0,0}, 
    
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},//-
  {0,0,0,1,1,0,0,0}, 

  {0,0,0,0,0,0,0,0},
  {0,1,0,0,0,1,0,0},
  {0,1,0,0,1,0,1,0},//S
  {0,1,0,0,1,0,1,0},
  {0,0,1,1,0,0,1,0},
  {0,0,0,0,0,0,0,0},

  {0,1,1,1,1,1,1,0},
  {0,1,0,0,1,0,1,0},
  {0,1,0,0,1,0,1,0},
  {0,1,0,0,1,0,1,0},//E
  {0,1,0,0,0,0,1,0},
  {0,0,0,0,0,0,0,0}, 

  {0,0,1,1,1,1,0,0},
  {0,1,0,0,0,0,1,0},
  {0,1,0,0,0,0,1,0},//C
  {0,1,0,0,0,0,1,0},
  {0,1,0,0,0,0,1,0},
  {0,0,0,0,0,0,0,0},
  
  {0,0,1,1,1,1,0,0},
  {0,1,0,0,0,0,1,0},
  {0,1,0,0,0,0,1,0},//C
  {0,1,0,0,0,0,1,0},
  {0,1,0,0,0,0,1,0},
  {0,0,0,0,0,0,0,0},

  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},// BLANCO

  {0,1,1,0,0,0,0,0},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,0,1,1,0},//A
  {0,0,0,1,1,0,0,0},
  {0,1,1,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
   
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},//BLANCO
  
  {0,0,0,1,0,0,0,0},
  {0,0,0,0,1,0,0,0},
  {0,0,0,0,0,1,0,0},//^
  {0,0,0,0,0,1,0,0},
  {0,0,0,0,1,0,0,0},
  {0,0,0,1,0,0,0,0},
  {0,0,0,0,0,0,0,0},
 
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}, 
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}, 
  {0,0,0,0,0,0,0,0}
};
//! PIEZAS QUE SE VAN GENERANDO
int naves[19][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}
};
//! MATRIZ AUXILIAR DONDE SE GUARDAN LAS POSICIONES Y ROTACIONES
int naves2[19][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}
};
//! CONTENEDOR DE TODAS LAS PIEZAS QUE YA TOCARON FONDO Y QUEDARON (MODO TIESO)
int uyquieto[19][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}
};
//! PARA INTERCAMBIO EN EL MENU START: 

//! FRAMES O MATRICES PARA LAS PUNTUACIONES
int cero[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,1,1,1,1,1,1,0},
  {0,1,1,0,0,0,1,0},
  {0,1,0,1,1,0,1,0},
  {0,1,0,0,0,1,1,0},
  {0,1,1,1,1,1,1,0},
  {0,0,0,0,0,0,0,0}
};


int uno[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,1,0,0,1,0,0,0},
  {0,1,0,0,0,1,0,0},
  {0,1,1,1,1,1,1,0}, 
  {0,1,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}
};

int dos[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,1,1,0,0,1,0,0},
  {0,1,0,1,0,0,1,0},
  {0,1,0,0,1,0,1,0},//2
  {0,1,0,0,0,1,0,0},
  {0,0,0,0,0,0,0,0}, 
  {0,0,0,0,0,0,0,0}
};
int tres[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,1,1,0,0,0,1,1},
  {0,1,0,0,0,0,0,1},
  {0,1,0,0,1,0,0,1},
  {0,1,0,1,0,1,0,1},
  {0,0,1,0,0,0,1,0},
  {0,0,0,0,0,0,0,0}
};

int cuatro[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,1,1,1,1,0},
  {0,0,0,1,0,0,0,0},
  {0,0,0,1,0,0,0,0},
  {0,1,1,1,1,1,0,0},
  {0,0,0,1,0,0,0,0},
  {0,0,0,0,0,0,0,0}
};

int cinco[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,1,0,1,1,1,1},
  {0,1,0,0,1,0,0,1},
  {0,1,0,0,1,0,0,1},
  {0,1,0,0,1,0,0,1},
  {0,1,0,0,1,0,0,1},
  {0,0,1,1,0,0,0,1},
  {0,0,0,0,0,0,0,0}
};

int seis[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,1,1,1,1,1,0},
  {0,1,0,0,1,0,0,1},
  {0,1,0,0,1,0,0,1},
  {0,1,0,0,1,0,0,1},
  {0,1,0,0,1,0,0,1},
  {0,0,1,1,0,0,1,0},
  {0,0,0,0,0,0,0,0}
};

int siete[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,1},
  {0,0,0,0,0,0,0,1},
  {0,1,1,1,0,0,0,1},
  {0,0,0,0,1,0,0,1},
  {0,0,0,0,0,1,0,1},
  {0,0,0,0,0,0,1,1},
  {0,0,0,0,0,0,0,0}
};

int ocho[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,1,1,0,1,1,0},
  {0,1,0,0,1,0,0,1},
  {0,1,0,0,1,0,0,1},
  {0,1,0,0,1,0,0,1},
  {0,1,0,0,1,0,0,1},
  {0,0,1,1,0,1,1,0},
  {0,0,0,0,0,0,0,0}
};

int nueve[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,1,0,0,1,1,0},
  {0,1,0,0,1,0,0,1},
  {0,1,0,0,1,0,0,1},
  {0,1,0,0,1,0,0,1},
  {0,1,0,0,1,0,0,1},
  {0,0,1,1,1,1,1,0},
  {0,0,0,0,0,0,0,0}
};
int ene[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,1,1,1,1,1,1,0},
  {0,0,0,0,0,1,0,0},
  {0,0,0,0,1,0,0,0},
  {0,0,0,1,0,0,0,0},
  {0,0,1,0,0,0,0,0},
  {0,1,1,1,1,1,1,0},
  {0,0,0,0,0,0,0,0}
};

int E[8][8]={
  {1,1,1,1,1,1,1,1},
  {1,1,1,1,1,1,1,1},
  {1,1,0,1,1,0,1,1},
  {1,1,0,1,1,0,1,1},
  {1,1,0,1,1,0,1,1},
  {1,1,0,0,0,0,1,1},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}
};

int Pieza0[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,1,1,1,1,1,1,0},
  {0,1,1,1,1,1,1,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}
};

int Pieza1[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,1,1,0,0,0},
  {0,0,0,1,1,0,0,0},
  {0,1,1,1,1,1,1,0},
  {0,1,1,1,1,1,1,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}
};

int Pieza2[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,1,1,0,0,0,0,0},
  {0,1,1,0,0,0,0,0},
  {0,1,1,1,1,1,1,0},
  {0,1,1,1,1,1,1,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}
};

int Pieza3[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,1,1,1,1,0},
  {0,0,0,1,1,1,1,0},
  {0,0,0,1,1,0,0,0},
  {0,1,1,1,1,0,0,0},
  {0,1,1,1,1,0,0,0},
  {0,0,0,0,0,0,0,0}
};

int Pieza4[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,1,1,1,1,1,1,0},
  {0,1,1,1,1,1,1,0},
  {0,1,1,1,1,1,1,0},
  {0,1,1,1,1,1,1,0},
  {0,1,1,1,1,1,1,0},
  {0,1,1,1,1,1,1,0},
  {0,0,0,0,0,0,0,0}
};

int Pieza5[8][8]={
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,1,1,1,0,0,0},
  {0,0,1,1,1,0,0,0},
  {0,0,1,1,1,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0},
  {0,0,0,0,0,0,0,0}
}; 


int pot = A2;//potenciometro velocidad letras
int pot2 = A0;//potenciometro velocidad juego
int dir = 22;//direccion de las letras
unsigned long tiempo;//tiempo de movimiento de las letras
unsigned long tiempoStar;//tiempo de botón precionado.
unsigned long tiempoPausar;//tiempo de botón pausar precionado.
unsigned long tiempoBalas;//tiempo para movimiento de balas
unsigned long tiempoNaves;//tiempo para movimiento de naves
unsigned long tiempoGameOver;//tiempo en que muestra punteo luego de perder
int fActual=0;//fila de la matriz de letras con la que se empieza a pintar la matriz de leds
int boton = 23;//botonStart
int estadoAnteriorBtnStart = 1;
int btnder = 24;//boton derecha
int btndisp = 25;//boton disparar
int btnizq = 26;//boton izquierda
int btnpush = 28;//boton para el push  del juego
int juegoEmpezado = 0;//bandera de inicio de juego
int flag0 = 0;//bandera de inicio de contador tiempoStar
int flag1 = 0;//bandera de inicio de para quitar pausa
int posJugador = 2;//posicion del jugador
int estadoBtnDer = 1;//estadoActual del pusador, pulso en 0
int estadoAnteriorBtnDer = 1;//estado anterior del pusador, pulso en 0
int estadoBtnIzq = 1;//estadoActual del pusador, pulso en 0
int estadoAnteriorBtnIzq = 1;//estado anterior del pusador, pulso en 0
int estadoBtnDisp = 1;//estadoActual del pusador, pulso en 0
int estadoAnteriorBtnDisp = 1;//estado anterior del pusador, pulso en 0
int estadoBtnPush = 1;
int estadoAnteriorBtnPush = 1;
long randomNumber;
int punteo = 0;//punteo del juego
int derecha = 0;
int izquierda = 0;
int aceptarCambio = 0;
int UltimaFiguraCreada = -1;
int figurarand =0; // guarda posicion random de bloque del 0-6
int rotacion=0; //INDICADOR DE LA ROTACION QUE TIENE CADA BLOQUE
int quedoquieto=1; //variable para saber si ya se quedo quieta la pieza en "uyquieto"
int piezaActual = -1;
int piezaSiguiente = -1;
int cambiopuntospieza=0; // alterna puntos y piezas en el menu de pausa
int contadorpasar=0;
int flagPuedePasar = 1;//1 si las celdas estan vacias(bandera)
int posX0 = 3;
int posX1 = 3;
int posX2 = 3;
int posX3 = 3;
int posX4 = 3;
int posX5 = 3;
int posX6 = 3;
int posX7 = 3;
int cambiarDer = 0;  
int cambiarIzq = 0;
  
void setup() {
  digitalWrite(27,HIGH);//puerto 27 que va a el reset se coloca en positivo
  pinMode(27,OUTPUT);//se declara que puerto 27 como salida
  tiempo = millis();
  tiempoStar = millis();
  randomSeed(analogRead(A1));//A1 puerto analogo de ruido(simulado con potenciometro)
  //INICIAMOS TODOS PUERTOS NECESARIOS
  Serial.begin(9600);
  pinMode(dir,INPUT);
  pinMode(boton, INPUT);
  pinMode(btnder,INPUT);
  pinMode(btndisp,INPUT);
  pinMode(btnizq,INPUT);
  
  for (int i = 31; i<39; i++){
    pinMode(i,OUTPUT); 
  }
  for (int i = 41; i<49; i++){
    pinMode(i,OUTPUT);
  }
  //limpia las columnas encendidas matriz1
  for(int i=41; i<49; i++){
    digitalWrite(i, HIGH);
  }
  //PARAMETROS INICIALES MATRIZ 2
  lc.shutdown(0,false);
  lc.setIntensity(0,15);
  lc.clearDisplay(0); 
}

void limpiarTodo(){  
  pot = A2;//potenciometro velocidad letras
  pot2 = A0;//potenciometro velocidad juego
  dir = 22;//direccion de las letras 
  fActual=0;//fila de la matriz de letras con la que se empieza a pr la matriz de leds
  boton = 23;//botonStart
  estadoAnteriorBtnStart = 1;
  btnder = 24;//boton derecha
  btndisp = 25;//boton disparar
  btnizq = 26;//boton izquierda
  btnpush = 28;//boton para el push  del juego
  juegoEmpezado = 0;//bandera de inicio de juego
  flag0 = 0;//bandera de inicio de contador tiempoStar
  flag1 = 0;//bandera de inicio de para quitar pausa
  posJugador = 2;//posicion del jugador
  estadoBtnDer = 1;//estadoActual del pusador, pulso en 0
  estadoAnteriorBtnDer = 1;//estado anterior del pusador, pulso en 0
  estadoBtnIzq = 1;//estadoActual del pusador, pulso en 0
  estadoAnteriorBtnIzq = 1;//estado anterior del pusador, pulso en 0
  estadoBtnDisp = 1;//estadoActual del pusador, pulso en 0
  estadoAnteriorBtnDisp = 1;//estado anterior del pusador, pulso en 0
  estadoBtnPush = 1;
  estadoAnteriorBtnPush = 1;
  randomNumber = 0;
  punteo = 0;//punteo del juego
  derecha = 0;
  izquierda = 0;
  aceptarCambio = 0;
  UltimaFiguraCreada = -1;
  figurarand =0; // guarda posicion random de bloque del 0-6
  rotacion=0; //INDICADOR DE LA ROTACION QUE TIENE CADA BLOQUE
  quedoquieto=1; //variable para saber si ya se quedo quieta la pieza en "uyquieto"
  piezaActual = -1;
  piezaSiguiente = -1;
  cambiopuntospieza=0; // alterna puntos y piezas en el menu de pausa
  contadorpasar=0;
  flagPuedePasar = 1;//1 si las celdas estan vacias(bandera)
  posX0 = 3;
  posX1 = 3;
  posX2 = 3;
  posX3 = 3;
  posX4 = 3;
  posX5 = 3;
  posX6 = 3;
  posX7 = 3;
  cambiarDer = 0;  
  cambiarIzq = 0;

  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves[i][j]=0;
        naves2[i][j]=0;
        uyquieto[i][j]=0;
    }
  }
  
}

//!████████████████████████████ MENSAJE GRUPAL ███████████████████████████████████████████████
//----PINTAR MATRIZ 1 DE LETRAS----
void pintar(int f){
  for (int i=0; i<8; i++){
    //habilitamos fila con HIGH
    digitalWrite(i+31, HIGH);
    for(int j=0; j<8; j++){
      if (figura[i+f][j] == 1){
        //encendemos led con LOW
        digitalWrite(j+41, LOW);
      }
    }
    delay(1);//después de pintar una fila completa esperamos un milisegundo
    digitalWrite(i+31, LOW);//desabilitamos fila con LOW
    for(int j=41; j<49; j++){
      digitalWrite(j, HIGH);//apagamos columnas con HIGH
    }    
  }
  //Luego de pintar primera Matriz llamamos a pintar Segunda ya que el método es diferente
  pintarSegundaMatriz(f+8);
}

//----PINTAR MATRIZ 2 DE LETRAS----
void pintarSegundaMatriz(int f){
  //Se maneja columna fila por el recorrido de la matriz física
  //como la matriz está volteada si se están recorriendo por filas visualmente
  for (int columna = 0; columna <8; columna++){
    for(int fila = 0; fila <8; fila++){
      if(figura[columna+f][fila] == 1){
        lc.setLed(0,fila,columna,true);
      }
    }
    delay(1);//despues de pintar la "fila visual" esperamos 1 milisegundo
    //la matriz2 se borra completa al cambiar la variable tiempo con el potenciometro
  }
}

//----FUNCION DE PINTADO DE NOMBRES----

void pintarNombres(int lectura){
  int antIzq = izquierda;
  int antDer = derecha;
  
  if(digitalRead(btnder) == LOW){ 
      if(izquierda == 1){
         izquierda = 0;
      }
      derecha = 1;
  }

  if(digitalRead(btnizq) == LOW){ 
      if(derecha == 1){
         derecha = 0;
      }
      izquierda = 1; 
  }

  if(digitalRead(boton) == LOW){ 
      if(antDer == 1){ 
          cambiarDer = 1;
          cambiarIzq = 0;
      }else if(antIzq == 1){ 
          cambiarDer = 0;
          cambiarIzq = 1;
      }
  }

  
  if(cambiarDer == 1){  
    if (millis()-tiempo >lectura){ 
      fActual--;
      tiempo = millis();
      lc.clearDisplay(0);
    }
    if (fActual ==-1){ 
      fActual = 117;
    }  
    pintar(fActual);  
  }else{
    if (millis()-tiempo >lectura){ 
      fActual++;
      tiempo = millis();
      lc.clearDisplay(0);
    }
    
    if (fActual ==117){ 
      fActual = 0;
    } 
    pintar(fActual);  
  }
  
  if(cambiarIzq == 1){
        if (millis()-tiempo >lectura){ 
      fActual++;
      tiempo = millis();
      lc.clearDisplay(0);
    }
    
    if (fActual ==117){ 
      fActual = 0;
    }  
    pintar(fActual);  
  }

}

//!████████████████████████████ TIEMPO PRESIONADO START ███████████████████████████████████████████████

void turnar(){
  
  if (cambiopuntospieza == 0){  
    pintarPunteo();                          // * <== Esto se va alternando
  }else if(cambiopuntospieza==1){  
    pintarSiguientePieza(); 
  }
  
}



//! ----EVALUA EL TIEMPO QUE LLEVA PRECIONADO EL BOTÓN STAR----
// ESTADOS:  (Variable "juegoempezado")
// - 0 esta en mensaje
// - 1 esta jugando
// - 2 esta en pausa
// - 3 salida (reinicio)    <=- es directo no es estado utilizable
// - 4 esta modo Error
void esperarStar()
{
  //! SI SE PRESIONA EL BOTON PUSH
  if (digitalRead(boton) == LOW)
  {
    //* si el juego esta en pausa
    // si juego en pausa y boton anterior estuvo presionado -> se activa bandera 1
    // se guarda el tiempo en que se pauso
    if ((juegoEmpezado == 2) && (estadoAnteriorBtnStart == 1))
    {
      flag1 = 1;
      tiempoPausar = millis();
      //Aqui siempre entra si estuvo encendido el boton
      // tiempoStar = millis();
    }

    //* si el juego esta corriendo
    // si detectamos primera vez el pulso activo bandera 0 y guardo tiempo de inicio del pulso
    else if (flag0 == 0)
    {                        //! SI ES PRIMERA DETECCIÓN DE PULSO
      flag0 = 1;             // ACTIVA BANDERA DE CONTEO
      tiempoStar = millis(); // INICIA CONTADOR   (a que hora empece a presionar)
    }
    //* luego...
    // si han pasado 3 segundos entra al menu+
    else
    {
      if (juegoEmpezado!=2){ // sino esta pausado
        if (millis() - tiempoStar > 3000)
      { // SI EL CONTADOR YA LLEVA 3 SEGUNDOS
        flag0 = 0;
        switch (juegoEmpezado)
        {
        case 0:
          //! AL PRESIONAR 3 SEGUNDOS LA PRIMERA VEZ ENTRA A INICIAR EL JUEGO
          juegoEmpezado = 1; // EMPIEZA JUEGO
          Serial.println("--------------------------Juego empezado--------------------------");
          break;
        case 1: 
          juegoEmpezado = 2;//PAUSA EL JUEGO  
          for(int i=0; i<8; i++){
            lc.setLed(0,14,i,false);
            lc.setLed(0,15,i,false);
          }
          break;
        }
        lc.clearDisplay(0); // BORRA SEGUNDA MATRIZ
      }
    }
  }   
  }else{
    if ((flag0 == 1) && (flag1 == 1)){       
      if(millis() - tiempoStar <= 2000){ 
        if (cambiopuntospieza == 0){  
          cambiopuntospieza=1; 
        }else if(cambiopuntospieza==1){  
          cambiopuntospieza=0;
        } 
        lc.clearDisplay(0);
                
      }else if((millis() - tiempoStar > 2000) && (millis() - tiempoStar <= 3000)){  
        limpiarTodo();
        flag1 = 0;
      }else if ((millis() - tiempoStar > 3000) && (millis() - tiempoStar <= 4000)){ 
        juegoEmpezado = 1;
        flag1 = 0; 
      }else if ((millis() - tiempoStar > 4000) && (millis() - tiempoStar <= 5000)){ 
        Serial.println("4 seg");
        limpiarTodo();
        juegoEmpezado = 1;         
        lc.clearDisplay(0);
        flag1 = 0;  
      }else if ((millis() - tiempoStar > 5000)){
        juegoEmpezado = 4;
        lc.clearDisplay(0);
        flag1 = 0;
      }
    }
    flag0 = 0;
  }  
  estadoAnteriorBtnStart = digitalRead(boton); 
}

//ASIGNAR MATRIZ Y 
//!██████████████████████████████████ ROTACIONES ████████████████████████████████████████████████
void limpiarMatrizNaves(){
  //* limpiamos la matriz
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves[i][j]=0;
    }
  }
}
//! FUNCIONES DE ROTACIONES
//? Palito original
void  rotPalito0(){
  //*ASIGNAMOS NAVES2 A NAVES
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* SETEAMOS LA FIGURA

  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        //! TRATO DE VALIDAR QUE CUANDO ESTE ACOSTADO EN LAS ULTIMAS 3 FILAS NO SE PASE DEL LIMITE
        //* si queda una figura acostada pero esta en las ultimas 3 filas osea de la 5-7
        if(j>=0 && j<=2){
          if((naves2[i][j]==1)&&(naves2[i+1][j]==1)&&(naves2[i+2][j]==1)&&(naves2[i+3][j]==1)){
            //* entonces la I queda en una misma forma :
            naves[i+3][0]=1;  //! █
            naves[i+3][1]=1;  //! █
            naves[i+3][2]=1;  //! █
            naves[i+3][3]=1;  //! █
            return;
          }
        }
        
        if(naves2[i][j]==1){
          naves[i+3][j]=1;    //! █
          naves[i+3][j-1]=1;  //! █
          naves[i+3][j-2]=1;  //! █
          naves[i+3][j-3]=1;  //! █
          return;
        }
    }
  }
}
//? Palito Acostadito
void  rotPalito1(){
  //*ASIGNAMOS NAVES2 A NAVES
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* SETEAMOS LA FIGURA
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        if(naves2[i][j]==1){
          naves[i][j+3]=1;
          naves[i-1][j+3]=1; //! ▀▀▀▀▀▀▀▀▀▀▀▀
          naves[i-2][j+3]=1;
          naves[i-3][j+3]=1;
          return;
        }
    }
  }
}

//? Ele original
void  rotEle0(){
  //*ASIGNAMOS NAVES2 A NAVES
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* SETEAMOS LA FIGURA
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
      // solo si esta el primero osea j=6
        if(naves2[i][0]==1 && naves2[i+1][0]==1 && naves2[i+2][0]==1 && naves2[i][1]==1 ){
          naves[i+2][0]=1;    //!    █
          naves[i+2][1]=1;    //!    █ Hasta abajo
          naves[i+2][2]=1;    //!    █
          naves[i+1][0]=1;    //! ▀▀▀▀
          return;
        }
        if(naves2[i][j]==1){
          naves[i+2][j]=1;    //!    █
          naves[i+2][j+1]=1;  //!    █ 
          naves[i+2][j-1]=1;  //!    █
          naves[i+1][j-1]=1;  //! ▀▀▀▀
          return;
        }
    }
  }
}

//? Ele rot1
void  rotEle1(){
  //*ASIGNAMOS NAVES2 A NAVES
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* SETEAMOS LA FIGURA
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        if(naves2[i][j]==1){
          naves[i+1][j+2]=1;    //! ▀▀▀▀▀▀▀█
          naves[i+1][j+1]=1;    //!        █
          naves[i][j+2]=1;
          naves[i-1][j+2]=1;
          return;
        }
    }
  }
}

//? Ele rot2
void  rotEle2(){
  //*ASIGNAMOS NAVES2 A NAVES
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* SETEAMOS LA FIGURA
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
      if(naves2[i][0]==1 && naves2[i][1]==1 && naves2[i-1][1]==1 && naves2[i-2][1]==1 ){
          naves[i-1][0]=1;    //!    █▀▀
          naves[i-1][1]=1;    //!    █
          naves[i-1][2]=1;    //!    █  hasta abajo
          naves[i][2]=1;      //!
          return;
        }
        if(naves2[i][j]==1){
          naves[i+1][j]=1;    //!    █▀▀
          naves[i][j]=1;      //!    █
          naves[i][j-1]=1;    //!    █
          naves[i][j-2]=1;    //!
          return;
        }

    }
  }
}

//? Ele rot3
void  rotEle3(){
  //*ASIGNAMOS NAVES2 A NAVES
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* SETEAMOS LA FIGURA
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        if(naves2[i][j]==1){
          naves[i][j+1]=1;    //!    █
          naves[i][j+2]=1;    //!    ▀▀▀▀▀▀▀▀
          naves[i+1][j+1]=1;
          naves[i+2][j+1]=1;
          return;
        }
    }
  }
}

//! TRIANGULITO
//? Trian original
void  rotTrian0(){
  //*ASIGNAMOS NAVES2 A NAVES
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* SETEAMOS LA FIGURA
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
      if(naves2[i][0]==1 && naves2[i+1][0]==1 && naves2[i+2][0]==1 && naves2[i+1][1]==1 ){
          naves[i+2][0]=1;    //!      ██
          naves[i+2][1]=1;    //!    ████ hasta abajo
          naves[i+2][2]=1;    //!      ██
          naves[i+1][1]=1;
          return;
        }
        if(naves2[i][j]==1){
          naves[i+1][j]=1;        //!      ██
          naves[i+2][j]=1;        //!    ████
          naves[i+2][j+1]=1;      //!      ██
          naves[i+2][j-1]=1;
          return;
        }
    }
  }
}

//? Trian rot1
void  rotTrian1(){
  //*ASIGNAMOS NAVES2 A NAVES
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* SETEAMOS LA FIGURA
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        if(naves2[i][j]==1){
          naves[i+1][j]=1; 
          naves[i][j]=1;         //!    ██████
          naves[i-1][j]=1;         //!      ██
          naves[i][j-1]=1;
          return;
        }
    }
  }
}

//? Ele rot2
void  rotTrian2(){
  //*ASIGNAMOS NAVES2 A NAVES
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* SETEAMOS LA FIGURA
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
    if(naves2[i][6]==1 && naves2[i][7]==1 && naves2[i+1][7]==1 && naves2[i-1][7]==1 ){
          naves[i][7]=1;    //!    ██
          naves[i+1][6]=1;  //!    ████ hasta abajo
          naves[i][5]=1;    //!    ██
          naves[i][6]=1;
          return;
        }
        if(naves2[i][j]==1){
          naves[i][j-1]=1;        //!    ██
          naves[i][j+1]=1;      //!    ████
          naves[i][j]=1;      //!    ██
          naves[i+1][j]=1;
          return;
        }
    }
  }
}

//? Trian rot3
void  rotTrian3(){
  //*ASIGNAMOS NAVES2 A NAVES
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* SETEAMOS LA FIGURA
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        if(naves2[i][j]==1){
          naves[i][j+1]=1;        //!      ██
          naves[i-1][j+1]=1;      //!    ██████
          naves[i+1][j+1]=1;
          naves[i][j+2]=1;
          return;
        }
    }
  }
}

//! ZETA
//? ZETA original
void  rotZeta0(){
  //*ASIGNAMOS NAVES2 A NAVES
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* SETEAMOS LA FIGURA
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        if(naves2[i][j]==1){
          naves[i][j+1]=1;        //!      ████
          naves[i-1][j]=1;      //!    ████
          naves[i-1][j+1]=1;
          naves[i-2][j]=1;
          return;
        }
    }
  }
}

//? Zeta rot1
void  rotZeta1(){
  //*ASIGNAMOS NAVES2 A NAVES
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* SETEAMOS LA FIGURA
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        if(naves2[i][0]==1 && naves2[i+1][0]==1 && naves2[i+1][1]==1 && naves2[i+2][1]==1 ){
          naves[i+2][0]=1;    //!   ██
          naves[i+2][1]=1;    //!   ████ hasta abajo
          naves[i+1][1]=1;    //!     ██
          naves[i+1][2]=1;
          return;
        }
        if(naves2[i][j]==1){
          naves[i+1][j]=1;      //!    ██
          naves[i+2][j]=1;      //!    ████
          naves[i+1][j+1]=1;    //!      ██
          naves[i+2][j-1]=1;
          return;
        }
    }
  }
}



//!███████████████████████████████ CREACION DE FIGURAS ███████████████████████████████████████████████████
//!----MOVIMIENTO FIGURAS----
int hayunotopo(){
  int flagdeKieto=0;
  //! VALIDACIONES PARA CADA TIPO DE FIGURA Y CADA ROTACION CON LO QUE TOPE:
  for(int i=posX0; i<19; i++){
    if(naves[posX0][0] == 1){
      flagdeKieto=1;
      posX0 = posX0+1; 
    }
   }

  for(int i=posX1; i<19; i++){ 
    if(naves[posX1][1] == 1){
      flagdeKieto=1;
      posX1 = posX1+1;   
    }
  }
  
  for(int i=posX2; i<19; i++){ 
    if(naves[posX2][2] == 1){
      flagdeKieto=1;
      posX2 = posX2+1;   
    }
  }

  for(int i=posX3; i<19; i++){ 
    if(naves[posX3][3] == 1){
      flagdeKieto=1;
      posX3 = posX3+1;  
    }
  }

  for(int i=posX4; i<19; i++){ 
    if(naves[posX4][4] == 1){
      flagdeKieto=1;
      posX4 = posX4+1;  
    }
  }

  for(int i=posX5; i<19; i++){ 
    if(naves[posX5][5] == 1){
      flagdeKieto=1;
      posX5 = posX5+1;  
    }
  }

  for(int i=posX6; i<19; i++){ 
    if(naves[posX6][6] == 1){
      flagdeKieto=1;
      posX6 = posX6+1;  
    }
  }

  for(int i=posX7; i<19; i++){ 
    if(naves[posX7][7] == 1){
      flagdeKieto=1;
      posX7 = posX7+1;  
    }
  } 
  return flagdeKieto;
}

void validarChoque(){
  int flagdeKieto=0;
  
  flagdeKieto=hayunotopo();
  
  if(flagdeKieto==1){
     //*AGREGAMOS naves A uyquieto + uyquietoAnterior
    for(int i=0; i<19; i++){
      for(int j=0; j<8; j++){
          if(naves[i][j]==1){ //* Agrego el frame actual (pieza) para que quede inmovil en uyquieto
            uyquieto[i][j]=1; //!uyquieto no se borra hasta eliminar las columnas de 8
          }
      }
    }
    limpiarMatrizNaves();
    flagPuedePasar = 1;
  }
  //! VALIDACION DE PUNTOS (VERIFICAR SI TODA UNA COLUMNA ES UN 1)
}

//!███████████████████████████████ VALIDAR PUNTOS DEL JUEGO███████████████████████████████████████████████████

//! Funcion que valida si la columna se lleno con las piezas entrantes

void validar_columnas(){
  for(int i=0; i < 19; i++){
    //*Recorre las 19 columnas
    int contador_columnas = 0;
    for(int j=0; j<8; j++){
      //*Recorre las 8 filas 
      if(uyquieto[i][j] == 1){
        contador_columnas++;
        if(contador_columnas == 8){
          for(int j=0; j<8; j++){ 
            Eliminar_Columna(i);
            
            for(int k = i; k<19; k++){ 
              for(int l = 0; l<8; l++){ 
                uyquieto[k][l] = uyquieto[k+1][l]; 
              }
            }

            posX0 = 3;
            posX1 = 3;
            posX2 = 3;
            posX3 = 3;
            posX4 = 3;
            posX5 = 3;
            posX6 = 3;
            posX7 = 3;

            for(int i=posX0; i<19; i++){
              if(naves[posX0][0] == 1){ 
                posX0 = posX0+1; 
              }
             }
          
            for(int i=posX1; i<19; i++){ 
              if(naves[posX1][1] == 1){ 
                posX1 = posX1+1;   
              }
            }
            
            for(int i=posX2; i<19; i++){ 
              if(naves[posX2][2] == 1){ 
                posX2 = posX2+1;   
              }
            }
          
            for(int i=posX3; i<19; i++){ 
              if(naves[posX3][3] == 1){ 
                posX3 = posX3+1;  
              }
            }
          
            for(int i=posX4; i<19; i++){ 
              if(naves[posX4][4] == 1){ 
                posX4 = posX4+1;  
              }
            }
          
            for(int i=posX5; i<19; i++){ 
              if(naves[posX5][5] == 1){ 
                posX5 = posX5+1;  
              }
            }
          
            for(int i=posX6; i<19; i++){ 
              if(naves[posX6][6] == 1){ 
                posX6 = posX6+1;  
              }
            }
          
            for(int i=posX7; i<19; i++){ 
              if(naves[posX7][7] == 1){ 
                posX7 = posX7+1;  
              }
            }
            
            punteo = punteo + 1; 
            j = 8;
          }
        }
      }
    }
  }
}
void Eliminar_Columna(int i){ 
    for(int j=0; j<8; j++){
        uyquieto[i][j]=0;
    }
  }
   

//!███████████████████████████████ MOVIMIENTO DE FIGURAS ███████████████████████████████████████████████████
void moverMatrizNaves(){
  //BAJA FILA N-1 A FILA N, Y EN FILA 0 AGREGA CEROS
 
  //! SOLO UN CORRIMIENTO
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        if(i!=18){
          naves[i][j]=naves[i+1][j]; //* se hace el corrimiento importante para ir recorriendo todo
        }else{
          naves[i][j]=0; //* si es la ultima columna agrega ceros
        }
    }
  }
  for(int i=3; i<19; i++){
    for(int j=0; j<8; j++){
      if(uyquieto[i][j]==1){ 
        switch(j){
          case 0:
            posX0 = i+1;
            break;
          case 1:
            posX1 = i+1;              
            break;
          case 2:
            posX2 = i+1;  
            break;
          case 3:
            posX3 = i+1;  
            break;
          case 4:
            posX4 = i+1;  
            break;
          case 5:
            posX5 = i+1;  
            break;
          case 6:
            posX6 = i+1;  
            break;
          case 7:
            posX7 = i+1;  
            break; 
        }          
      }
    }
  }
  
  //! DESPUES DE VALIDAR DE QUE CORRA UNA POSICION VERIFICO SI QUEDA EN LA PRIMERRA COLUMNA
  validarChoque();
 
  if(contadorpasar == 18){
    flagPuedePasar = 1;
  }
  
  //si las celdas estan vacias la bandera permanece en 1 por lo que se agrega una nueva nave con random
  if (flagPuedePasar == 1){ 
    //! ☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻ GENERO LA FIGURA ☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻
    if(piezaActual == -1 && piezaSiguiente == -1){
      piezaActual = random(0,6);
      piezaSiguiente = random(0,6);
    }else{
      piezaActual = piezaSiguiente;
      piezaSiguiente = random(0,6);
    }
    
    figurarand = piezaActual;
    
    switch(piezaActual){
      case 0:
            UltimaFiguraCreada = 0;
            randomNumber = random(0,5);  
            Serial.print("* Posicion Pieza Actual: ");
            Serial.println(randomNumber);
            naves[18][randomNumber]=1;
            naves[18][randomNumber+1]=1;
            naves[18][randomNumber+2]=1;
            naves[18][randomNumber+3]=1;
            break;
      case 1:
            UltimaFiguraCreada = 1;
            randomNumber = random(0,6); 
            Serial.print("* Posicion Pieza Actual: ");
            Serial.println(randomNumber);
            naves[18][randomNumber]=1;
            naves[18][randomNumber+1]=1;
            naves[18][randomNumber+2]=1;
            naves[18-1][randomNumber+1]=1;
            break;
      case 2:
            UltimaFiguraCreada = 2;
            randomNumber = random(0,6);
            Serial.print("* Posicion Pieza Actual: ");
            Serial.println(randomNumber);
            naves[18][randomNumber]=1;
            naves[18][randomNumber+1]=1;
            naves[18][randomNumber+2]=1;
            naves[18-1][randomNumber]=1;
            break;
      case 3:
            UltimaFiguraCreada = 3;
            randomNumber = random(0,6);
            Serial.print("* Posicion Pieza Actual: ");
            Serial.println(randomNumber);
            naves[18][randomNumber]=1;
            naves[18][randomNumber+1]=1;
            naves[18-1][randomNumber+1]=1;
            naves[18-1][randomNumber+2]=1;
            break;
      case 4:
            UltimaFiguraCreada = 4;
            randomNumber = random(0,7);
            Serial.print("* Posicion Pieza Actual: ");
            Serial.println(randomNumber);
            naves[18][randomNumber]=1;
            naves[18][randomNumber+1]=1;
            naves[18-1][randomNumber]=1;
            naves[18-1][randomNumber+1]=1;
            break;
      case 5:
            UltimaFiguraCreada = 5;
            randomNumber = random(0,8);
            Serial.print("* Posicion Pieza Actual: ");
            Serial.println(randomNumber);
            naves[18][randomNumber]=1; 
            break;
    }

    switch(piezaSiguiente){
      case 0: 
            Serial.println("> Siguiente Pieza que se generará: I"); 
            break;
      case 1:  
            Serial.println("> Siguiente Pieza que se generará: T");
            break;
      case 2: 
            Serial.println("> Siguiente Pieza que se generará: L"); 
            break;
      case 3: 
            Serial.println("> Siguiente Pieza que se generará: Z"); 
            break;
      case 4: 
            Serial.println("> Siguiente Pieza que se generará: O"); 
            break;
      case 5: 
            Serial.println("> Siguiente Pieza que se generará: ."); 
            break;
    }
    
    contadorpasar=0;
    flagPuedePasar=0;
  }
  contadorpasar++;
}

void comprobarChoques(){
  for (int i=14; i<16; i++){
    for(int j=0; j<8; j++){
      //SI EXISTE 1 EN LA MISMA POSICION EXISTE CHOQUE, SE TERMINA EL JUEGO
      
    }
  }
}

//!████████████████████████████████   UP / DOWN   ██████████████████████████████████████████████████
//! FUNCIONES PARA MOVER ARRIBA Y ABAJO
void moverdown(){
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* restamos 1 a las columnas para subir
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        if(naves2[i][j]==1){
          naves[i][j-1]=1;
        }
    }
  }
}

void  moverup(){
  //*ASIGNAMOS NAVES2 A NAVES
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        naves2[i][j]=naves[i][j];
    }
  }
  limpiarMatrizNaves();
  //* sumamos 1 a las columnas para bajar
  for(int i=0; i<19; i++){
    for(int j=0; j<8; j++){
        if(naves2[i][j]==1){
          naves[i][j+1]=1;
        }
    }
  }
}

//!----PINTAR MATRIZ 1 DE JUEGO----
void pintarCampoJuego1(){
  for (int i=0; i<8; i++){
    //habilitamos fila con HIGH
    digitalWrite(i+31, HIGH);
    for(int j=0; j<8; j++){
      if ((naves[i+3][j] == 1)){
        //encendemos led con LOW
        digitalWrite(j+41, LOW);
      }
    }
    delay(1);//después de pintar una fila completa esperamos un milisegundo
    digitalWrite(i+31, LOW);//desabilitamos fila con LOW
    for(int j=41; j<49; j++){
      digitalWrite(j, HIGH);//apagamos columnas con HIGH
    }
  }
  //Luego de pintar primera Matriz llamamos a pintar Segunda ya que el método es diferente
  pintarCampoJuego2();  
}

//!----PINTAR MATRIZ 2 DE JUEGO----
void pintarCampoJuego2(){
  //Se maneja columna fila por el recorrido de la matriz física
  //como la matriz está volteada si se están recorriendo por filas visualmente
  for (int columna = 0; columna <8; columna++){
    for(int fila = 0; fila <8; fila++){
      if((naves[columna+11][fila] == 1)){
        lc.setLed(0,fila,columna,true);
      }
    }
    delay(1);//despues de pintar la "fila visual" esperamos 1 milisegundo
    //la matriz2 se borra completa al cambiar la variable tiempo con el potenciometro
  }
}


//!----PINTAR MATRIZ 1 DE JUEGO----
void pintarCampoJuego1UYKIETO(){
  for (int i=0; i<8; i++){
    //habilitamos fila con HIGH
    digitalWrite(i+31, HIGH);
    for(int j=0; j<8; j++){
      if ((uyquieto[i+3][j] == 1)){
        //encendemos led con LOW
        digitalWrite(j+41, LOW);
      }
    }
    delay(1);//después de pintar una fila completa esperamos un milisegundo
    digitalWrite(i+31, LOW);//desabilitamos fila con LOW
    for(int j=41; j<49; j++){
      digitalWrite(j, HIGH);//apagamos columnas con HIGH
    }
  }
  //Luego de pintar primera Matriz llamamos a pintar Segunda ya que el método es diferente
  pintarCampoJuego2UYKIETO();  
}

//!----PINTAR MATRIZ 2 DE JUEGO----
void pintarCampoJuego2UYKIETO(){
  //Se maneja columna fila por el recorrido de la matriz física
  //como la matriz está volteada si se están recorriendo por filas visualmente
  for (int columna = 0; columna <8; columna++){
    for(int fila = 0; fila <8; fila++){
      if((uyquieto[columna+11][fila] == 1)){
        lc.setLed(0,fila,columna,true);
      }
    }
    delay(1);//despues de pintar la "fila visual" esperamos 1 milisegundo
    //la matriz2 se borra completa al cambiar la variable tiempo con el potenciometro
  }
}

//!█████████████████████████████████████ CORAZON █████████████████████████████████████████████
//!----CORAZON DEL JUEGO----
void juego2(int velocidad){
  
  if(digitalRead(btnpush) == LOW){ 
    velocidad = 80;
  }

  if (millis()-tiempoNaves > velocidad){//CONTROLA TIEMPO DE MOVIMIENTO
    moverMatrizNaves();
    comprobarChoques();
    tiempoNaves = millis();
    lc.clearDisplay(0);
  }

  pintarCampoJuego1();
  pintarCampoJuego1UYKIETO();
  validar_columnas();
  
  estadoBtnDer = digitalRead(btnder);
  estadoBtnIzq = digitalRead(btnizq);
  estadoBtnDisp = digitalRead(btndisp);

  //!EN CASO DE MOVIMIBENTO   = ABAJO
  if(estadoBtnDer == LOW){
    if((estadoBtnDer == LOW)&&(estadoAnteriorBtnDer == HIGH)){
      int flagtemp=1;
        //validacion de borde superior
        for(int i=0; i<19; i++){
          if(naves[i][0]==1){
            flagtemp=0;
          }
        }
        if (flagtemp!=0){ 
          moverdown();
          lc.clearDisplay(0);

          comprobarChoques();//COMPROBAMOS SI EXISTEN CHOQUES
        }
      }
    }

  //!EN CASO DE MOVIMIBENTO ARRIBA
  if(estadoBtnIzq == LOW){
    if((estadoBtnIzq == LOW)&&(estadoAnteriorBtnIzq == HIGH)){ 
      int flagtemp=1;
      //validacion de borde superior
      for(int i=0; i<19; i++){
        if(naves[i][7]==1){
          flagtemp=0;
        }
      }
      if (flagtemp!=0){
        moverup();
        comprobarChoques();//COMPROBAMOS SI EXISTEN CHOQUES
      }
      lc.clearDisplay(0);
      pintarCampoJuego1();
    }
  }

  //!EN CASO DE ROTACIONES
  if(estadoBtnDisp == LOW){
    if((estadoBtnDisp == LOW)&&(estadoAnteriorBtnDisp == HIGH)){ 
      int flagtemp=1;
      switch(figurarand){
        case 0: //! ☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻ PALITO ☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻
          if(rotacion==0){
            //************** ROTACION 0 ****************
              rotacion++;
              rotPalito1();
              comprobarChoques();//COMPROBAMOS SI EXISTEN CHOQUES
          }else if(rotacion == 1){
            //************** ROTACION 1 ****************
              rotPalito0();
                rotacion = 0;
          }
          break;
        case 2: //! ☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻ ELE ☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻
          if(rotacion==0){
            //************** ROTACION 0 ****************
              rotEle1();
              rotacion++;
              comprobarChoques();
          }else if(rotacion == 1){
            //************** ROTACION 1 ****************
              rotEle2();
                rotacion++;
          }else if(rotacion == 2){
            //************** ROTACION 2 ****************
              rotEle3();
                rotacion++;
          }else if(rotacion == 3){
            //************** ROTACION 3 ****************
              rotEle0();
                rotacion = 0; //regresa a su estado normal
          }
          break;
        case 1: //! ☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻ TRIANGULITO ☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻
          if(rotacion==0){//ayuda excel
            //************** ROTACION 0 ****************
              rotTrian1();
              rotacion++;
              comprobarChoques();
          }else if(rotacion == 1){
            //************** ROTACION 1 ****************
              rotTrian2();
                rotacion++;
          }else if(rotacion == 2){
            //************** ROTACION 2 ****************
              rotTrian3();
                rotacion++;
          }else if(rotacion == 3){
            //************** ROTACION 3 ****************
              rotTrian0();
                rotacion = 0; //regresa a su estado normal
          }
          break;
        case 3: //! ☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻ ZETA ☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻☻
          if(rotacion==0){//copiar rotacion como palito
            //************** ROTACION 0 ****************
              
              rotZeta0();
              rotacion++;
              comprobarChoques();
          }else if(rotacion == 1){
            //************** ROTACION 1 ****************
              rotZeta1();
                rotacion=0;
          }
          break;
        //! CASO 4 Y CASO 5   (CUADRADO Y PUNTITO NO ROTAN)
      }
      
      lc.clearDisplay(0);
      pintarCampoJuego1();

    }
  }
  //GUARDAMOS LOS ESTADOS DE LOS BOTONES PARA EL SIGUIENTE CICLO
  estadoAnteriorBtnDer = estadoBtnDer;
  estadoAnteriorBtnIzq = estadoBtnIzq;
  estadoAnteriorBtnDisp = estadoBtnDisp;
}




//!████████████████████████████████   PINTAR PUNTEOS   ██████████████████████████████████████████████████

//----PINTAR MATRIZ 1 DE NUMEROS----
void pintarNumeroMatriz1(int f){
  for (int i=0; i<8; i++){
    //habilitamos fila con HIGH
    digitalWrite(i+31, HIGH);
    for(int j=0; j<8; j++){
      switch(f){
        case 0:
          if (cero[i][j] == 1){
            //encendemos led con LOW
            digitalWrite(j+41, LOW);
          }
          break;
        case 1:
          if (uno[i][j] == 1){
            //encendemos led con LOW
            digitalWrite(j+41, LOW);
          }
          break;
        case 2:
          if (dos[i][j] == 1){
            //encendemos led con LOW
            digitalWrite(j+41, LOW);
          }
          break;
        case 3:
          if (tres[i][j] == 1){
            //encendemos led con LOW
            digitalWrite(j+41, LOW);
          }
          break;
        case 4:
          if (cuatro[i][j] == 1){
            //encendemos led con LOW
            digitalWrite(j+41, LOW);
          }
          break;
        case 5:
          if (cinco[i][j] == 1){
            //encendemos led con LOW
            digitalWrite(j+41, LOW);
          }
          break;
        case 6:
          if (seis[i][j] == 1){
            //encendemos led con LOW
            digitalWrite(j+41, LOW);
          }
          break;
        case 7:
          if (siete[i][j] == 1){
            //encendemos led con LOW
            digitalWrite(j+41, LOW);
          }
          break;
        case 8:
          if (ocho[i][j] == 1){
            //encendemos led con LOW
            digitalWrite(j+41, LOW);
          }
          break;
        case 9:
          if (nueve[i][j] == 1){
            //encendemos led con LOW
            digitalWrite(j+41, LOW);
          }
          break;
        default:
          Serial.println("NO SE RECONOCE EL NÚMERO");
          break;
      }

    }
    delay(1);//después de pintar una fila completa esperamos un milisegundo
    digitalWrite(i+31, LOW);//desabilitamos fila con LOW
    for(int j=41; j<49; j++){
      digitalWrite(j, HIGH);//apagamos columnas con HIGH
    }    
  }
}

//----PINTAR MATRIZ 2 DE NUMEROS----
void pintarNumeroMatriz2(int f){
  //Se maneja columna fila por el recorrido de la matriz física
  //como la matriz está volteada si se están recorriendo por filas visualmente
  for (int columna = 0; columna <8; columna++){
    for(int fila = 0; fila <8; fila++){
      switch(f){
        case 0:
          if(cero[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 1:
          if(uno[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 2:
          if(dos[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 3:
          if(tres[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 4:
          if(cuatro[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 5:
          if(cinco[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 6:
          if(seis[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 7:
          if(siete[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 8:
          if(ocho[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 9:
          if(nueve[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        default:
          
          Serial.println("NO SE RECONOCE EL NÚMERO");
          break;
      }
    }
    delay(1);//despues de pintar la "fila visual" esperamos 1 milisegundo
    //la matriz2 se borra completa al cambiar la variable tiempo con el potenciometro
  }
}


void pintarPunteo(){
  lc.clearDisplay(0);
  //punteo = 99;
  int decena = punteo/10;
  int unidad = punteo - (decena*10);
  if(decena>10){//si es mayor a 100 se arroja simbolo de interrogación
    pintarNumeroMatriz2(10);
    pintarNumeroMatriz1(10);
  }else{
    pintarNumeroMatriz2(unidad);
    pintarNumeroMatriz1(decena);
  }  
}
 
//!████████████████████████████████   PINTAR SIGUIENTE PIEZA   ██████████████████████████████████████████████████
//----PINTAR MATRIZ 1 DE NUMEROS----
void pintarPiezaMatriz1(int f){
  for (int i=0; i<8; i++){
    digitalWrite(i+31, HIGH);
    for(int j=0; j<8; j++){
      switch(f){
        case 100:
          if (ene[i][j] == 1){
            //encendemos led con LOW
            digitalWrite(j+41, LOW);
          }
          break;
        default:
          Serial.println("NO SE RECONOCE EL NÚMERO");
          break;
      }

    }
    delay(1);//después de pintar una fila completa esperamos un milisegundo
    digitalWrite(i+31, LOW);//desabilitamos fila con LOW
    for(int j=41; j<49; j++){
      digitalWrite(j, HIGH);//apagamos columnas con HIGH
    }    
  }
}

//----PINTAR MATRIZ 2 DE NUMEROS----
void pintarPiezaMatriz2(int f){
  //Se maneja columna fila por el recorrido de la matriz física
  //como la matriz está volteada si se están recorriendo por filas visualmente
  for (int columna = 0; columna <8; columna++){
    for(int fila = 0; fila <8; fila++){
      switch(f){
        case 0:
          if(Pieza0[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 1:
          if(Pieza1[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 2:
          if(Pieza2[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 3:
          if(Pieza3[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 4:
          if(Pieza4[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        case 5:
          if(Pieza5[columna][fila] == 1){
            lc.setLed(0,fila,columna,true);
          }
          break;
        default:
          break;
      }
    }
    delay(1);//despues de pintar la "fila visual" esperamos 1 milisegundo
    //la matriz2 se borra completa al cambiar la variable tiempo con el potenciometro
  }
}


void pintarSiguientePieza(){
  lc.clearDisplay(0);
  pintarPiezaMatriz2(piezaSiguiente);
  pintarPiezaMatriz1(100);
}


 
 
//!████████████████████████████████   PINTAR ERROR   ██████████████████████████████████████████████████

//----PINTAR MATRIZ 1 DE E----
void pintarErrorMatriz1(){
  for (int i=0; i<8; i++){
    digitalWrite(i+31, HIGH);
    for(int j=0; j<8; j++){
      if (E[i][j] == 1){ 
        digitalWrite(j+41, LOW);
      }
    }
    delay(1); 
    digitalWrite(i+31, LOW); 
    for(int j=41; j<49; j++){
      digitalWrite(j, HIGH); 
    }    
  }
}

//----PINTAR MATRIZ 2 DE E----
void pintarErrorMatriz2(){ 
  for (int columna = 0; columna <8; columna++){
    for(int fila = 0; fila <8; fila++){
      if(E[columna][fila] == 1){
        lc.setLed(0,fila,columna,true);
      }
    }
    delay(1); 
  }
}


void pintarError(){
  lc.clearDisplay(0);
  pintarErrorMatriz2();
  pintarErrorMatriz1();
}


//!████████████████████████████████   MAIN   ██████████████████████████████████████████████████
void loop() { 
  //MOSTRANDO MENSAJE 
  if (juegoEmpezado == 0)  {
    pintarNombres(analogRead(pot));
    esperarStar();

    // JUGANDO
  }else if (juegoEmpezado == 1){
    esperarStar();
    juego2(analogRead(pot2));

    // GAME OVER
    //! cuando termina el juego (tope limite derecho) "juegoEmpezado" debe de ser 3
  }else if (juegoEmpezado == 3){
    if (millis() - tiempoGameOver > 5000){
      digitalWrite(27, LOW); //! REINICIA LITERALMENTE EL ARDUINO
    }else{
      // pintarPunteo();
    }
    
    // JUEGO EN PAUSA
  }else if (juegoEmpezado == 2){ 
    esperarStar();
    turnar();
    // JUEGO EN MODO ERROR
  }else if (juegoEmpezado == 4){
    pintarError();
    if (digitalRead(boton) == LOW){ 
      juegoEmpezado = 1;
    } 
  }
}
