Graphics Menu in c++ - c++

I am working on a project and I want to make a Graphics Menu. Issue which I am facing is that after it shows any text written in the function I've put in switch. it goes back to main menu. I want to make a function which stays on new function and once it directs to new function, It has nothing to do with main menu anymore. Until this function is called again.
I want it to be a simple menu function which directs me to function. Nothing else.
your help would mean allot!
Thanks in advance.
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<iomanip>
#include<fstream>
#include<windows.h>
using namespace std;
int main() {
system("cls");
string Menu[3] = { " Admin", " Customer", " Exit" };
int pointer = 0;
bool flag=true;
while (flag==true)
{
system("cls");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
cout << "Main Menu\n\n";
for (int i = 0; i < 3; ++i)
{
if (i == pointer)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 11);
cout << Menu[i] << endl;
}
else
{
SetConsoleTextAttribute ( GetStdHandle ( STD_OUTPUT_HANDLE), 15);
cout << Menu[i] << endl;
}
}
while (true)
{
if (GetAsyncKeyState(VK_UP) != 0)
{
pointer =pointer-1;
if (pointer == -1)
{
pointer = 2;
}
break;
}
else if (GetAsyncKeyState(VK_DOWN) != 0)
{
pointer += 1;
if (pointer == 3)
{
pointer = 0;
}
break;
}
else if (GetAsyncKeyState(VK_RETURN) != 0)
{
switch (pointer)
{
case 0:
{
admin_login();
Sleep(500);
break;
}
case 1:
{
customer_sign();
Sleep(500);
break;
}
case 2:
{
thank_you();
Sleep(800);
break;
}
default:
{
cout<<"Invalid Input! ";
}
}
}
}
Sleep(150);
}
return 0;
}

Your 'flag' boolean needs to be checked as the condition for both while loops, not just the first one. You also need to clear the console when you press enter on a menu selection.
Inside your switch case after detecting key press, in each case you need to set your flag boolean to false so you stop drawing the main menu, and instead start drawing the sub menus. I don't have access to your other functions so here is a solution emulating that behaviour in a simplified and minimal reproducible proof of concept:
#include<windows.h>
#include <iostream>
using namespace std;
int main()
{
system("cls");
string Menu[3] = { " Admin", " Customer", " Exit" };
int pointer = 0;
bool bMainMenu = true;
while (bMainMenu)
{
system("cls");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
cout << "Main Menu\n\n";
for (int i = 0; i < 3; ++i)
{
if (i == pointer)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 11);
cout << Menu[i] << endl;
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
cout << Menu[i] << endl;
}
}
while (bMainMenu)
{
if (GetAsyncKeyState(VK_UP)&1)
{
pointer = pointer - 1;
if (pointer == -1)
{
pointer = 2;
}
break;
}
else if (GetAsyncKeyState(VK_DOWN)&1)
{
pointer += 1;
if (pointer == 3)
{
pointer = 0;
}
break;
}
else if (GetAsyncKeyState(VK_RETURN)&1)
{
switch (pointer)
{
case 0:
{
//admin_login();
system("cls");
std::cout << "admin selected\n";
Sleep(1000);
bMainMenu = false;
break;
}
case 1:
{
//customer_sign();
system("cls");
std::cout << "customer selected\n";
Sleep(1000);
bMainMenu = false;
break;
}
case 2:
{
//thank_you();
system("cls");
std::cout << "thank you selected\n";
Sleep(1000);
bMainMenu = false;
break;
}
default:
{
cout << "Invalid Input! ";
}
}
}
}
Sleep(150);
}
return 0;
}

Related

Switch cases and getch() don't work together

I've done a pretty simple switch where if I press a character, the integer of it adds one to itself and prints a message, it worked pretty fine with the "cin>>" and the "getchar()", but when I added the getch, It still prints the message but it stops updating the integer "how I know"? cause I made a random value that the integer has to get to, and it's between 1 and 20, and with the getch it simply goes on without stopping itself when arrived to the value
'''
void Journ(char const *bypassto = "x")
{
int m = 4;
int VAL[m];
for (int j=0; j<m; j++)
{
VAL[j] = rand()%20 + 1;
}
char comm;
int W;
int A;
int S;
int D;
char journkey;
if (bypassto != "x" ) {
journkey = *bypassto;
} else {
cout << "Choose a direction: \n";
cout <<"[FOWARD]-[LEFT]-[RIGHT]-[BACKWARDS]\n";
cout << "w for foward - a for left - d for right - s for backwards \n";
}
while (comm!=4)
{
// cin >> comm;
comm = getch();
switch(comm)
{
case 'w':
{
cout << "You went foward. \n";
W++;
break;
}
case 'a':
{
cout << "You went left. \n";
A++;
break;
}
case 's':
{
cout << "You went backwards. \n";
S++;
break;
}
case 'd':
{
cout << "You went right. \n";
D++;
break;
}
}
if(W == VAL[0])
{
BattleIntro();
break;
}
else if(A == VAL[1])
{
BattleIntro();
break;
}
else if(S == VAL[2])
{
BattleIntro();
break;
}
else if(D == VAL[3])
{
BattleIntro();
break;
}
}
}
'''

C++ with menu system: How to eliminate input buffers when pressing arrow keys

I was able to make a program that has a menu on it. At first, the program is running smoothly. The problem starts to appear when, at a certain point in the program, the user starts inputting something and then navigating the menus again.
Sometimes it will print out integers/characters that were previously entered by the user when pressing the ENTER key in the menu.
I managed to block the inputs with cin.ignore(). But how can I eliminate the display of the (I don't know if its excess or garbage) inside the input buffer whenever the user presses the LEFT and RIGHT arrow keys? Or I think there's even one for UP and DOWN arrow key?
int main()
{
color(FG_WHITE);
bool progFinished = false;
while (!progFinished) {
cout << "[ACTIVITY FOR 26 FEBRUARY 2018]\n";
vector<string> menu = { "Currency Converter","Student Information System" };
int choice = menu_std(menu, FG_YELLOW, false);
bool currencyFinished = false;
bool studentFinished = false;
switch (choice) {
case 0:
while (!currencyFinished) {
cout << "\n\n[CURRENCY CONVERT]\n";
vector<string> curr_menu = { "PHP TO OTHERS","USD TO PHP","YEN TO PHP","EUR TO PHP","BHD TO PHP" };
int currency = menu_std(curr_menu, FG_YELLOW, false);
double value = validation("\nEnter the value", 0, false);
CurrencyConverter convert(currency, value);
cout << "\n\nConvert again? ";
currencyFinished = !menu_yn(FG_YELLOW);
}
system("cls");
break;
case 1:
Studentv2 stud;
stud.LoadFile();
while (!studentFinished) {
cout << "\n\n[STUDENT INFO SYSTEM]\n";
vector<string> stud_menu = { "Add Student","View All Students" };
int stud_choice = menu_std(stud_menu, FG_YELLOW, false);
switch (stud_choice) {
case 0:
stud.AddStudent();
cout << "\n\nDo you want to continue with the Student Info System? ";
stud.SaveFile();
studentFinished = !menu_yn(FG_YELLOW);
break;
case 1:
stud.DisplayStudentInformation();
cout << "\n\nDo you want to continue with the Student Info System? ";
studentFinished = !menu_yn(FG_YELLOW);
break;
}
}
system("cls");
break;
}
cout << "\nContinue using the program? ";
progFinished = !menu_yn(FG_YELLOW);
system("cls");
}
cout << "Press any key to exit.\n";
cin.get();
return 0;
}
Code snippets for some of the functions I used inside my program.
Function menu_std():
int menu_std(std::vector<std::string> &menu, WORD atrribute, bool argument)
{
sleep_for(milliseconds(150));
int elements = menu.size();
int elements_max_size = menu.size() - 1;
int menu_position = 0;
COORD position = getcoordinates();
while (true) {
for (int i = 0; i < elements; i++) {
move(position.X, position.Y + i);
if (i == menu_position) {
color(atrribute);
std::cout << menu[i];
color(FG_WHITE);
}
else {
std::cout << menu[i];
}
}
while (true) {
if (GetAsyncKeyState(VK_UP) < 0 && menu_position != 0) {
menu_position--;
break;
}
if (GetAsyncKeyState(VK_DOWN) < 0 && menu_position != elements_max_size) {
menu_position++;
break;
}
if (GetAsyncKeyState(VK_RETURN) < 0) {
std::cin.ignore(10000, '\n');
if (argument == true) {
sleep_for(milliseconds(100));
COORD previous = getcoordinates();
std::cout << "\n\nAre you sure? ";
bool sure = menu_yn(atrribute);
if (sure) {
clear_output(previous);
return menu_position;
}
else {
clear_output(previous);
break;
}
}
else {
return menu_position;
}
}
sleep_for(milliseconds(50));
}
sleep_for(milliseconds(175));
}
}
Function menu_yn():
bool menu_yn(WORD attribute)
{
sleep_for(milliseconds(150));
COORD currentpos = getcoordinates();
int pos = 0;
while (true) {
move(currentpos);
switch (pos) {
case 0:
color(attribute);
std::cout << "YES";
color(FG_WHITE);
std::cout << " NO";
break;
case 1:
std::cout << "YES";
color(attribute);
std::cout << " NO";
color(FG_WHITE);
break;
}
while (true) {
if (GetAsyncKeyState(VK_RIGHT) < 0 && pos != 1) {
pos++;
break;
}
if (GetAsyncKeyState(VK_LEFT) < 0 && pos != 0) {
pos--;
break;
}
if (GetAsyncKeyState(VK_RETURN) < 0) {
std::cin.ignore(10000, '\n');
if (pos == 0) {
return true;
}
else if (pos == 1) {
return false;
}
}
}
sleep_for(milliseconds(175));
}
}
Function validation()
double validation(std::string question, double limit, bool argument)
{
double userInput;
while (true) {
std::cout << question << " >> ";
while (!(std::cin >> userInput)) {
std::cout << "Error: Non-integer input. " << question << " >> ";;
std::cin.clear();
std::cin.ignore(256, '\n');
}
std::cin.ignore(10000, '\n');
while (userInput > limit && limit != 0) {
std::cout << "Error: Input out-of-bounds. " << question << " >> ";
std::cin >> userInput;
std::cin.ignore(10000, '\n');
}
if (argument) {
return (userInput <= 0) ? 1 : userInput;
}
else {
return userInput;
}
}
}
Screenshot of the problem:
There are numbers appearing whenever I press enter on the menu. I suspect that it comes whenever the user presses the arrow keys before entering the enter.

Error with getch()

void move_player(int& x, int& y) {
int old_x, old_y, new_x, new_y;
switch (getch()) {
case 0x31: // miscare stanga
if (current_x>min_x) {
old_x=x;
new_x=x-1;
if (y==1) {
path[1][old_x]=' ';
path[1][new_x]=player;
system("cls");
for (int y=0;y<3;y++) {
for (int x=0;x<20;x++) {
cout << path[y][x];
}
cout << endl;
}
} else if (y==2) {
path[2][old_x]='_';
path[2][new_x]=player;
system("cls");
for (int y1=0;y1<3;y1++) {
for (int x1=0;x1<20;x1++) {
cout << path[y1][x1];
}
cout << endl;
}
}
}
break;
case 0x32:
if (x<max_x) {
old_x=current_x;
new_x=current_x+1;
if (y==1) {
path[1][old_x]=' ';
path[1][new_x]=player;
system("cls");
for (int y2=0;y2<3;y2++) {
for (int x2=0;x2<20;x2++) {
cout << path[y2][x2];
}
cout << endl;
}
} else if (y==2) {
path[2][old_x]='_';
path[2][new_x]=player;
system("cls");
for (int y3=0;y3<3;y3++) {
for (int x3=0;x3<20;x3++) {
cout << path[y3][x3];
}
cout << endl;
}
}
}
break;
case 0x33:
if (y>min_y) {
old_y=y;
new_y=y-1;
path[old_y][x]='_';
path[new_y][x]=player;
system("cls");
for (int y4=0;y4<3;y4++) {
for (int x4=0;x4<20;x4++) {
cout << path[y4][x4];
}
cout << endl;
}
}
break;
case 0x34:
if (y<max_y) {
old_y=y;
new_y=y+1;
path[old_y][x]=' ';
path[new_y][x]=player;
system("cls");
for (int y5=0;y5<3;y5++) {
for (int x5=0;x5<20;x5++) {
cout << path[y5][x5];
}
cout << endl;
}
}
}
x=new_x;
y=new_y;
}
This is the function for moving a player in a two dimensional space.
It is represented by an array which I declared as char path[3][20] and the player can only move in path[1][20] or path[2][20]. The first layer of the array is just represented by a bunch of lines, kind of setting the boundaries for the map. Btw, the player starts at path[2][0] or lower left corner.
(I can't move it left or down in the starting position, only right or up)
The problem is, that when I run this, I can move it fine just once right, but then when I try it to move left or right it does nothing, and when I try to move it up or down the console just frezees and it quits.
How can I solve it?

Check out my C++ Scrolling Menu and give any tips

Right now I have a working scrolling menu, I just wanted to ask if there is anyone to give tips how to compact this because it's a bit "CHUNKY"!
Also I have two extra questions: How can I change it for my
"Rock,
Paper,
Scissors"
to be displayed like "Rock, Paper", Scissors"? If you try out my code, you'd see the text is all vertical, can I make it all horizontal? And is there any tips how to make it into a void statement to be used multiple times?
#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
int main()
{
string Menu[3] = {"Rock", "Paper", "Scissors"};
int pointer = 0;
while(true)
{
system("cls");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
cout << "Main Menu\n\n";
for (int i = 0; i < 3; ++i)
{
if (i == pointer)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 11);
cout << Menu[i] << endl;
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
cout << Menu[i] << endl;
}
}
while(true)
{
if (GetAsyncKeyState(VK_UP) != 0)
{
pointer -= 1;
if (pointer == -1)
{
pointer = 2;
}
break;
}
else if (GetAsyncKeyState(VK_DOWN) != 0)
{
pointer += 1;
if (pointer == 3)
{
pointer = 0;
}
break;
}
else if (GetAsyncKeyState(VK_RETURN) != 0)
{
switch (pointer)
{
case 0:
{
cout << "\n\n\nStarting new game...";
Sleep(1000);
} break;
case 1:
{
cout << "\n\n\nThis is the options...";
Sleep(1000);
} break;
case 2:
{
return 0;
} break;
}
break;
}
}
Sleep(150);
}
return 0;
}
There's a bunch of different ways you could go about this. I'd prefer to go about it a different way in my own code,but have tried to write something that was as close to your own code as I could at this hour of the day.
You can re-use the same function for any menu that needs displaying - just give it a different value for the list of strings and the count of the number of strings in that array. Even better - use a std::vector<string>.
Rather than hard-code the number of menu items in the main function, I work it out by taking the total size of the array of strings and dividing it by the size of the first element. Since each element gives the same value for sizeof regardless of the length of the string, this allows you to calculate the number of elements in the array. Note though - this trick won't work inside of the getUserChoice function though - by that time, the array had been degraded to a pointer and the function has no way of telling how many items are in the array, unlike main - that's why I calculate the number there. Using a vector of strings would be much cleaner, since you could just pass a reference to the vector to the function, then inside the function you could call the .size() method of the vector to get the number of items it contains. Probably a little in front of where you're up to just now, hence the code in a similar style to your own.
Hope its helpful. :)
#include <iostream>
#include <string>
#include <windows.h>
using namespace std;
int getUserChoice(string *items, int numItems)
{
int curSel = 0, textAttrib;
bool selectionMade = false, needsUpdate = true; // we want to clearscreen first time through
while (!selectionMade)
{
// only redraw the screen if something has changed, or we're on the first iteration of
// our while loop.
if (needsUpdate)
{
system("cls");
needsUpdate = false;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
cout << "Main Menu" << endl;
cout << "(navigate with arrow keys, select with enter)" << endl << endl;
for (int i=0; i<numItems; i++)
{
if (i == curSel)
textAttrib = 11;
else
textAttrib = 15;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), textAttrib);
if (i)
cout << " ";
cout << items[i];
}
}
if (GetAsyncKeyState(VK_LEFT) != 0)
{
curSel--;
needsUpdate = true;
}
else if (GetAsyncKeyState(VK_RIGHT) != 0)
{
curSel++;
needsUpdate = true;
}
else if (GetAsyncKeyState(VK_RETURN) != 0)
selectionMade = true;
if (curSel < 0)
curSel = numItems-1;
else if (curSel > (numItems-1) )
curSel = 0;
Sleep(100);
}
char dummy[10];
cin.getline(dummy, 10); // clear the enter key from the kbd buffer
return curSel;
}
int main()
{
string Menu[] = {"Rock", "Paper", "Scissors"};
int selection;
selection = getUserChoice(Menu, sizeof(Menu)/sizeof(Menu[0]) );
cout << "You chose: " << Menu[selection] << endl;
}

Checking if a string matches "END", and exit if it does

I have the following code below:
int main ()
{
char string[80];
bool Restart;
Restart = true;
while (Restart)
{
cout << "Enter a string\n" << endl;
cin.getline(string, 80);
cout << "\nYou entered: ";
printf(string, 80);
cout << endl;
int len=strlen(string);
bool flag = true;
for (int c=0; c!=len/2; c++)
{
if (flag)
{
if(string[c] != string[len-c-1])
{
flag = false;
}
}
else
{
break;
}
}
if (flag)
{
cout <<"\nThis is a Palindrome\n" << endl;
Restart = true;
continue;
}
else
{
cout << "\nThis is not a palindrome\n" << endl;
Restart = true;
continue;
}
cin.get();
}
}
I need to figure out a way to check if what the user entered is "END" in all caps, and if so, exit the program. I'm sure i can handle the exiting part, but I'm having trouble getting something that will check if the string entered is "END" in all caps.
Here is a solution that will terminate the while loop if "END" is entered. Create a helper method to do the parsing for END. Note this is very specific to the problem and not very reusable. It also is more difficult to maintain unlike Beta's solution, but you don't need to worry about maintenance until you start writing bigger programs.
bool Terminate(char* string, int len)
{
bool retval = false;
char* c = string;
if( 3 == len ) // "END\0"
{
if('E' == string[0])
{
if('N' == string [1])
{
if('D' == string[2])
{
retval = true;
}
}
}
}
return retval;
}
Then use it after int len=strlen(string); like so:
if(Terminate(string, len))
{
break; // Exit while loop
}
Make sure you declare Terminate before your main function
Is this enough of a hint?
#include <iostream>
int main()
{
char A[] = "END";
char B[10];
std::cin >> B;
std::cout << strcmp(A,B) << std::endl;
return(0);
}