Selector de opciones (consola)

Iniciado por ivancea96, 25 Julio 2014, 18:40 PM

0 Miembros y 2 Visitantes están viendo este tema.

ivancea96

Hola a todos. Hace mucho que no hago alguna aportación por aquí, y por cutre que sea, voy a poner un selector de opciones, en el que no hay que elegir el número de la opción, sinó hay que mover el marcador con W y S. Bueno, aquí va:

Código (cpp) [Seleccionar]
#include <iostream>
#include <vector>
#include <conio.h>
using namespace std;

class options{
    vector<string> _options;
    string _title;

    void coutTitle()const{
        if(_title.size()==0) return;
        vector<string> v;
        string t = _title;
        while(t.size()>80){
            v.push_back(t.substr(0,80));
            t.erase(0,80);
        }
        v.push_back(t);
        while(v.size()>1){
            cout << v[0];
            v.erase(v.begin());
        }
        cout << string((80-v[0].size())/2,' ') << v[0] << endl << endl;
    }

public:
    options(){}
    options(string title):_title(title){}
    options(const options& o):_options(o.getOptions()),_title(o.getTitle()){}
    void setTitle(string title){
        _title = title;
    }
    string getTitle()const{
        return _title;
    }
    vector<string> getOptions()const{
        return _options;
    }
    string getOption(size_t i)const{
        if(i<_options.size()) return _options[i];
        return "";
    }
    void addOption(string option){
        _options.push_back(option);
    }
    void addOptions(const vector<string>& v){
        for(int i=0; i<v.size(); i++)
            _options.push_back(v[i]);
    }
    void setOptions(const vector<string>& v){
        _options = v;
    }
    int show()const{
        int index = 0;
        char c = 0;
        while(c!='\r' && c!='\n'){
            system("cls");
            coutTitle();
            for(int i=0; i<_options.size(); i++){
                cout << '[' << (i==index?'X':' ') << "] " << _options[i] << endl;
            }
            c = getch();
            if((c=='w' || c=='W') && index>0)
                --index;
            if((c=='s' || c=='S') && index<_options.size()-1)
                ++index;
        }
        return index;
    }
};

int main(){
    options op;
    op.setTitle("Que querrias ser en otra vida?");
    op.addOption("Un Dios.");
    op.addOption("Un gobernador.");
    op.addOption("Un pensador.");
    op.addOption("Un trabajador.");
    op.addOption("Un esclavo.");
    cout << endl << endl << op.show();
}


Se le pone un titulo, se le agregan las opciones, y se invoca .show(). Show retorna el índice de la opcion elegida.


Utilizo la función system("cls") y getch(). Quién las quiera cambiar por otras, es libre de hacerlo, este código no tiene copyright xD

Usé getch() de conio.h porque es la más rápida y sencilla.

Jeje esto lo hice hace unos 4 años, pero lo hice a lo cutre con 2 solas opciones (y me costó). Ahora, años después, he visto lo terriblemente sencilo que es jaja.

"Una vez más, la experiencia marca la aptitud."

Saludos, espero que a alguien le sea útil :p

Baal_30

No entiendo ni la mitad :/ Pero muy interesante el aporte ¡! Gracias por compartirlo ;)
«La suerte es el cuidado de los detalles». -Winston Churchill

ivancea96

La mitad son simples getters y setters. El resto, es el cout de las opciones.

Mmm me diste la idea de colgarlo en mi blog xDD

leosansan

Cita de: ivancea96 en 25 Julio 2014, 18:40 PM
Hola a todos. Hace mucho que no hago alguna aportación por aquí, y por cutre que sea, voy a poner un selector de opciones, en el que no hay que elegir el número de la opción, sinó hay que mover el marcador con W y S. Bueno, aquí va:
..........................................................................
Utilizo la función system("cls") y getch(). Quién las quiera cambiar por otras, es libre de hacerlo, este código no tiene copyright xD

Usé getch() de conio.h porque es la más rápida y sencilla.

Jeje esto lo hice hace unos 4 años, pero lo hice a lo cutre con 2 solas opciones (y me costó). Ahora, años después, he visto lo terriblemente sencilo que es jaja.

"Una vez más, la experiencia marca la aptitud."

Saludos, espero que a alguien le sea útil :p

;-) ;-) ;-)

Antes que nada un fuerte saludo ivancea96 y gracias por el aporte.

Bueno, ya que no tiene "copyright" espero que no te moleste que lo modifique un poco.

El objetivo es no usar conio.h y su acólita getch, en su defecto sí windows. h  :rolleyes:  y se controla el menú con las teclas de flechas UP y DOWN y por cierto, incluyo la librería cstdlib que se te paso  ;) . También uso una nueva variable "tam" para que no me dé warnings por comparar signed ("i", index"") con unsigned ("_options.size()") y ya de paso enumero las opciones:  :o

Código (cpp) [Seleccionar]
#include <iostream>
#include <vector>
#include <cstdlib>
#include <windows.h>
using namespace std;
int gotoxy(int x, int y);

class options{
    vector<string> _options;
    string _title;

    void coutTitle()const{
        if(_title.size()==0) return;
        vector<string> v;
        string t = _title;
        while(t.size()>80){
            v.push_back(t.substr(0,80));
            t.erase(0,80);
        }
        v.push_back(t);
        while(v.size()>1){
            cout << v[0];
            v.erase(v.begin());
        }
        cout << string((80-v[0].size())/2,' ') << v[0] << endl << endl;
    }

public:
    options(){}
    options(string title):_title(title){}
    options(const options& o):_options(o.getOptions()),_title(o.getTitle()){}
    void setTitle(string title){
        _title = title;
    }
    string getTitle()const{
        return _title;
    }
    vector<string> getOptions()const{
        return _options;
    }
    string getOption(size_t i)const{
        if(i<_options.size()) return _options[i];
        return "";
    }
    void addOption(string option){
        _options.push_back(option);
    }
    void addOptions(const vector<string>& v){
        for(size_t i=0; i<v.size(); i++)
            _options.push_back(v[i]);
    }
    void setOptions(const vector<string>& v){
        _options = v;
    }
    int show()const{
        int index = 0;
        while(1){
            gotoxy (0,1);
            Sleep(100);
            //system("cls");
            coutTitle();
            int tam=_options.size();
            char indice ;
            for(int i=0; i<tam; i++){
                indice =  i+'0';
                cout << '[' << (i==index?'X':indice) << "] " << _options[i] << endl;
            }
            if(GetAsyncKeyState(VK_UP) && index>0){
              --index;
            }
            else if(GetAsyncKeyState(VK_UP) && index==0){
              index=_options.size()-1;
            }
            else if(GetAsyncKeyState(VK_DOWN) && index<tam-1){
              ++index;
            }
            else if(GetAsyncKeyState(VK_DOWN) && index==tam-1){
              index=0;
            }
            else if (GetAsyncKeyState(VK_RETURN)){
              cin.get();
              return index;
            }
        }
    }
};

int main(){
    options op;
    op.setTitle("Que querrias ser en otra vida?");
    op.addOption("Un Dios.");
    op.addOption("Un gobernador.");
    op.addOption("Un pensador.");
    op.addOption("Un trabajador.");
    op.addOption("Un esclavo.");
    cout << endl << endl << op.show();

}

int gotoxy(int x, int y){
  COORD coord;
  HANDLE h_stdout;
  coord.X = x;
  coord.Y = y;
  if ((h_stdout = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE)
    return 0;
  if (SetConsoleCursorPosition(h_stdout, coord) == 0)
    return 0;
  return 1;
}


Espero que no te disguste la modificación.  ;) ;) ;)

¡¡¡¡ Saluditos! ..... !!!!



ivancea96

No puse el índice porque la finalidad de este selector era que el usuario no necesitase saber de numeritos xD

Y la cstdlib no la puse porque no la requería xD

leosansan

Cita de: ivancea96 en 25 Julio 2014, 21:17 PM
............................................................
Y la cstdlib no la puse porque no la requería xD

En mi caso está de más ya que uso windows.h, pero en tu caso ""creo" que es necesaria para el uso de "system":

Código (cpp) [Seleccionar]
error: 'system' was not declared in this scope

Pero es sólo una opinión, no quiero que te molestes por una nimiedad como ésta.  ;) ;)

Lo realmente importante es que es una aportación interesante. Me obligas a meterme de lleno en las "clases" de C++.

¡¡¡¡ Saluditos! ..... !!!!



ivancea96

<iostream> ya me incluye el system.

Ahora estaba pensando en mostrar las opciones en una cuadrícula de 3xN. A ver si lo planteo. Hacer esta clase no me supo a nada xD

leosansan

Cita de: ivancea96 en 25 Julio 2014, 22:21 PM
<iostream> ya me incluye el system.
......................................................

No lo dudo pero el error que te comenté en el anterior mensaje es lo que me indica a mí Code::Blocks, no así el Dev-C++.  :o

Como se trata de un aporte, que no hacer una tarea, espero que el moderador de turno no se tome a mal mi siguiente aportación, pequeña y humilde que no soy un experto en estas lides, y no la borre.  ;D

Y es que los seguidores de C nos quedamos si no desvalidos ya que la mayor parte de los portes son en C++.

En esencia es la misma propuesta de ivancea96, por no variar el tema, sólo que al ser en C hago uso de arrays en lugar de Clases. Nos movemos en el menú con las flechas UP y DOWN y se selecciona la opción con la flecha RIGHT. El menú se muestra en color invertido y a cada respuestas le corresponde un color diferente.   ;)

Código (cpp) [Seleccionar]
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

void contraste ( int abajo ) ;
int gotoxy ( int x , int y ) ;
void Respuesta ( int Abajo ) ;

void color ( int n ) ;

const char *pregunta_respuesta [] = {
  "1. Un Dios." ,       "*** Piensas a lo Grande ***" ,
  "2. Un gobernador." , "*** Deseas Poder ***" ,
  "3. Un pensador." ,   "*** Eres Sabio ***" ,
  "4. Un trabajador." , "*** Menudo Currante estas hecho ***" ,
  "5. Un esclavo." ,    "*** Eres Servil ***"
  };

const int Color[] = { 30 , 62 , 181 , 45 , 123 } ;

int main (){
  int i , abajo = 0 ;
  puts ( "Que querrias ser en otra vida?" ) ;
  for ( i = 0 ; i < 9 ; i += 2){
    puts ( pregunta_respuesta [i] );
  }
  gotoxy (0,1);
  while (1)    {
    contraste ( abajo ) ;
    if ( abajo > 4 ){
      gotoxy (0,1) ;
      abajo = 0 ;
    }
    else if ( abajo < 0 ){
      gotoxy (0,5);
      abajo = 4 ;
    }
    else if (GetAsyncKeyState(VK_ESCAPE))
      {gotoxy (0,5);system("pause"); return 1;}

    else if (GetAsyncKeyState(VK_DOWN)){
      contraste ( abajo );
      gotoxy (0,abajo+1);
      abajo++;
      Sleep(100);
    }
    else if (GetAsyncKeyState(VK_UP)){
      contraste ( abajo );
      gotoxy (0,abajo-1);
      contraste ( abajo);
      abajo--;
      Sleep(100);
    }
    else  if (GetAsyncKeyState(VK_RIGHT)){
      Respuesta ( abajo ) ;
      break ;
    }
  }
  system ("pause");
  return 0;
}

int gotoxy(int x, int y){
  COORD coord;
  HANDLE h_stdout;
  coord.X = x;
  coord.Y = y;
  if ((h_stdout = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE)
    return 0;
  if (SetConsoleCursorPosition(h_stdout, coord) == 0)
    return 0;
  return 1;
}

void color (int n){
        SetConsoleTextAttribute(GetStdHandle (STD_OUTPUT_HANDLE), n );
}

void contraste (int abajo){
  int i ;
  color (7) ;
  gotoxy (0,0);
  puts ("Que querrias ser en otra vida?");
  for ( i = 0 ; i < 9 ; i+= 2){
    color ( abajo == i / 2 ? 112 : 7 ) ;
    puts ( pregunta_respuesta [i] );
  }
  color ( 7 ) ;
  gotoxy (0,abajo-1);
  Sleep(100);
}

void Respuesta ( int Abajo ){
  system ( "cls" ) ;
  gotoxy (0,0) ;
  color ( Color[Abajo] ) ;
  puts ( pregunta_respuesta [2 * Abajo + 1] ) ;
  color ( 7 ) ;
}


¡¡¡¡ Saluditos! ..... !!!!




ivancea96

Podrías convertirlo a una función del tipo:

int menu(char* titulo, char** opciones, int nOpciones);

Para poder reusarla más que nada xD

Y cabe decir, que yo también uso C::B. Es tema del MinGW usado.