SDL: Delay until keyboard input - c++

Say we have (pseudo) code like this:
GetInput()
{
//insert keyboard stuff here
}
Update()
{
//insert rendering stuff here
}
void game::loop()
{
game.Update();
player.GetInput();
}
How will I go about waiting for the player to give input before updating whats on screen?

Why not switch the order (GetInput first), then block in GetInput and don't return until the user has entered something acceptable?

Are you sure you really want to wait? Don't mean to be intrusive, but usually in games it's best to continue drawing stuff on the screen while waiting for any kind of input. Because players don't want to see the very same picture all the time.

To make the game turn-based, I recommend an array of objects with methods that represent a player's abilities in the game. You can have a game loop, a nested round loop, a nested turn loop, and a boolean that exits the round and turn loops when a player wins.
With your current pseudocode, you could use a switch and integer in the Update method to equate these nested loops.
Example Tic Tac Toe AI:
#include "Shared.h"
#include "Board.h"
#ifndef AI_H_
#define AI_H_
class AI{
public:
AI();
enum difficulty{Easy, Medium, Hard};
void setAlgorithm(difficulty h);
void applyAlgorithm(Board* b, int columns, int rows);
private:
Board::spot type;
difficulty harder;
void easy(Board* b, int columns, int rows);
void medium(Board* b, int columns, int rows);
void hard(Board* b, int columns, int rows);
};
#endif /*AI_H_*/
SDL_WaitEvent() is ridiculously more efficient than SDL_PollEvent(), if you don't want to hog the CPU.
while(!quit){
if(SDL_WaitEvent(&event)){
if(event.type == SDL_QUIT){
quit = true;
}else if(event.type == SDL_MOUSEBUTTONDOWN){
if(!menu.isClicked()){
if(menu.handleEvent(&event)){
}
}
}
}
}

Related

Do one time (once) execution in forever loop or void loop?

I want make one time or once execution syntax inside forever loop (void loop) for any program languages.
What i found the solution is with make new variable boolean "executed" and set to true after executed.
It's okay, but what if i want do once execution to other syntax? Should i make new variable boolean again? It will not effecient. Imagine theres many syntax but i must make new bool executiin for each syntax.
The solution is function i think
For example
void loop()
{
lcd.print("OK");
}
THIS IS WILL PRINT FOREVER
I wish theres function like this
void loop()
{
once(lcd.print("OK"));
}
so "once" is a function with parameter string which its for command/syntax.
once("command")
Several ways to approach this
Following is a very common way of how such an operation is usual made.
As you already suggested, with an global boolean:
bool once = true; // global variable
void loop() {
if (once) { // being called only once
lcd.print("OK");
once = false;
}
}
Do something only once after a specific time:
void loop() {
// millis() is the time in milliseconds after the startup
//if you want to print something once after a specific amount of time
//this also includes a little "wait time" of 100 milliseconds as the statement might be asked with a delay
if (mills() >= 1000 && mills() <= 1100) {// time in milliseconds
lcd.print("OK");
}
}
And thanks to this thread, with exiting the loop (might be not what you are searching for):
void loop() {
lcd.print("OK");
exit(0); //The 0 is required to prevent compile error.
}
But I suppose you are trying to make some kind of an interface, where a specific answer is printed regarding to the user input (probably many possibilities)?!
In that case it kind of depends on what inputs you are getting:
In case of Integers:
void loop() {
switch (input) { //input must be an integer
case 0:
lcd.print("OK"); //prints "ok" if input is 0
case 1:
lcd.print("Hello"); //prints "Hello" if input is 1
}
}
In case of Stings/chars, you need to go with an "if loop" trough every possible input(or with an array of Strings/chars):
void loop() {
lcd.print("Turn off?"); //asks if it should do something
if (input == "yes") { //String input
lcd.print("OK, shut down!");
//do something
}
else if (input == 'n' || input == 'N') { //char input
lcd.print("OK, no shut down!");
//do something
}
}
A function you are looking for, where a specific answer only prints ONCE regarding to an input can be just archived by if/else loops. If a String should be just printed once at startup, print it in the "setup()" constructor. Otherwise just with global booleans something like that is possible.
Note that those are only my suggestions based on my experience, but it does not necessarily mean that other solutions are not available.
Hope that helps still :)
Here is one way you can do it:
void loop()
{
{ // execute once. Can put this in a separate function also
static bool executed = (lcd.print("OK"), true);
}
}
You're guaranteed that this variable is initialized once.
If you want the once syntax in your question, you can achieve something similar with a macro:
#define ONCE(...) \
{\
static bool executed = ([&]{__VA_ARGS__;}(), true); \
}
void loop()
{
ONCE(lcd.print("OK"))
}
In C++, there is std::call_once which is even multi_thread, then you can do it generically:
template <typename F>
void simple_do_once(F f)
{
static std::once_flag flag;
std::call_once(flag, f);
}
As lambda have unique type, you have one flag by lambda:
Demo

Correcting a Tic Tac Toe-Draw function

I am making a multiplayer tic tac toe game with a semi-graphical interface. I have made the code and most of it works.The only part of it that doesn't work is the draw function.
I do understand that I am using TurboC++,which is a highly out of date compiler,but the Indian education system follows only TurboC++,so I have to make my project in it.(The syllabus was changed to have Python instead of C++ recently but I happened to be in the last batch of students that will not be taught Python)
The problem is in the last part of the result() function. I was unable to find what was wrong with it.I have not used graphics.h because it is not in my syllabus.
result function alone:
struct mat //To store the positions and what is present in the 9 boxes
{
int x,y;char ch;
};
struct xo //To keep track of the match
{
int actp,actx,acty;
mat pos[3][3];
char flag;
void setup() //To create the boxes/bars
{
actp=1,actx=1,acty=1;
flag=0;
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
pos[i][j].ch=0;
}
}
void result() //To find the result
{
char flage;
for(int i=0;i<3;i++) //Column win
{
if(pos[i][0].ch==pos[i][1].ch&&pos[i][1].ch==pos[i][2].ch)
flage=pos[i][0].ch;
}
for(i=0;i<3;i++) //Row win
{
if(pos[0][i].ch==pos[1][i].ch&&pos[1][i].ch==pos[2][i].ch)
flage=pos[0][i].ch;
}
if(pos[0][0].ch==pos[1][1].ch&&pos[1][1].ch==pos[2][2].ch) //Diagonal win
flage=pos[0][0].ch;
if(pos[0][2].ch==pos[1][1].ch&&pos[1][1].ch==pos[2][0].ch) //Other diagonal win
flage=pos[0][2].ch;
if(flage=='X')flag='1';
else if(flage=='O')flag='2';
else flag='0';
int chk=1;
for(i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{if(pos[i][j].ch=='0'){chk=0;gotoxy(3,15);cout<<chk;} }//Added cout statement for debugging
}
if(flag=='0'&&chk==0)flag='D';//I understand that the condition is supposed to be chk==1,but it works only if I have this condition
}
}a;
Here is the whole code,if necessary:
https://drive.google.com/open?id=19WMexp3Hw_p9hO3qiYm0HRj-GGAJeaTr
A screenshot:
https://i.stack.imgur.com/wGh7a.jpg
If I use the correct condition, the program says that the match is drawn just after 1 move.
With this wrong condition, the program works to a certain extent and is able to find winners but never declares a match drawn even if it happens.
Thanks for the help!!
I have corrected the errors, will elaborate soon. Thanks for the help.

Controls not responding properly in snake

I'm writing a basic snake game as console application in c++. It's based on two-dimensional array of "tile" structures. My problem is: when pressing button to change the direction the snake is going it doesn't work immidiately but waits for next "tick" instead. The function that manages game itself looks like this:
void board::play()
{
display();
while(1)
{
getInput();
delay(0.5);
getInput();
resetCursor();
tick();
display();
}
}
display() is pretty self-explanatory, displays whole board in console window.
delay() as well, it's function which gets number of seconds as a float and waits this much time before proceeding
getInput() looks like this:
void board::getInput()
{
int input;
if(kbhit())
{
input=getch();
if(input==KEY_LEFT)
turnLeft();
if(input==KEY_RIGHT)
turnRight();
if(input==KEY_UP)
turnUp();
if(input==KEY_DOWN)
turnDown();
}
}
resetCursor() sets the cursor to 0,0 coordinate so each time the board will write over itself and not one under another
And now for the game itself: class board contains amongst others field int direction. The tiles themselves contain a counter, which counts down by 1 with each move, and when reaches 0 the tile becomes empty. If the counter is equal to the lenght of a snake the tile is considered a head.
The tick()function does just that: decreases all counters by 1, remembers where head was and spawns a new head in the field next to previous one in direction specified. It looks like this:
void board::tick()
{
int posx, posy;
for(int i=0; i<boardSize; i++)
{
for(int j=0; j<boardSize; j++)
{
if(tab[i][j].getCounter()==lenght)
{
posx=i;
posy=j;
}
tab[i][j].tick();
}
}
switch(direction)
{
case UP: tab[posx-1][posy].addSnake(lenght);
break;
case DOWN: tab[posx+1][posy].addSnake(lenght);
break;
case LEFT: tab[posx][posy-1].addSnake(lenght);
break;
case RIGHT: tab[posx][posy+1].addSnake(lenght);
break;
}
}
Problem is, as stated before, that game waits one "tick" before changing direction when it should do so immediately after pressing associated button, e.g. when turning from UP to LEFT it does one more move up and only after that moves left.
It seems to me that you have an extra getInput() call. Could it be the problem?
while(1)
{
getInput(); // <--
delay(0.5);
getInput(); // <--
resetCursor();
tick();
display();
}
Solved.
Turns out there were too many things put into buffer, as the program started going crazy if you mashed controls randomly during waiting time. I solved it by replacing
if(kbhit())
{
input=getch();
//reactions
}
with
while(kbhit())
{
input=getch();
}
//reactions
It now checks every signal in the buffer and reacts only to the last one, so the delay is eliminated.

Placing a piece in a connect four game using c++

Ok so i have a homework assignment and i dont know where to start with this function.
bool placePiece(char** pBoard, int colSize, int rowSize, int columnSelection, char player)
The function is to place a piece represented by char player, on the game board char** pBoard (a 2dArray made from colSize and rowSize) the function is to put the players piece at the bottom of the column selected during that players turn. also if a piece is already at the bottom of the column it puts the piece on top of that one and if the column is full it will return false.
really the biggest issue im having is i really dont understand how im supposed to be using pBoard.
Im not looking for someone to do it for me but just to help me start out on the right path.
To solve this, you need to understand arrays and loops. The first argument in your signature is an array containing your board data (and the next two arguments the dimensions of it) - there you need to access the first element at the columnSelection position and set it to the value of the player argument. The return value should indicate if the operation was successful.
bool placePiece(char** pBoard, int colSize, int rowSize, int columnSelection, char player) {
if (columnSelection >= colSize) {
/* invalid column */
return false;
}
for (size_t i = 0; i < rowSize; ++i) {
/* loop to go over all rows - starting with 0 */
if (pBoard[columnSelection][i] == 0) {
/* find first empty row and set it to 'player' value */
pBoard[columnSelection][i] = player;
return true;
}
}
/* no free row found -> all rows already set*/
return false;
}
This code assumes an column-row order in your array and goes from row 0 upwards, but you should get the general idea.

Overwhelmed by assignment based on Conway's Game of Life [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am given files gameOfLife.cpp, life.cpp, and life.h. I am only allowed to edit life.cpp in order to make the program work. I don't know where to with editing life.cpp because there is so much going on that I am unfamiliar with. I am given a file checkoutLife.cpp to check my work.
I've spent the last two days looking at other people's Game of Life files trying to see how to proceed but am at a loss. I don't want someone to do my work for me but I need some direction.
gameOfLife.cpp
#include <iostream>
#include "life.cpp"
#include "life.h"
const int GENERATIONS=100;
using namespace std;
//make a random array of initial living cells
void gen(bool a[ROWS][COLS]){
for(int i=0;i<ROWS;++i){
for(int j=0;j<COLS;++j){
if(rand()%100<10)a[i][j]=true;
else a[i][j]=false;
}
}
a[5][5]=true;
a[5][6]=true;
a[5][7]=true;
return;
}
// check to see if two arrays are equal
bool equal(const bool a[ROWS][COLS], const bool b[ROWS][COLS]){
int i,j;
for(i=0;i<ROWS;++i)for(j=0;j<COLS;++j)if(a[i][j]!=b[i][j])return false;
return true;
}
//copy the b array into the a array
void copy(bool a[ROWS][COLS], const bool b[ROWS][COLS]){
for(int i=0;i<ROWS;++i){
for(int j=0;j<COLS;++j){
a[i][j]=b[i][j];
}
}
return;
}
//print out the array
void print(const bool a[ROWS][COLS]){
for(int i=0;i<ROWS;++i){
for(int j=0;j<COLS;++j){
if(a[i][j])cout << 'X';
else cout << ' ';
}
cout << endl;
}
return;
}
int main(){
bool current[ROWS][COLS];
bool next[ROWS][COLS];
int i=0;
//initialze the cell array and print it out
gen(current);
print(current);
while(i<GENERATIONS){
//get a carriage return before the next generation
cin.get();
//give the current generation to life()
//it puts the next generation into next
life(current,next);
//copy the next generation into the current
copy(current,next);
//print it out
print(current);
i++;
}
return 0;
}
life.cpp
/*1. You need to write a file life.cpp that implements the function prototyped in life.h. You can and should write other functions
and tuck them into the same file; whatever you need to get your function working in an elegant manner.
2. Compile your file with checkoutLife.cpp and run the resulting executable to see if it passes all the tests.
3. Compile yourfile with gameOfLife.cpp and run the resulting executable to see if it makes pretty pictures.
4. If you are convinced steps 2 and 3 are working, submit your life.cpp via canvas.
*/
#include <iostream>
#include <cstdlib>
#include "life.h"
using namespace std;
void life(const bool current[ROWS][COLS], bool next[ROWS][COLS]){
}
life.h
#ifndef LIFE_H
#define LIFE_H
const int ROWS=25;
const int COLS=25;
// Simulate one generation of Conways Game of Life
//
// Given:
// a constant 2D bool array called "current" where each true element
// indicates a live cell and each false element indicates a dead cell.
//
// an empty 2D bool array called "next"
void life(const bool current[ROWS][COLS], bool next[ROWS][COLS]);
#endif
life() is called with two parameters: an array of your board's current state (which presumably you will not touch) and an array of the board's next state (which you will populate).
Here is an algorithm you could use:
For each row in ROW:
For each col in COL:
Add up all surrounding neighbours in current[][], store in "neighbours"
If current[row][col] is alive and neighbours < 2, next[row][col] = dead
Else if current[row][col] is alive and neighbours == 2 or 3, next[row][col] = alive
Else if current[row][col] is alive and neighbours > 4, next[row][col] = dead
Else if current[row][col] is dead and neighbours == 3, next[row][col] = alive
You can clean up the logic a bit, but I printed it out just like the rules on Wikipedia's Game of Life entry. The complicated part (IMO) is "Add up all surrounding neighbours" - there's a lot of bounds checking here. I suggest calling a different method that you write, for clarity's sake.