Curso C++: Eliminar Carpetas y Archivos

Curso C++: Eliminar Carpetas y Archivos

Eliminar directorios completos en C++ puede ser un reto, especialmente cuando se busca hacerlo de manera segura y eficiente. En este capítulo, les mostraré un código que permite eliminar archivos o directorios, incluyendo subcarpetas y archivos contenidos. Veremos cómo funciona y algunas consideraciones importantes.

Ejemplo de Código para Eliminar Carpetas Completas

A continuación, presentamos un código en C++ que permite eliminar archivos y carpetas. Este código está estructurado para manejar tanto archivos individuales como directorios con contenido.

#if !defined(KILLFOLDER_H__)
#define KILLFOLDER_H__

// Includes necesarios
#include <rc_class/msgbox.h>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;

// Definiciones de atributos de carpetas
#define FOLDER_NORMAL  (FILE_ATTRIBUTE_DIRECTORY)
#define FOLDER_WINSYS  (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN)
#define FOLDER_READONLY  (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY)
#define FOLDER_HIDDEN  (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN)
#define FOLDER_NOTMOVE  (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN)
#define FOLDER_COMPRESSED (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_COMPRESSED)
#define FOLDER_TEMP  (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_TEMPORARY)

// Mensajes de error
#define MSG_CAPTION   "Ha ocurrido un error"
#define MSG_ERROR_HANDLE "La dirección no es válida: \n%s"
#define MSG_ERROR_FILE  "El archivo %s está siendo utilizado por una aplicación externa.\nNo se puede continuar."

// Propiedades
#define ALLFILES "\\*.*" // Atributo: todos los archivos.
#define ROOTBACK ".."  // Carpeta superior.

class CKillFolder
{
private:
    HWND m_hWnd;
public:
    int Run(char*);
    CKillFolder(HWND hWndParent) { m_hWnd = hWndParent; };
};

int CKillFolder::Run(char* lpszInitPath)
{
    HANDLE hFile;
    BOOL bNextFile = true;
    WIN32_FIND_DATA tdataFind;
    string lpszTemp;
    vector<string> lpszDirectory;
    DWORD dwType;
    INT iPos;

    // Bloque A: Detecta si es archivo o carpeta
    dwType = GetFileAttributes(lpszInitPath);
    if (dwType != (dwType | FILE_ATTRIBUTE_DIRECTORY))
    {
        // Quita el atributo del archivo
        SetFileAttributes(lpszInitPath, (DWORD)0);
        // Intenta eliminar el archivo
        if (!DeleteFile(lpszInitPath))
        {
            MsgOut(m_hWnd, MB_ICONEXCLAMATION, MSG_ERROR_FILE, lpszInitPath);
            return 0;
        }
        return 1;
    }

    // Bloque B: Inicia la búsqueda de subcarpetas
    lpszDirectory.push_back(lpszInitPath);
    lpszDirectory[0] = lpszDirectory[0] + ALLFILES;

    iPos = 0;
    while (iPos < lpszDirectory.size())
    {
        hFile = FindFirstFile((char*)lpszDirectory[iPos].c_str(), &tdataFind);
        if (hFile == INVALID_HANDLE_VALUE)
        {
            MsgOut(m_hWnd, MB_ICONEXCLAMATION, MSG_CAPTION, MSG_ERROR_HANDLE, lpszDirectory[iPos].c_str());
            FindClose(hFile);
            return 0;
        }
        while (bNextFile == TRUE)
        {
            bNextFile = FindNextFile(hFile, &tdataFind);
            if (bNextFile && strcmp(tdataFind.cFileName, ROOTBACK))
            {
                switch (tdataFind.dwFileAttributes)
                {
                    case FOLDER_NORMAL:
                    case FOLDER_HIDDEN:
                    case FOLDER_WINSYS:
                    case FOLDER_READONLY:
                    case FOLDER_COMPRESSED:
                    case FOLDER_TEMP:
                    case FOLDER_NOTMOVE:
                        lpszTemp = lpszDirectory[iPos].substr(0, lpszDirectory[iPos].length() - 3) + tdataFind.cFileName + ALLFILES;
                        lpszDirectory.push_back(lpszTemp);
                        break;
                    default:
                        // Bloque D: Elimina el archivo
                        lpszTemp = lpszDirectory[iPos].substr(0, lpszDirectory[iPos].length() - 3) + tdataFind.cFileName;
                        SetFileAttributes((LPCTSTR)lpszTemp.c_str(), (DWORD)0);
                        if (!DeleteFile((LPCTSTR)lpszTemp.c_str()))
                        {
                            MsgOut(m_hWnd, MB_ICONEXCLAMATION, MSG_ERROR_FILE, tdataFind.cFileName);
                            FindClose(hFile);
                            return 0;
                        }
                        break;
                }
            }
        }
        FindClose(hFile);
        bNextFile = true;
        iPos = iPos + 1;
    }

    // Bloque E: Elimina subcarpetas encontradas
    while (iPos > 0)
    {
        iPos = iPos - 1;
        lpszTemp = lpszDirectory[iPos].substr(0, lpszDirectory[iPos].length() - 4);
        RemoveDirectory((char*)lpszTemp.c_str());
    }
    return 1;
}

#endif // _KILLFOLDER_

Explicación del Código

Este código define una clase CKillFolder con el objetivo de eliminar un archivo o una carpeta con todo su contenido. Aquí se presentan las funciones principales y cómo trabajan:

  1. Detección de Archivos y Carpetas: Utilizando GetFileAttributes, se identifica si la ruta proporcionada corresponde a un archivo o una carpeta.

  2. Eliminación de Archivos: Los archivos se eliminan después de cambiar sus atributos para que no sean de solo lectura. Si el archivo está en uso, muestra un mensaje de error.

  3. Búsqueda y Eliminación de Subcarpetas: Utiliza FindFirstFile y FindNextFile para recorrer las subcarpetas y almacenar sus rutas en un vector. Los archivos dentro de las carpetas se eliminan primero, y luego se elimina la carpeta.

Consideraciones Importantes

  • Archivos en Uso: El código no puede eliminar archivos que estén siendo utilizados por otra aplicación. Esto es importante, ya que evita errores críticos.

  • Manejo de Errores: Se muestra un cuadro de diálogo si algo falla durante la eliminación, lo cual es útil para depurar problemas comunes.

  • Eficiencia: Aunque este método es eficaz para eliminar archivos y carpetas, no es necesariamente el más rápido, especialmente cuando hay muchas subcarpetas y archivos.

Mejoras Potenciales

  • Manejo de Excepciones: El código actual depende de retornos numéricos para manejar errores, una posible mejora sería usar excepciones para un manejo más robusto de errores.

  • Compatibilidad Multiplataforma: Actualmente, este código solo funciona en entornos Windows. Adaptarlo para ser multiplataforma podría ser una mejora significativa.

  • Paralelismo: Para mejorar la eficiencia, se podrían ejecutar las eliminaciones en paralelo usando std::thread o similar.

Conclusión

Eliminar archivos y directorios completos en C++ no es una tarea trivial, especialmente cuando queremos hacerlo de manera segura y eficiente. Este ejemplo proporciona una base sólida para manejar este proceso, pero siempre se pueden hacer mejoras para aumentar la robustez y eficiencia del código. Recuerda siempre probar bien el código en un entorno controlado antes de implementarlo en situaciones críticas.

Curso C++: Codificación de Huffman

Curso C++: Codificación de Huffman

La codificación de Huffman es un algoritmo utilizado en la compresión de datos para minimizar el tamaño de los archivos. En este post, presentamos una implementación de la codificación de Huffman en C++. A continuación, se explica el código y se detallan algunos aspectos importantes para mejorar su eficiencia y facilidad de uso.

Implementación del Código en C++

#include <iostream>
#include <vector>
#include <limits.h>
using namespace std;

const int maxsize = 100;
const int null = 0;

struct huff_node
{
    char symbol;
    int freq;
    huff_node *parent;
    char childtype;
};

typedef huff_node *ptr;
ptr node[maxsize];

void create(int k);
void print(int k);
void twosmall(ptr &p, ptr &q, int numnode);

int main()
{
    int numsymbols;
    ptr p, q, r;

    cout << "Introduce el numero de simbolos: ";
    cin >> numsymbols;

    for (int i = 0; i < numsymbols; i++)
        create(i);

    for (int j = numsymbols; j < 2 * numsymbols - 1; j++)
    {
        r = new huff_node;
        node[j] = r;
        r->parent = nullptr;
        twosmall(p, q, j);
        p->parent = r;
        q->parent = r;
        p->childtype = 'L';
        q->childtype = 'R';
        r->symbol = ' ';
        r->freq = p->freq + q->freq;
    }

    cout << endl << "Simbolo *-------* Codigo: " << endl;
    for (int k = 0; k < numsymbols; k++)
        print(k);

    return 0;
}

void create(int k)
{
    ptr t = new huff_node;
    cout << "Introduce el simbolo numero " << k + 1 << ": ";
    cin >> t->symbol;
    cout << "Introduce su frecuencia: ";
    cin >> t->freq;
    t->parent = nullptr;
    node[k] = t;
}

void print(int k)
{
    ptr t = node[k];
    vector<char> code;

    while (t->parent != nullptr)
    {
        if (t->childtype == 'L')
            code.push_back('0');
        else
            code.push_back('1');
        t = t->parent;
    }

    cout << t->symbol << " - ";
    for (auto it = code.rbegin(); it != code.rend(); ++it)
        cout << *it;
    cout << endl;
}

void twosmall(ptr &p, ptr &q, int numnodes)
{
    int min1 = INT_MAX;
    int min2 = INT_MAX;
    p = nullptr;
    q = nullptr;

    for (int i = 0; i < numnodes; i++)
    {
        if (node[i]->parent == nullptr)
        {
            if (node[i]->freq < min1)
            {
                min2 = min1;
                min1 = node[i]->freq;
                q = p;
                p = node[i];
            }
            else if (node[i]->freq < min2)
            {
                min2 = node[i]->freq;
                q = node[i];
            }
        }
    }
}

Explicación del Código

  1. Definiciones y Estructuras: Se define la estructura huff_node para representar un nodo del árbol de Huffman. Cada nodo tiene un símbolo (symbol), una frecuencia (freq), un puntero a su padre (parent) y un indicador del tipo de hijo (childtype).

  2. Función create: Esta función permite crear los nodos iniciales con el símbolo y la frecuencia proporcionada por el usuario. Almacena estos nodos en el arreglo node.

  3. Algoritmo de Huffman: En el main, se construye el árbol de Huffman. Cada vez que se seleccionan los dos nodos con las frecuencias más bajas (función twosmall), se crea un nodo padre para combinarlos.

  4. Función twosmall: Busca los dos nodos con la frecuencia más baja que no tengan un padre asignado, lo cual es esencial para construir el árbol de Huffman.

  5. Función print: Muestra el código de Huffman de cada símbolo. Para cada nodo, recorre el árbol hacia arriba hasta la raíz para determinar su representación en binario.

Mejoras Realizadas

  • Actualización de Bibliotecas: Se reemplazó la biblioteca #include <iostream.h> por #include <iostream>, eliminando también el uso de #include <conio.h> que no es necesario.

  • Uso de nullptr: Se cambió null por nullptr para una mejor compatibilidad con C++ moderno.

  • Uso de vector para el Código: Se reemplazó el arreglo char code[10] por un vector<char>, lo cual hace que el código sea más seguro y flexible.

  • Constantes Adecuadas: Se reemplazó 9999 por INT_MAX para una mejor comprensión y para seguir las mejores prácticas de C++.

Conclusión

La codificación de Huffman es una técnica poderosa para la compresión de datos. Este ejemplo en C++ nos muestra cómo implementar el árbol de Huffman y generar los códigos para cada símbolo en función de su frecuencia. Aunque este es un ejemplo básico, proporciona una buena base para entender cómo funcionan los algoritmos de compresión.

Agenda de Contactos en C++: Gestión de Registros con Archivos Binarios y CSV

Agenda de Contactos en C++: Gestión de Registros con Archivos Binarios y CSV

Este programa escrito en C++ permite gestionar una agenda de contactos completa. Puedes dar de alta, modificar o eliminar registros, y ordenar la información por nombre, apellidos, o edad. Los datos se almacenan en un archivo binario y se pueden exportar en formato CSV para facilitar su uso con otras aplicaciones.

Una gran ventaja de este programa es su compatibilidad con Linux, aunque en Windows se debe quitar la función sleep() para un funcionamiento adecuado. En este post, exploraremos cómo se organiza este programa y cómo puedes usarlo para manejar tus propios registros.

Funcionalidades del Programa

Este programa te permite realizar las siguientes operaciones sobre una agenda:

  1. Agregar Registros: Puedes agregar nuevos contactos a la agenda, incluyendo información como nombre, apellidos, edad, teléfono, dirección, etc.

  2. Eliminar Registros: Puedes eliminar registros específicos por su clave.

  3. Modificar Registros: Actualiza cualquier dato de un registro existente.

  4. Ordenar Registros: Ordena la agenda por nombre, apellidos, edad o calle.

  5. Mostrar Todos los Registros: Muestra la lista completa de registros.

  6. Exportar a CSV: Guarda los registros en un archivo CSV para compartir o analizar en otras aplicaciones.

Estructura del Código

Vamos a explorar la estructura del código de manera resumida para entender mejor cómo funcionan las funciones principales:

1. Definiciones y Estructura Principal

El código comienza definiendo las librerías necesarias y la estructura principal agenda. Esta estructura contiene todos los campos relevantes de un contacto, como su nombre, teléfono y dirección:

#define FICHERO "datos"
#define MAX 25

FILE *fichero;

struct agenda {
    int clave;
    char nom[20];
    char ApPat[15];
    char ApMat[15];
    int edad;
    long int tel;
    long int cel;
    char calle[15];
    char col[15];
    char mun[15];
    char estado[15];
    int sw;
    char mail[25];
} r[MAX];

Esta estructura se usará para almacenar y manejar los datos de cada contacto.

2. Apertura del Archivo

La función apertura() es responsable de abrir el archivo binario que almacena los registros. Si el archivo no existe, lo crea:

void apertura(void) {
    if ((fichero = fopen(FICHERO, "r+")) == NULL)
        fichero = fopen(FICHERO, "w");
}

3. Menú Principal

El programa presenta un menú de opciones para el usuario. Esto le permite navegar por las distintas funcionalidades disponibles:

int menu(void) {
    int opmenu = 0;
    printf("\nMENU\n");
    printf("1) Agregar\n2) Borrar\n3) Buscar\n4) Mostrar Todos\n5) Ordenar Archivo\n6) Listar\n7) Modificar Registro\n8) Exportar\n9) Salir\n");
    printf("Opcion: ");
    scanf("%d", &opmenu);
    return opmenu;
}

4. Agregar un Registro

La función agregar() permite al usuario agregar un nuevo registro al archivo binario. Primero se verifica si la clave ya está en uso, luego se solicita al usuario que ingrese los datos del contacto:

void agregar(void) {
    int clave;
    struct agenda registro, aux;

    clavesdisponibles();
    do {
        printf("Dame tu clave: ");
        scanf("%d", &clave);
        if (clave > MAX) {
            printf("Tu clave debe ser menor que %d\n", MAX);
        }
        aux = ReadToDisk(clave);
        if (aux.sw == 1) {
            printf("La clave ya está en uso\n");
        }
    } while (clave > MAX || aux.sw == 1);

    // Resto del código para ingresar datos...
}

5. Mostrar Todos los Registros

La función m_todo() lee todos los registros del archivo y los muestra en pantalla. Es útil para visualizar la agenda completa de contactos:

void m_todo(void) {
    int i = 2;
    struct agenda registro;
    registro = ReadToDisk(1);
    do {
        if (registro.sw == 1)
            mostrar(registro);
        registro = ReadToDisk(i);
        i++;
    } while (!feof(fichero));
}

6. Exportar a CSV

Finalmente, la función exportar() permite al usuario guardar todos los registros en un archivo CSV. Esto facilita el compartir o analizar los datos en aplicaciones como Excel:

void exportar(void) {
    FILE *archivo;
    char nombre[20];
    int c, i;
    c = ReadAllToDisk();
    OrdenaOnMemory(c, 1);
    printf("Nombre del Archivo: ");
    scanf("%s", nombre);
    archivo = fopen(nombre, "w");

    for (i = 0; i < c; i++) {
        fprintf(archivo, "%d,%s,%s,%s,%d,%ld,%ld,%s,%s,%s,%s,%s\n", r[i].clave, r[i].nom, r[i].ApPat, r[i].ApMat, r[i].edad, r[i].tel, r[i].cel, r[i].calle, r[i].col, r[i].mun, r[i].estado, r[i].mail);
    }
    fclose(archivo);
}

Código Completo

#include <stdio.h>
#include <string.h>
#define FICHERO "datos"
#define MAX 25
#define ESCAPE ((char)27)

FILE *fichero;

struct agenda {
    int clave;
    char nom[20];
    char ApPat[15];
    char ApMat[15];
    int edad;
    long int tel;
    long int cel;
    char calle[15];
    char col[15];
    char mun[15];
    char estado[15];
    int sw;
    char mail[25];
} r[MAX];

// Declaración de prototipos de funciones
int menu(void);
void agregar(void);
void mostrar(struct agenda);
void buscarnom(char[]);
void buscaredad(int);
void apertura(void);
void m_todo(void);
void borrar(int);
void borrartodo(void);
void ordena(void);
void SaveToDisk(struct agenda);
struct agenda ReadToDisk(int);
int ReadAllToDisk(void);
void OrdenaOnMemory(int, int);
void clavesdisponibles(void);
void actualizar(struct agenda, int);
void exportar(void);

int main() {
    int op;
    apertura();

    while ((op = menu()) != 9) {
        switch (op) {
            case 1:
                agregar();
                break;
            case 2:
                int clave;
                printf("Dame la clave a borrar: ");
                scanf("%d", &clave);
                borrar(clave);
                break;
            case 3:
                // Código para buscar registros
                break;
            case 4:
                m_todo();
                break;
            case 5:
                ordena();
                break;
            case 6:
                // Código para listar registros
                break;
            case 7:
                // Código para modificar registros
                break;
            case 8:
                exportar();
                break;
            default:
                printf("Opción no válida. Intente nuevamente.\n");
        }
    }

    fclose(fichero);
    return 0;
}

Cosas a Tener en Cuenta

  • Compatibilidad con Sistemas Operativos: Este código funciona perfectamente en Linux, pero si se usa en Windows, hay que quitar la función sleep() para evitar problemas.

  • Archivos Binarios vs. Archivos de Texto: La información se guarda en un archivo binario para mantener la estructura compacta y evitar la manipulación directa, pero se proporciona una opción de exportación en CSV para un formato más amigable.

Mejoras Futuras

  • Mejorar la Interfaz de Usuario: Podría beneficiarse de una interfaz más moderna, quizá utilizando una biblioteca gráfica para ofrecer menús más intuitivos.

  • Agregar Validaciones de Datos: Incluir validaciones adicionales para asegurarse de que la información proporcionada sea correcta y evitar registros con datos inconsistentes.

  • Optimizar el Manejo de Archivos: Podría mejorarse la forma en que se leen y escriben los registros, quizá mediante el uso de punteros inteligentes y gestión de errores más robusta.

Conclusión

Este programa de gestión de agenda en C++ demuestra cómo gestionar eficientemente la información personal de los contactos utilizando archivos binarios. Aunque tiene un enfoque clásico y puede beneficiarse de mejoras modernas, es un excelente punto de partida para cualquiera que quiera aprender sobre manejo de archivos en C++.

¡Prueba el código y modifica la agenda según tus necesidades! Con algunos cambios, podría ser la base de una aplicación de gestión personal mucho más amplia.

Pruebas PacMan

Primeras pruebas a color del juego del Comecocos. Sólo está implementado el movimiento del PacMan comiendo los círculos y las frutas y el paso de un lado al otro por el pasillo. Faltan los fantasmas y la dinámica de persecución y choques... 
Desarrollado para LINUX en Code::Blocks. No os correrá correctamente en Wine...
///Carrega de llibreries
#include<stdio.h>
#include<stdlib.h>
#include <termios.h>

static struct termios old, new;

///variables globals
int punts=0,vides=2,nivell=1,atac=0;
int matriu[24][28]={
35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,
35,46,46,46,46,46,46,46,46,46,46,46,46,35,35,46,46,46,46,46,46,46,46,46,46,46,46,35,
35,67,35,35,35,35,46,35,35,35,35,35,46,35,35,46,35,35,35,35,35,46,35,35,35,35,67,35,
35,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,35,
35,46,35,35,35,35,46,35,35,46,35,35,35,35,35,35,35,35,46,35,35,46,35,35,35,35,46,35,
35,46,46,46,46,46,46,35,35,46,46,46,46,35,35,46,46,46,46,35,35,46,46,46,46,46,46,35,
35,35,35,35,35,35,46,35,35,35,35,35,32,35,35,32,35,35,35,35,35,46,35,35,35,35,35,35,
32,32,32,32,32,35,46,35,35,32,32,32,32,32,32,32,32,32,32,35,35,46,35,32,32,32,32,32,
32,32,32,32,32,35,46,35,35,32,35,35,35,32,32,35,35,35,32,35,35,46,35,32,32,32,32,32,
35,35,35,35,35,35,46,35,35,32,35,32,32,32,32,32,32,35,32,35,35,46,35,35,35,35,35,35,
101,32,32,32,32,32,46,32,32,32,35,32,32,32,32,32,32,35,32,32,32,46,32,32,32,32,32,101,
35,35,35,35,35,35,46,35,35,32,35,32,32,32,32,32,32,35,32,35,35,46,35,35,35,35,35,35,
32,32,32,32,32,35,46,35,35,32,35,35,35,35,35,35,35,35,32,35,35,46,35,32,32,32,32,32,
32,32,32,32,32,35,46,35,35,32,32,32,32,32,32,32,32,32,32,35,35,46,35,32,32,32,32,32,
35,35,35,35,35,35,46,35,35,32,35,35,35,35,35,35,35,35,32,35,35,46,35,35,35,35,35,35,
35,46,46,46,46,46,46,46,46,46,46,46,46,35,35,46,46,46,46,46,46,46,46,46,46,46,46,35,
35,46,35,35,35,35,46,35,35,35,35,35,46,35,35,46,35,35,35,35,35,46,35,35,35,35,46,35,
35,67,46,46,35,35,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,35,35,46,46,67,35,
35,35,35,46,35,35,46,35,35,46,35,35,35,35,35,35,35,35,46,35,35,46,35,35,46,35,35,35,
35,46,46,46,46,46,46,35,35,46,46,46,46,35,35,46,46,46,46,35,35,46,46,46,46,46,46,35,
35,46,35,35,35,35,35,35,35,35,35,35,46,35,35,46,35,35,35,35,35,35,35,35,35,35,46,35,
35,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,35,
35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35};
int X,Y,V,Z;
int punts,vides,nivell;

/// Declaració de funcions
/* Initialize new terminal i/o settings */
void initTermios(int echo){
  tcgetattr(0, &old); /* grab old terminal i/o settings */
  new = old; /* make new settings same as old settings */
  new.c_lflag &= ~ICANON; /* disable buffered i/o */
  new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */
  tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */
}
/* Restore old terminal i/o settings */
void resetTermios(void){
  tcsetattr(0, TCSANOW, &old);
}
/* Read 1 character - echo defines echo mode */
char getch_(int echo){
  char ch;
  initTermios(echo);
  ch = getchar();
  resetTermios();
  return ch;
}
/* Read 1 character without echo */
char getch(void){
  return getch_(0);
}
/* Read 1 character with echo */
char getche(void){
  return getch_(1);
}
/* Funció que reemplaça el gotoxy de conio.h */
void gotoxy(int x, int y){
    printf("%c[%d;%df",0x1B,y,x);
}
/* Funció que reemplaça l'ordre delay o retard */
void delay(int del){
    int c,d;
    for (c=1;c<= del;c++) {
        for (d=1;d <=del;d++){
        }
    }
}
/* Funció per presentar la pantalla */
void mostra(){
int i,j;

for(i=0;i<24;i++){
        printf("ntt");
        for(j=0;j<28;j++){
            if(matriu[i][j]==35){
                printf("e[104m e[0m");
            }
            if(matriu[i][j]==46){
                printf("e[96m*e[0m");
            }
            if(matriu[i][j]==64){
if(atac>0){
printf("e[5me[93m@e[0m");
                }
                else{
printf("e[93m@e[0m");
                }
            }
            if(matriu[i][j]==111){
                printf(" ");
            }
            if(matriu[i][j]==32||matriu[i][j]==101){
                printf(" ");
            }
            if(matriu[i][j]==67){
                printf("e[96m█e[0m");
            }
        }
    }
    gotoxy(49,2);
    printf("e[93m+---------------+e[0m");
    gotoxy(49,3);
    printf("e[93m│   COMECOCOS   │e[0m");
    gotoxy(49,4);
    printf("e[93m+---------------+e[0m");
    gotoxy(49,5);
    printf("Punts:  %d",punts);
    gotoxy(49,6);
    printf("Vides:  %d",vides);
    gotoxy(49,7);
    printf("Nivell: %d",nivell);
    gotoxy(49,10);
    printf("e[90mPosició X=%d Y=%de[0m",X,Y);
    gotoxy(49,11);
    printf("e[90mCaracter: %ce[0m",matriu[X][Y]);
    gotoxy(100,29);
}
/* Funcio dreta */
void dreta(){

    if(matriu[X][Y+1]!=35){
        system("clear");
        if(matriu[X][Y+1]==46){
            punts++;
        }
        if(matriu[X][Y+1]==67){
            atac=1;
            punts=punts+10;
        }
        matriu[X][Y+1]=matriu[X][Y];
        matriu[X][Y]=32;
        Y++;
        if(matriu[10][27]==64){
            matriu[10][27]=32;
            matriu[10][0]=64;
            X=10;
            Y=0;
            atac=0;
        }
        mostra();
    }

}
/* Funcio esquerra */
void esquerra(){
    if(matriu[X][Y-1]!=35){
        system("clear");
        if(matriu[X][Y-1]==46){
            punts++;
        }
        if(matriu[X][Y-1]==67){
            atac=1;
            punts=punts+10;
        }
        matriu[X][Y-1]=matriu[X][Y];
        matriu[X][Y]=32;
        Y--;
        if(matriu[10][0]==64){
            matriu[10][0]=32;
            matriu[10][27]=64;
            X=10;
            Y=27;
            atac=0;
        }
        mostra();
    }
}
/* Funcio adalt */
void adalt(){
    if(matriu[X-1][Y]!=35){
        system("clear");
        if(matriu[X-1][Y]==46){
            punts++;
        }
        if(matriu[X-1][Y]==67){
            atac=1;
            punts=punts+10;
        }
        matriu[X-1][Y]=matriu[X][Y];
        matriu[X][Y]=32;
        X--;
        mostra();
    }
}
/* Funcio baix */
void baix(){
    if(matriu[X+1][Y]!=35){
        system("clear");
        if(matriu[X+1][Y]==46){
            punts++;
        }
        if(matriu[X+1][Y]==67){
            atac=1;
            punts=punts+10;
        }
        matriu[X+1][Y]=matriu[X][Y];
        matriu[X][Y]=32;
        X++;
        mostra();
    }
}
/* Funció MAIN del programa */
int main(void){
int i,j,x,y,m;
char opcio;

X=13;Y=14;
matriu[X][Y]=64;
    mostra();
    while(opcio!='q'&&opcio!='Q'){
        opcio=getch();///scanf("%c",&opcio);
        switch(opcio){
        case 'd':
            dreta();
        break;
        case'C':
            dreta();
        break;
        case 'e':
            esquerra();
        break;
        case'D':
            esquerra();
        break;
        case 'a':
            adalt();
        break;
        case'A':
            adalt();
        break;
        case 'b':
            baix();
        break;
        case'B':
            baix();
        break;
        }
    }
    return 0;
}