I'm trying to increase the ease of use of my project at work. I'm a test engineer, not a programmer. The creator won't give me any source files and said if I had ideas to forward them to him and he will code it. Well, I have a lot of time and I want to learn how my project works under the hood and also save him time. I'll start out by saying I know next to nothing about C++ and honestly don't want to learn an entire language to fix this one issue.
The base functions are load() and start(). There are multiple games on 15 racks.
For instance, if I want to load game3 on rack 2, the current "call" is game3_rack2_.load(); and game3_rack2_.start()
Basically, I want the user to select the rack and game. I'm not super concerned with the game part, but let's say the user inputs rack 6 and this 6 is stored to variable num. Is there a simple way to do game3_rack<num>_.load() and game3_rack<num>_.start() ? I could use if statements, but with the amount of games/racks and multiple calls per game/rack, it seems unfeasible. In another language we have (native to company), the above case works. The variable is evaluated before the statement is executed. I think this is known as reflection? but I'm not entirely sure.
Can I utilize a basic array?
game3[N] {game3_rack0_, game3_rack1_, game3_rack2,...game3_rackN};
then just call the user input?
num = 2; //user wants rack 2
game3[num].load(); game3[num].start(); //loads and starts game3_rack2_
Thanks in advance and apologies for my poor understanding of C++.
Related
I do have a 2D game server written in C++ that can host up to 1000 players (that limit is because of map size, not by a performance by any means).
It's optimization and so is more-or-less great, as it was written by some really good developers.
What I am now trying to do, is to attach logging for each and every player. I do want to log such actions like:
Move things within, talks, die, login and so on and so on (so basically not everything, but fairly bit of what the player is doing)
I am not having problem programming-wise, rather I do lack knowledge about how to (performance) handle it and if my attempt is any good. What I am trying to do right now is:
I, for some reason, thought that it would be good to have each player log save to different files using ofstream.open. (I do believe that's an actually bad idea, but (1.) is it really? (2.) And why is it so? (3.) Can it handle up to 1000 files open?) I do have a class LoggingPlayer; on player login, I create an instance of this class and follow players actions by sending information to logging function.
I do save write to file when the buffer's full. I do close file only when player logs-off.
If I lose file - that's not the big deal, really. If the server crashes or slows for few seconds - that's a big deal for me.
I do have a few questions regarding:
(4.) How can I make it better? (e.g. using one logger for all players? log in one file?)
(5.) Should I totally abandon trying to make my own logger and try the already existing ones?
(5a.) If so, what are the recommendations for such a case? (online with 500-1000 users). I heard about boost log, but never tried.
I do appreciate all the help; so if you know the answer just for the one question, please don't hesitate.
I'm not even sure if my plan for doing things is the best way, so I apologize if this post is a bit vague. Also, I understand that similar questions have been asked before. However, I haven't been able to find anything that pertained to my situation and that made sense to me.
So me and my friends from school are building arcade machine, and I'm planning on putting together the main GUI that allows the user to select different games and load them if they have enough tokens. However, these separate windows will have to share some variables, mainly the number of tokens in the machine. I figured a separate Lua program could store such variable, and also have requests sent to it to perform other functions like opening and closing the different windows. Also, in case it's important to note, we will be using the Love2D engine for the games and be running all this on a Linux machine.
By what I've read, there seems to be some C and C++ code involved in this. I know next to nothing about C or C++, and we're trying to get this project moving along, so if you could include some code in your answer and instruct me on how to use it, that'd would be amazing. I can come back later and learn some C or C++, but right now Lua is my top priority.
My questions:
Is there a better way to accomplish what I'm trying to do?
How should I go about doing this?
Can this be done solely with Lua, or is some C, C++, or any other external programming language/utility/etc. required?
Also, incase anyone brings it up, I have tried using global variables, but I couldn't seem to get two programs/scripts to use the same variable at once.
Again, sorry if I'm being a bit vague.
Thanks in advance!
(this method is a combination of #Puzzlem00n's suggestion and reading the comments, so I shouldn't take much credit from this at all)
Putting multiple games in one lua program!
In main.lua:
require("spaceInvaders") --require all the other Lua files
-- without the ".lua" at the end!
gamestate=spaceInvaders
function love.load()
--all the setup things
end
function love.update()
gamestate.update()
end
function love.draw()
gamestate.draw()
end
function love.keypressed(key)
gamestate.keypressed(key)
end
--and so on for the rest of the love callbacks that you need (such as love.keyreleased())
Then in each game (which is a separate Lua file such as spaceInvaders.lua):
spaceInvaders = {}
function spaceInvaders.draw()
--your draw code
end
function spaceInvaders.update()
--your update code
end
--and so on for every other callback you want to use
What this code does is it gives each game its own set of love functions. When you want to play that game, you should set gamestate to that game's name. The spaceInvaders={} line defines spaceInvaders as a table, which stores each function in place. When you define a variable as an existing variable, you are actually creating a reference to it, for example:
t = {}
table.insert(t,1) --place 1 inside t
table.insert(t,3) --also place 3 inside t
s = t
print(s[1]) --will print 1, the first value of t
t[1]=2
print(s[1]) --will print 2, as it refers to t[1], which has just been changed
Sharing variables! (I worked out this bit!)
NOW, this means you can send variables around the program with another function. If you want to share score between games, you could do the following:
in main.lua:
function love.update()
gamestate.update()
score = gamestate.returnScore() --score will always equal to the current score being returned by the game
end
in a game, such as spaceInvaders.lua:
function spaceInvaders.returnScore()
return score --or whatever the score is stored in
end
This will allow you to get a variable, such as score, from one game to main.lua!
I'm sorry if this is a little confusing but hopefully this is what you're looking for! :)
for quite some time I've been working on an application. As programming is just a hobby this project is already taking way too long, but that's besides the point. I'm now at a point where every "problem" becomes terribly difficult to solve. And I'm thinking of refactoring the code, however that would result in a "complete" rewrite.
Let me explain the problem, and how I solved it currently. Basically I have data, and I let things to happen over this data (well I described about every program didn't I?). What happens is:
Data -> asks viewer to display -> viewer displays data based on actual data
viewer returns user input -> data -> asks "executor" to execute it -> new data
Now this used to work very well, and I was thinking originally "hey I might for example change command prompt by qt, or windows - or even take that external (C#) and simply call this program".
However as the program grew it became more and more tiresome. As the most important thing is that the data is displayed in different manners depending on what the data is and -more importantly- where it is located. So I went back to the tree & added someway to "track" what the parent-line is". Then the general viewer would search for the most specific actual widget.
It uses has a list with [location; widget] values, and finds the best matching location.
The problems starts when updating for new "data" - I have to go through all the assets - viewer, saver etc etc. Updating the check-mechanism gave me a lot of errors.. Things like "hey why is it displaying the wrong widget now again?".
Now I can completely swap this around. And instead of the tree datastructure calling to a generic viewer. I would use OO "internal" tree capabilities. The nodes would be childs (& when a new viewer or save-mechanism is needed a new child is formed).
This would remove the difficult checking mechanism, where I check the location in the tree. However it might open up a whole other can of worms.
And I'd like some comments on this? Should I keep the viewer completely separate - having difficulty checking for data? Or is the new approach better, yet it combines data & execution into a single node. (So if I wish to change from qt to say cli/C# it becomes almost impossible)
What method should I pursue in the end? Also is there something else I can do? To keep the viewer separate, yet prevent having to do checks to see what widget should be displayed?
EDIT, just to show some "code" and how my program works. Not sure if this is any good as I said already it has become quite a clusterfuck of methodologies.
It is meant to merge several "gamemaker projects" together (as GM:studio strangely lacks that feature). Gamemaker project files are simply sets of xml-files. (Main xml file with only links to other xml files, and an xml file for each resource -object, sprite, sound, room etc-). However there are some 'quirks' which make it not really possible to read with something like boost property trees or qt: 1) order of attributes/child nodes is very important at certain parts of the files. and 2) white space is often ignored however at other points it is very important to preserve it.
That being said there are also a lot of points where the node is exactly the same.. Like how a background can have <width>200</width> and a room too can have that. Yet for the user it is quite important which width he is talking about.
Anyways, so the "general viewer" (AskGUIFn) has the following typedefs to handle this:
typedef int (AskGUIFn::*MemberFn)(const GMProject::pTree& tOut, const GMProject::pTree& tIn, int) const;
typedef std::vector<std::pair<boost::regex, MemberFn> > DisplaySubMap_Ty;
typedef std::map<RESOURCE_TYPES, std::pair<DisplaySubMap_Ty, MemberFn> > DisplayMap_Ty;
Where "GMProject::pTree" is a tree node, RESOURCE_TYPES is an constant to keep track in what kind of resource I am at the moment (sprite, object etc). The "memberFn" will here simply be something that loads a widget. (Though AskGUIFn is not the only general viewer of course, this one is only opened if other "automatic" -overwrite, skip, rename- handlers have failed).
Now to show how these maps are initialized (everything in namespace "MW" is a qt widget):
AskGUIFn::DisplayMap_Ty AskGUIFn::DisplayFunctionMap_INIT() {
DisplayMap_Ty t;
DisplaySubMap_Ty tmp;
tmp.push_back(std::pair<boost::regex, AskGUIFn::MemberFn> (boost::regex("^instances "), &AskGUIFn::ExecuteFn<MW::RoomInstanceDialog>));
tmp.push_back(std::pair<boost::regex, AskGUIFn::MemberFn> (boost::regex("^code $"), &AskGUIFn::ExecuteFn<MW::RoomStringDialog>));
tmp.push_back(std::pair<boost::regex, AskGUIFn::MemberFn> (boost::regex("^(isometric|persistent|showcolour|enableViews|clearViewBackground) $"), &AskGUIFn::ExecuteFn<MW::ResourceBoolDialog>));
//etc etc etc
t[RT_ROOM] = std::pair<DisplaySubMap_Ty, MemberFn> (tmp, &AskGUIFn::ExecuteFn<MW::RoomStdDialog>);
tmp.clear();
//repeat above
t[RT_SPRITE] = std::pair<DisplaySubMap_Ty, MemberFn>(tmp, &AskGUIFn::ExecuteFn<MW::RoomStdDialog>);
//for each resource type.
Then when the tree datastructure tells the general viewer it wishes to be displayed the viewer executes the following function:
AskGUIFn::MemberFn AskGUIFn::FindFirstMatch() const {
auto map_loc(DisplayFunctionMap.find(res_type));
if (map_loc != DisplayFunctionMap.end()) {
std::string stack(CallStackSerialize());
for (auto iter(map_loc->second.first.begin()); iter != map_loc->second.first.end(); ++iter) {
if (boost::regex_search(stack, iter->first)) {
return iter->second;
}
}
return map_loc->second.second;
}
return BackupScreen;
}
And this is where the problems began to be frank. The CallStackSerialize() function depends on a call-stack.. However that call_stack is stored inside a "handler". I stored it there because everything starts FROM a handler. I'm not really sure where I ought to store this "call_stack". Introduce another object that keeps track of what's going on?
I tried going the route where I store the parent with the node itself. (Preventing the need for a call-stack). However that didn't go as well as I wished: each node simply has a vector containing its child nodes. So using pointers is out of the question to point to the parent note...
(PS: maybe I should reform this in another question..)
Refactoring/rewriting this complicated location checking mechanism out of the viewer into a dedicated class makes sense, so you can improve your solution without affecting the rest of your program. Lets call this NodeToWidgetMap.
Architecture
Seems your heading towards a Model-View-Controller architecture which is a good thing IMO. Your tree structure and its nodes are the models, where as the viewer and the "widgets" are views, and the logic selecting widgets depending on the node would be part of a controller.
The main question remains when and how you choose the widget wN for a given node N and how to store this choice.
NodeToWidgetMap: When to choose
If you can assume that wN does not change during its lifetime even though nodes are moved, you could choose it right when creating the node . Otherwise you'll need to know the location (or path through the XML) and, in consequence, find the parent of a node when requesting it.
Finding Parent Nodes
My solution would be to store pointers to instead of the node instances themselves, perhaps using boost::shared_ptr. This has drawbacks, for example copying nodes forces you to implement your own copy-constructors that uses recursion to create a deep-copy of your sub-tree. (Moving however will not affect the child nodes.)
Alternatives exist, such as keeping child nodes uptodate whenever touching the parent node respective the grandfathers vector. Or you can define a Node::findParentOf(node) function knowing that certain nodes can only (or frequently) be found as child of certain nodes. This is brute but will work reasonably well for small trees, just does not scale very well.
NodeToWidgetMap: How to choose
Try writing down the rules how to choose wN on piece of paper, perhaps just partially. Then try to translate these rules into C++. This might slightly longer in terms of code but will be easier to understand and maintain.
Your current approach is to use regular expressions for matching the XML path (stack).
My idea would be to create a lookup graph whose edges are labelled by the XML element names and whose nodes indicate which widget shall be used. This way your XML path (stack) describes a route through the graph. Then the question becomes whether to explicitly model a graph or whether a group of function calls could be used to mirror this graph.
NodeToWidgetMap: Where to store choice
Associating a unique, numeric id to each node, record the widget choice using a map from node id to widget inside the NodeToWidgetMap.
Rewriting vs Refactoring
If you rewrite you might get good leverage tieing to an existing framework such as Qt in order to focus on your program instead of rewriting the wheels. It can be easier to port a well-written program from on framework to another than to abstract around the pecularities of each platform. Qt is a nice framework for gaining experience and good understanding of the MVC-architectures.
A complete rewrite gives you a chance to rethink everything but implies the risk that you start from scratch and will be without a new version for a good amount of time. And who knows whether you will have enough time to finish? If you choose to refactor the existing structures you will improve it step by step, having a useable version after each step. But there is small risk to remain trapped in old ways of thinking, where as rewriting nearly forces you to rethink everything. So both approaches have their merits, if you enjoy programming I would rewrite. More programming, more joy.
Welcome to the world of programming!
What you describe is the typical life cycle of an application, starts as a small simple app, then it gets more and more features until it is no longer maintainable. You can't imagine how many projects I've seen in this last collapsing phase!
Do you need to refactor? Of course you do! All the time! Do you need to rewrite everything? Not so sure.
In fact the good solution is to work by cycles: you design what you need to code, you code it, you need more functionality, you design this new functionality, you refactor the code so you can integrate the new code, etc. If you don't do it like this then you will arrive to the point where its less expensive to rewrite then to refactor. Get this book: Refactoring - Martin Fowler. If you like it then get this one: Refactoring to Patterns.
As Pedro NF said, Martin Fowler "Refactoring" is the nice place to get familiar with it.
I recommend buying a copy of Robert Martins "Agile Principles, Patterns and Practices in C#" He goes over some very practical case studies that show how to overcome maintenance problems like this.
I’m teaching an entry-level C++ programming class. We only use iostream in the class (No GUI). It seems like students are not so excited to printout strings and numbers to their console. (Most students even never used the console before.) It is hard to motivate or convey the excitement of programming by showing strings in their console.
What would be a good and exciting console program that can be written by C++ beginners? I’m looking for something doable with basic C++ skill + a bit challenging + very exciting, which can motivate students to learn programming languages.
Any comments will be appreciated.
When I taught an undergrad intro course, we did the Game of Fifteen in straight C as the third homework project. It's pretty well scoped, and it's a game, so there's some inherent motivation there.
Back when I taught, I made an early project be an ATM machine.
Text-only interface, with basic operations like withdraw, deposit, query balance, transfer between accounts, etc.
It was something that everyone was already familiar with, it didn't take huge amounts of programming time, but it did help students feel like it was a practical and realistic program.
Other similar ideas would be a cash-register (handle refunds, coupons, items priced by the pound, sales-tax, store specials, etc, etc), or a cell-phone billing program (separate daytime, night, and weekend minutes, bill text messages, picture messages separately, etc).
How about a system that generates a set of poker hands from a deck? While clearly defined, the intricacies of ensuring no duplicate cards etc, make it a good entry level challenge.
As an extension, you could have the system take an input as to whether you want to bet or fold, and effectively play a poker game.
Finally, a good design would allow them to switch the console for a gui front-end later on (e.g. intermediate class).
I always enjoyed problems where there's a real world purpose for doing it. Something like calculating a mathematical equation, or a range of prime numbers. A lot of stuff on ProjectEuler would be good, I would think. Not everybody likes math (but then again, it's kind of a necessary thing for computer science!).
Instead of just printing to the screen you could make ascii animations.
Introduce your students to pipes and filters. Create a useful utility that takes data from stdin and directs its output to stdout. Create another utility that does something else using that same protocol. Create a third utility. Demonstrate how robustly the utilities can work together.
For example, create a clone of the GNU head and tee utilities, and perhaps add a new utility called cap which capitalizes letters. Then demonstrate how you can get the first 3 lines of a text file capitalized and tee'd to a file and stdout. Next, demonstrate how you use the same utilities, without changing a single line of code, to take the first 5 lines of a file and output to the screen the capitalized letters and to a file the original letters.
When I took C++ we had to replicate a Theseus and the Minotaur game. It lends well to outputting multiple lines to the console to form something "graphical" and it's easily based on a set of implemented rules.
I've had to program a Tower of Hanoi game in the console before, I found that quite fun. It requires use of basic data structures, user input, checking for game end conditions so it would be good for a beginner I believe.
New programming students usually find graphical programs to be the most exciting.
It doesn't have to be anything really advanced, just being able to manipulate pixels and stuff should be enough to keep them interested. Making a simple graphic class around SDL should be ok. Maybe something like this:
int main()
{
GraphicWindow graphic;
graphic.setPixel(10,20,GraphicWindow::Red);
graphic.idle();
}
Then you give out assignments like "implement a drawRect function" etc.
Perhaps a text-only version of the Lunar Lander game. You could do full ASCII art and animations (with ncurses, perhaps) as an advanced exercise, but even in a pure text form it can be interesting.
I recall playing the version that ran on the HP 67 calculator, and it was entertaining with only a seven segment display to work with.
I vaguely recall a version that probably ran on an ALTAIR 8800 written in MITS/Microsoft BASIC that used the leading part of the line to show height above ground as ASCII art, with your prompt for the next tick's burn at the right.
Another traditional choice would be to implement Hunt the Wumpus, or for the ambitious, Battleship.
One of my first programming class had a long homework about implementing a (reduced) Monopoly game.
You can use chained lists for the board.
You can use Inheritance for board tiles.
You need some logic to process players turns.
It was probably the first project I've done in CS that I could talk about to my non-tech friends and generate some interest.
The game will be written in C++
Programming:
enemies.puch_back(new DefaultEnemy(200, 300, 3, 5));
enemies.puch_back(new DefaultEnemy(500, 400, 4, 5));
enemies.puch_back(new DefaultEnemy(300, 420, 3, 15));
enemies.at(2).createAward(new Key(4), "pling.wav");
Or Interpret them from a file like this:
DefaultEnemy 200 300 3 5
DefaultEnemy 500 400 4 5
DefaultEnemy 300 420 3 15
CreateAward 2 "pling.wav" Key 4
Program it would be more easy and people can't (without speaking of hacking) edit your levels. But it maybe a bit rubbish to program it all? Are there other reasons to choose for programming or interpreting?
How about memory-management (if I should go for interpreting)?
How to delete the (game)objects when the level unloads?
Always separate application from data.
First variant is equivalent to hardcoding game resources. This is absolutely bad and is suitable only for debugging.
Every games store their resources in external files - xml, archived packages and parse and load them during runtime.
Therefore, modern game engines almost every time have their set of tools which is bundled with it.
Deleting game resources is also a vast question - it depends. Depends on your objects' lifetime management and on that fact if you need to unpack your data into temporal files.
Well I would save the level design in a file. Thats what scripting is for right. This then gives me a way to JUST change the levels..
Also It will keep your objects (the stuff used in the levels) seperate from the logic (the game logic). This will help debugging and have a clearer structure
Depends on if you can spare the resources for interpretation, and who else you intend to use your work. If you and you alone are creating it, then there's nothing wrong per se with hardcode.
If, however, you ever intend users or anyone else to modify it, ever, then interpret.