Public Group

# Console Menu Structure - How to get node type

## Recommended Posts

Posted (edited)

This is just a part of the standard C++ convention, but it's still useful in your case.

Quote

How should I actually get the type of my MenuItem? Lets say I want to find the options SubMenu and add some ActionItems at runtime

Also you should probably use objects than just pointers to objects in a vector<> . This way you reduce memory usage and a vector actually cleans itself automatically when out of range.

This could lead to loss of pointers, which can bring to confusion as smarter pointers are defined as "better"("smarter") by C++ standard than new and delete.

Smart pointers prevent you from having too many pointers with complicated connections across data structures(functions). Also they are always automatically deleted when completely out of scope.

Nodes are parts of a linked list, so you should make a link list structure(just a match map in Unreal Tournament 2004 - Onslaught mode).
A node represents a part of a linked list, but it is also a building block of a linked structure.

Linked nodes in the aforementioned Onslaught mode work independently. They are linked to each other, but each of them contains their own independent information.

Nodes connect between each other, they check other nodes like connected to other nodes. However, making such a structure can very expensive what regards implementation time investment and RAM usage.

So my suggestion would be, use the independence of each node. So whenever a node's link has changed, only the array of connections is changed, meaning before the connected node, it was set from one third note

If both second and third are connected to the first node, you would apply the same process as the third node is independent as well.

I have tried this: (personal preference, but I'm making a menu system in my console-text game myself) :P

main.cpp

int main()
{

for (;;)
{

{
break;
}
}
}

#include <iostream>
#include <vector>

{
std::vector<std::string> options;
int id{ 0 };						//sort through
int target_id{ 0 };
};

#pragma once

{
static bool exit;

int current_target{ 0 };

};

I would do this:(in your case)

Basically you get the Node name, by sorting through using its private: data identifier and once you get the correct ID,
take the std::string from the Node which contains the node's name.

Edited by Acosix

##### Share on other sites
7 minutes ago, Acosix said:

This could lead to loss of pointers, which can bring to confusion as smarter pointers are defined as "better"("smarter") by C++ standard than new and delete.

Smart pointers prevent you from having too many pointers with complicated connections across data structures(functions). Also they are always automatically deleted when completely out of scope

First things first: Ofc you cant know it but the code I used in my example is just a quick "expression of my thoughts". I´m aware of possible memory leaks and that I should use smart pointers instead of raw pointers ^^

10 minutes ago, Acosix said:

I have tried this: (personal preference, but I'm making a menu system in my console-text game myself) :P

Maybe I do not quite understand your code or how it translates to my problem but I think it´s not far away from registering an enum or am unique identifier in the ctor of my classes and give me the right type back based on these "tags". On the other hand I could use your "Linked List approach" then I could say: A Submenu can have a parent (if its nullptr then I know I´m at the root level) AND a Submenu can have either a pointer to another Submenu OR a pointer to an ActionItem. Thus I only have to check which pointer is not a nullptr.

##### Share on other sites
Posted (edited)
1 hour ago, Geosesarma said:

Maybe I do not quite understand your code or how it translates to my problem but I think it´s not far away from registering an enum or am unique identifier in the ctor of my classes and give me the right type back based on these "tags". On the other hand I could use your "Linked List approach" then I could say: A Submenu can have a parent (if its nullptr then I know I´m at the root level) AND a Submenu can have either a pointer to another Submenu OR a pointer to an ActionItem. Thus I only have to check which pointer is not a nullptr.

What I presented in my approach is naming / getting a node.by using an enum (or string in my case).

In most cases an ActionItem is just a target to another specific menu. When it comes to selecting profile and such, you just use a class Profile and ProfileHandler.

So you would basically get the NodeType the same way. You can use action items as I described ActionItem:

This would be the code in which I actually suggested for you(not only what I have tried):

ActionItem.h

#include "nodetypes.h"
class ActionItem
{
//basically two types of action items: a node which switches to another(true)
//and a node which makes extra data handling(false)

console_game::All_Node_Types selected_node_type;

void tranlate_from_file(ActionItemData& data);
//this then loads an action item from a file
};

nodetypes.h

namespace console_game
{
enum class All_Node_Types
{
//...
};
}

Node.h

#include "NodeType.h"
#include <string>

class Node
{
//what I just called "menu option"

NodeType type;

std::string node_name;
};

NodeType.h

#include "ActionType.h"

class NodeType
{
ActionItem a;
};

main.cpp

#include "Node.h"

int main()
{
//load node names and types; and ActionItems from files or source code
}
Quote

Ofc you cant know it but the code I used in my example is just a quick "expression of my thoughts".

I still don't like exemplary code, other than pseudo-code. It is hard to understand and read to me.

Edited by Acosix

##### Share on other sites
Posted (edited)

To get a NodeType then:

-you define nodes or in the main() or load them from a file in the start of the main function

-load the NodeType when you need it

class ActionItemData
{
std::string file_name;
};

//main.cpp example

#include "Node.h"

void getNodeType(NodeType& set_type, console_game::All_Node_Types& result)
{
{
}
else
{
result = set_type.selected_node_type;
}
}

int main()
{
Node a1;
NodeType type;
ActionItem a_item;

ActionItemData data;
data.file_name="C:\\data.txt";

type.a=a_item;

console_game::All_Node_Types final_result;

getNodeType(type, final_result);
}

Edited by Acosix

##### Share on other sites

If S2 exists (and you draw it so it's likely there), then I don't see why it should not be trusted. You could add submenus too at runtime, probably with a (skip adding if it already exists), to avoid all kinds of mess if two new actions both need the same submenu.

A different approach is to skip drawing empty submenus (as well as submenus that contain only empty submenus, recursivley). Then you could add the entire submenu structure you ever need in advance. One step further, if you add all actions as well, with a flag "don't show", you don't need to add actions in runtime either (other than clearing the flag).

##### Share on other sites

What I provided was just a sample code. Just rename "Node" into "Submenu"

My point is I use composition ( building objects from other objects ) over inheritance whenever possible, especially over polymorphism.

If you really want to use polymorphism though:

class MenuItem {
public:
virtual void action() = 0;
virtual string& getItemName() = 0;
}

class ActionItem : public MenuItem {
public:
void action() override {
//Trigger stuff
}
string& getItemName() {
return itemName;
}
}

public:
void action() override {
//The problem is here. You are adding an action, even though a submenu item
//doesn't have an "action" where you trigger something.	It just switches to

//Also you have only two types of menu items, and probably won't have more
//than that if I got you.

//An ActionItem actually does work outside of the scope of the menu system
//operating(like selecting an option).

//So it's confusing.

}
string& getItemName() {
return itemName;
}

{
//Here the problem arises, you can switch menus this way by just
//setting the target ID and the current ID

the source of the problem is you should have provided us with ChildItems,
in this case menu options(note: not game options)

a submenu doesn't exactly have an action item...a node therefore isn't an

a node should be a child item of a submenu
}

};


What I wanted to show you in the "Node" code is a node should be actually a child option.

All in all, I think this is the easiest way to solve your problem:

class ChildItem: public MenuItem
{
void action() override
{
//check if the child item needs an ActionItem
//or if just switches the SubMenuItems to be displayed
}
};

private:
vector<ChildItem*> childItems;
public:
void action() override {
//display childItems
}
string& getItemName() {
return itemName;
}
};

What is ItemName used for? Name of the submenu?

##### Share on other sites

If you insist on trying a node to be a MenuItem and not a menu option; you could try this:

class MenuItem {
public:
virtual void action() = 0;
virtual string& getItemName() = 0;
virtual const char* getType() = 0;
};

class SubMenuItem
{
private:
public:
void action() override {
//What to do?
}
string& getItemName() {
return itemName;
}

virtual const char* getType() pverride
{
}
};

class ActionItem : public MenuItem {
public:
void action() override {
//Trigger stuff
}
string& getItemName() {
return itemName;
}
virtual const char* getType() pverride
{
}
}

main.cpp

#include <iostream>

int main()
{
std::cout << "MenuItem type is " << m_1.getName();
}

##### Share on other sites

Correction for the previous above post main.cpp:

std::cout << "MenuItem type is " << m_1.getType();

##### Share on other sites
Posted (edited)

Maybe I should be more precise in what I want to achieve.

First things first: I´m only interessted in building the menu structure (no navigating or drawing logic).

A ActionItem is just a class, which triggers a function/an event.

Another class, maybe MenuNavigator should be able to iterate through the Menu. It also should be able to keep the current state (current selected, current SubmenuItem ect). Navigation could look like this: Player presses arrow down: cursor gets one "MenuItem" down. Player presses arrow up: cursor gets one "MenuItem" up. Player presses X: if current selected MenuItem is a SubmenuItem set its childs as the current "Submenu", if current selected MenuItem is an ActionItem, trigger a function/ an event.

7 hours ago, Acosix said:

What is ItemName used for? Name ﻿of the submen﻿﻿u?﻿﻿

It´s just a name which should be displayed (like the windows filesystem -> a folder(=SubmenuItem) has a name, a file(=ActionItem) has a name )

Maybe I should just store pointers from classes which I want to use in a "Menu" class and use them directly.

Edited by Geosesarma

##### Share on other sites
Posted (edited)
Quote

A container class would something like this:

class MenuItem
{
int type_ID{0};
public:
int getType_ID();

};

#include "MenuItem.h"
#include <vector>

{
int fixed_set{0};
int current_index{o};
public:

{
}

{
}
};

#include "SubmenuItem.h"

{
setType();
}

MenuNavigator.h

//and then just use:

{
public:

{
action_call=1,
root=2,
//...
}

//possible applications:

{
//finds the first of a type

{
{
return iterator;
}
}

return 0;
}

{
//finds all of the same type, stops after finding 5th menu item

int results{0};

for(int iterator{1};(iterator<=loop_box.getSubMenuSize() && iterator <= 5);iterator+=1)
{
results+=1;
}

return results;
}
};

main.cpp

#include "MenuNavigator.h"

int main()
{

//possible use:

//the 1 here means action call
int first_index{ E.loop_findFirstType(D, 1)};

//here it means finding the node type
//this should return 1(searching index result) as MenuItem

//a is the first added MenuItem which has type 1

The problem is how you define a MenuItem container.

Edited by Acosix

• 18
• 18
• 11
• 21
• 16