I'm wrinig a simple snake game on C++. But I have a problem: I need to use kbhit() and getch() for read what the user enters. For use it I need conio.h but there're no this library on Linux. I tryed use this, but there're have a trouble: code is compiling but I can't use program, it just stoping.
So how can I use kbhit() and getch()? Or is there any alternative for it?
My code:
#include <iostream>
#include <conio.h>
using namespace std;
bool GameOver;
const int height = 20;
const int width = 20;
int x, y, fruit_x, fruit_y, score;
enum eDirection { STOP, RIGHT, LEFT, UP, DOWN };
eDirection dir;
void setup() {
GameOver = false;
dir = STOP;
x = width / 2 - 1;
y = height / 2 - 1;
fruit_x = rand() % width;
fruit_y = rand() % height;
score = 0;
}
void draw() {
system("clear");
for (int i = 0; i < width; i++)
{
cout << "#";
}
cout << endl;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (j == 0 || j == width - 1)
{
cout << "#";
}
if (i == y && j == x)
{
cout << "0";
}
else if (i == fruit_y && j == fruit_x)
{
cout << "F";
}
else
{
cout << " ";
}
}
cout << endl;
}
for (int i = 0; i < width; i++)
{
cout << "#";
}
cout << endl;
}
void input() {
if (_kbhit)
{
switch(getch())
{
case 'a':
dir = LEFT;
break;
case 'd':
dir = RIGHT;
break;
case 'w':
dir = UP;
break;
case 's':
dir = DOWN;
break;
case 'x':
GameOver = true;
break;
}
}
}
void logic() {
switch(dir)
{
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
case UP:
y--;
break;
case DOWN:
y++;
break;
}
}
int main() {
setup();
while(!GameOver)
{
draw();
input();
logic();
}
}
As zoelabbb said in this link,
Step 1 :
Open terminal sudo apt-get update
sudo apt-get upgrade
sudo apt-get install git
git clone https://github.com/zoelabbb/conio.h.git
cd conio.h
Step 2 :
sudo cp conio.h /usr/include/
or (step 2)
In GUI, using open-as-administrator pakage:
Copy file conio.h --> !! copy file not folder !!
Go to /usr/include/
Right click on folder /usr/include/
Choose Open as Administrator
Paste file conio.h
Finaly after step 1 and step 2 you can use #include <conio.h> in your code.
Related
I'm trying to separate my code into header.h, main.cpp and implementation.cpp, but I'm not getting it. Can someone help me? I need that separate code in these files, and that the game works properly. I've tried in several ways, but I'm not getting.If I try to run as is, the IDE reports "multiple definition of"
main.cpp
#include<iostream>
#include<conio.h>
#include"implem.cpp"
using namespace std;
int main()
{
setup();
while (!gameover) {
mapa ();
input ();
algoritmo ();
}
return 0;
}
header.h
#ifndef HEADER_FLAG
#define HEADER_FLAG
void setup();
void mapa();
void input();
void algoritmo();
#endif
implem.cpp
#include<conio.h>
#include"header.h"
#include<stdlib.h>
#include<time.h>
using namespace std;
bool gameover;
const int width = 20;
const int height = 17;
int x, y, fruitX, fruitY, score;
int tailX[100], tailY[100]; //snake coordinates
int nTail;
enum eDirecton {STOP = 0, LEFT,RIGHT, UP, DOWN}; // Controls
eDirecton dir;
void setup(){
gameover = false;
dir = STOP;
x = width / 2;
y = height / 2;
fruitX = rand() % width;
fruitY = rand() % height; score = 0;
}
void mapa(){
system("cls");
for(int i = 0; i < width+2; i++)
cout << "#";
cout << endl ;
for (int i = 0; i < height ; i++) {
for (int j = 0; j < width; j++) {
if (j == 0)
cout << "#"; //walls
if (i == y && j == x)
cout << "*"; // snake tale
else if (i == fruitY && j == fruitX )
cout << "%"; // change it to change the fruit
else {
bool print = false;
for (int k = 0; k< nTail ; k++) {
if (tailX [k] == j && tailY [k] == i) {
cout << "*"; print = true;
}
} if (!print) cout << " ";
}if (j == width -1)
cout << "#";
}cout << endl;
}
for (int i = 0; i< width+2; i++)
cout << "#";
cout << endl;
cout << "Score:" << score << endl ;
}
void input()
{
if (_kbhit ()) {
switch (_getch ()) {
case 'a':
dir = LEFT;
break;
case 'd':
dir = RIGHT;
break;
case 'w':
dir = UP;
break;
case 's':
dir = DOWN ;
break;
case 'x':
gameover = true;
break;
}
}
}
void algoritmo(){
int prevX = tailX [0];
int prevY = tailY [0];
int prev2X, prev2Y;
tailX[0] = x;
tailY[0] = y;
for(int i = 1;i < nTail ; i++) {
prev2X = tailX[i];
prev2Y = tailY[i];
tailX[i] = prevX;
tailY[i] = prevY;
prevX = prev2X;
prevY = prev2Y ;
}
switch (dir) {
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
case UP:
y--;
break;
case DOWN:
y++;
break;
default:
break;
}
if (x >= width) x =0;else if (x <0) x = width -1;
if (y >= height) y = 0; else if (y < 0) y = height - 1;
for (int i =0; i< nTail ;i++)
if (tailX[i] == x && tailY[i] == y)
gameover = true;
if (x == fruitX && y == fruitY) {
score +=10;
fruitX = rand() % width;
fruitY = rand() % height;
nTail ++;
}
}```
I suspect that the multiple definition error is due to the fact that the project has main.cpp and implem.cpp. Since you also #include "implem.cpp" in main, symbols from implem.cpp have two origins, and the linker complains.
Never ever #include an implementation code. The correct way to structure your project is:
// main.cpp
#include "header.h"
int main()
{
setup();
while (!gameover) {
mapa ();
input ();
algoritmo ();
}
return 0;
}
header.h and implem.cpp should remain as they are.
Notice that you don't need to #include anything else in main, because it doesn't refer to the symbols declared in either iostream or conio.h.
You're #includeing implem.cpp into main.cpp instead of implem.h.
Probably you've also added implem.cpp to the project in your IDE. Then it's compiled on its own, and a second time as included part of main.cpp. When the IDE links the compiled object files, all the stuff in implem.cpp will be doubly defined.
I'm writing a simple console game and I'm having problems with console flickering (i think system("cls") might be the issue?). I tried using double buffers but I messed it up I guess.I know Move() function doesnt work fully correct but it's enough to show movement on console. I'm also unsure about kbhit and getch, since usage of these is not recommended. What are some good alternatives?
void Snake::DrawBuffer()
{
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < WIDTH; j++)
{
std::cout << buffer[WIDTH * i + j];
}
std::cout << '\n';
}
}
void Snake::WriteNextBuffer()
{
for (int i = 0; i < WIDTH * HEIGHT; i++)
nextbuffer[i] = ' ';
for (int i = 0; i < length; i++)
nextbuffer[body[i]] = 'o';
}
void Snake::WriteBuffer()
{
for (int i = 0; i < WIDTH * HEIGHT; i++)
{
buffer[i] = nextbuffer[i];
}
}
void Snake::Move()
{
char key;
if (_kbhit())
key = _getch();
else
key = lastkey;
switch (key)
{
case 'w':
if (lastkey != 's')
{
body.pop_back();
body.emplace(body.begin(), head - WIDTH);
}
break;
case 's':
if (lastkey != !'w')
{
body.pop_back();
body.emplace(body.begin(), head + WIDTH);
}
break;
case 'a':
if (lastkey != 'd')
{
body.pop_back();
body.emplace(body.begin(), head - 1);
}
break;
case 'd':
if (lastkey != 'a')
{
body.pop_back();
body.emplace(body.begin(), head + 1);
}
break;
}
head = body[0];
lastkey = key;
}
void Snake::Frame()
{
Move();
WriteNextBuffer();
WriteBuffer();
DrawBuffer();
}
void Snake::Game()
{
while (1)
{
Frame();
system("cls");
}
}
I have one problem. My snake is not moving. I cant find mistake. It draws map and snake head bt it doesnt move.
#include <iostream>
#include <conio.h>
using namespace std;
bool gameOver;
const int width = 20;
const int height = 20;
int x, y, fruitX, fruitY;
enum eDirecton { STOP = 0, LEFT, RIGHT, UP, DOWN };
eDirecton dir;
void Setup() {
gameOver = false;
dir = STOP;
x = width / 2;
y = height / 2;
fruitX = rand() % width;
fruitY = rand() % height;
}
void Draw() {
system("cls");
for(int i = 0; i < width + 2; i++) cout << "#";
cout << endl;
for(int i = 0; i < height; i++) {
for(int j = 0; j < width; j++) {
if(j == 0) cout << "#";
if(i == y && j == x)
cout << "O";
else if(i == fruitY && j == fruitX)
cout << "F";
else
cout << " ";
if(j == width - 1) cout << "#";
}
cout << endl;
}
for(int i = 0; i < width + 2; i++) cout << "#";
cout << endl;
}
void Input() {
if(_kbhit()) {
switch(_getch()) {
case 'a':
dir = LEFT;
break;
case 'd':
dir = RIGHT;
break;
case 'w':
dir = UP;
break;
case 's':
dir = DOWN;
break;
case 'q':
gameOver = true;
break;
}
}
}
void Logic() {
switch(dir) {
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
case UP:
y++;
break;
case DOWN:
y--;
break;
default:
break;
}
}
int main() {
Setup();
while(!gameOver) {
Draw();
Input();
Logic();
// sleep (10)
}
return 0;
}
Start game right-away as you don't have a control key to start the game. Also it seems the UP/DOWN keys logic needs to interchange, as it is behaving opposite.
void Setup() {
dir = DOWN;
/* … */
}
// Control speed of animation . You may require #include<chrono>
int main() {
Setup();
while (!gameOver) {
Draw();
Input();
Logic();
this_thread::sleep_for(chrono::milliseconds(300));
}
return 0;
}
It's moving here (after pressing a key). Are you sure you're using the a,d,w,s keys and not the arrow keys?
You also need to switch the up an down logic, and provide a way to prevent going past the borders:
void Logic() {
switch(dir) {
case LEFT:
x--;
if (x < 0)
x = width-1;
break;
case RIGHT:
x++;
if (x == width)
x = 0;
break;
case UP:
y--;
if (y < 0)
y = height-1;
break;
case DOWN:
y++;
if (y == height)
y = 0;
break;
default:
break;
}
}
Or the short style version like:
case LEFT:
if (--x < 0)
x = width-1;
break;
To start te game immediately just set the direction in your setup().
It's Moving
Make Sure You're using a,s,d,w Keys and not Arrow Keys .
I'm a C++ noob coding the snake game. The whole program draws the board, fruit and snake head perfectly, however I cannot seem to make the snake head coordinates change using a keyboard hit function. When going through the input function which gets keyboard strokes for snake movement, it appears that the if(kbhit) evaluates to false when running program,what is my error and how can I get the snake head to move?
Thanks.
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <conio.h>
using namespace std;
int X, Y, fruitX, fruitY;
enum eDir { STOP = 1, UP = 2, DOWN = 3, RIGHT = 4, LEFT = 5 }; //declare variables
eDir direction;
const int height = 20;
const int width = 20;
int board[height][width];
bool gameOver;
void setup()
{
gameOver = false;
srand(time(NULL)); // initilize game set up
fruitX = (rand() % width);
fruitY = (rand() % height);
X = height / 2;
Y = width / 2;
direction = STOP;
int board[height][width];
};
void draw()
{
system("cls");
for (int i = 0; i < width + 2; i++)
cout << '#';
cout << endl;
for (int i = 0; i < height; i++) //loop through matrix to draw board
{
for (int j = 0; j < width; j++)
{
if (j == 0)
cout << '#';
if (i == Y && j == X) // draw snake head
cout << 'T';
else if (i == fruitY && j == fruitX) // draw fruit
cout << 'F';
else
cout << ' ';
if (j == width - 1)
cout << '#';
}
cout << endl;
}
for (int i = 0; i < width + 2; i++)
cout << '#';
cout << endl;
};
void input()
{
if (_kbhit())
{
switch (_getch())
{
case 'w':
direction = UP;
break;
case 's':
direction = DOWN;
break;
case 'a':
direction = LEFT;
break;
case 'd':
direction = RIGHT;
break;
default:
break;
}
}
};
void logic()
{
switch (direction)
{
case UP:
Y--;
break;
case DOWN:
Y++;
break;
case LEFT:
X--;
break;
case RIGHT:
X++;
break;
default:
break;
}
};
int main()
{
setup();
while (!gameOver)
{
draw();
input();
logic();
return 0;
}
};
For one thing, you do return 0; inside your game loop which kills the program after only one iteration which I assume you did not intend.
I made snake using a similar method and mine looks like this:
bool play = true;
while(play) {
while (_kbhit) {
switch (_getch) {
case 'w':
//code
break;
case 's':
//code
break;
case 'a':
//code
break;
case 'd':
//code
break;
}
}
}
That method worked for me and I think the only difference is that I used a while loop instead of an if.
I'm beginner to C++. i'm making a snake game in c++ simple game console based. without using any graphics. i had done almost 60% of work the only thing which makes me confuse is the movement of snake after eating "fruit". Below is my code if someone can help me please it'll be very helpful or i want you to give me any hint so that i can continue my code
Here is my header file
snake.h:
#ifndef SNAKE_H
#define SNAKE_H
class snake
{
private:
char key;
int x1, y1, x2, y2, n;
char keyp;
public:
snake()
{
x1=28; y1=12; x2=0; y2=0; n=1;
}
void gotoxy(int x, int y);
void frame();
char movement(char keyp);
char rmove();
char lmove();
char umove();
char dmove();
void rstar();
void rcstar();
void options();
};
#endif // SNAKE_H
Here is my snake.cpp File
Snake.cpp
#include "snake.h"
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
//gotoxy function
COORD coord={0,0};
void snake::gotoxy(int x,int y)
{
coord.X=x;
coord.Y=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
}
void snake::frame()
{
for(int i=0;i<=78;i++)
cout << char(45);
for(int i=1;i<22;i++)
{
gotoxy(0,i);
cout << char(124);
gotoxy(63,i);
cout << char(124);
gotoxy(78,i);
cout << char(124);
}
cout << endl;
for(int i=0;i<=78;i++)
cout << char(45);
}
char snake::rmove()
{
for(;x1<=63;x1++)
{
Sleep(200);
if(x1==62)
{
x1=1;
gotoxy(61,y1);
cout << " ";
}
if(x1!=1)
{
gotoxy(x1-1,y1);
cout << " ";
gotoxy(x1,y1);
cout << "*";
}
rcstar();
if(kbhit())
{
keyp=getch();
if(keyp=='a' || keyp=='A' || keyp=='d' || keyp=='D')
continue;
else
break;
}
}
return keyp;
}
char snake::lmove()
{
for(x1;x1>=0;x1--)
{
Sleep(200);
if(x1==0)
{
x1=62;
gotoxy(1,y1);
cout << " ";
}
if(x1!=62)
{
gotoxy(x1+1,y1);
cout << " ";
gotoxy(x1,y1);
cout << "*";
}
rcstar();
if(kbhit())
{
keyp=getch();
if(keyp=='d' || keyp=='D' || keyp=='a' || keyp=='A')
continue;
else
break;
}
}
return keyp;
}
char snake::umove()
{
for(;y1>=0;y1--)
{
Sleep(200);
if(y1==0)
{
y1=21;
gotoxy(x1,1);
cout << " ";
}
if(y1!=21)
{
gotoxy(x1,y1+1);
cout << " ";
gotoxy(x1,y1);
cout << "*";
}
rcstar();
if(kbhit())
{
keyp=getch();
if(keyp=='s' || keyp=='S' || keyp=='w' || keyp=='W')
continue;
else
break;
}
}
return keyp;
}
char snake::dmove()
{
for(;y1<=22;y1++)
{
Sleep(200);
if(y1==22)
{
y1=1;
gotoxy(x1,21);
cout << " ";
}
if(y1!=1)
{
gotoxy(x1,y1-1);
cout << " ";
gotoxy(x1,y1);
cout << "*";
}
rcstar();
if(kbhit())
{
keyp=getch();
if(keyp=='w' || keyp=='W' || keyp=='s' || keyp=='S')
continue;
else
break;
}
}
return keyp;
}
char snake::movement(char keyp)
{
switch(keyp)
{
case 'w':
keyp=umove();
break;
case 's':
keyp=dmove();
break;
case 'd':
keyp=rmove();
break;
case 'a':
keyp=lmove();
break;
}
return keyp;
}
void snake::rcstar()
{
if(x1==x2 && y1==y2)
{
rstar();
n++;
}
gotoxy(65,8);
cout << "Score : " << n-1;
}
void snake::rstar()
{
x2 = rand()%61+1;
y2 = rand()%21+1;
gotoxy(x2, y2);
cout << "*";
}
void snake::options()
{
gotoxy(64,4);
cout << "[P] Pause";
gotoxy(64,5);
cout << "[K] Difficulty";
gotoxy(64,6);
cout << "[Q] Quit";
gotoxy(66,9);
cout << "High Score";
gotoxy(70,10);
cout << "0";
gotoxy(66,13);
cout << "SNAKE 2K ";
gotoxy(65,15);
cout << "Created By";
gotoxy(66,17);
cout << "Khurram";
}
And Here is main main.cpp file
main.cpp
#include <iostream>
#include <conio.h>
#include <windows.h>
#include "snake.h"
using namespace std;
int main()
{
snake a1;
char kph;
a1.load();
system("cls");
a1.frame();
a1.gotoxy(28,12);
cout << "*";
a1.rstar();
a1.options();
kph=getch();
do
{
if(kph=='w' || kph=='s' || kph=='a' || kph=='d')
kph=a1.movement(kph);
else if(kph=='q')
break;
else if(kph=='p' || kph=='P')
kph=getch();
else if(kph=='k' || kph=='K')
{ kph=a1.difficulty(); }
else
continue;
}
while(kph!='q');
a1.gotoxy(0,24);
return 0;
}
First of all i want to say that i know this code is really messed up but i'm beginner and still learning how to make a good program.
Please help me to complete this program.
You are going to need to save the coordinates (positions) of each segment of the snake. You will need to prepend a head and erase a tail segment. You will save the coordinates in a container.
There are many containers such as std::vector, std::list, std::stack and std::deque. I recommend std::deque. This allows you to push new segment coordinates into the back and pop the oldest segment from the top.
The std::deque structure allows growth too. You can push more items than you pop and also pop more than push (until the container is empty).
You can also do this the more difficult method and use an array or std::vector. You would erase the tail (using the coordinates at the end of the array), then move all the coordinates down (to make room for a new head coordinate), then set the first slot to the new coordinate.
Also, please invest some time with your debugger. Debugging your program is a lot faster than using StackOverflow to debug it. Most of us don't have the time to take your program, use a debugger, to find out where the issues are. If the issue is not obvious to most people in the first minute, your question is less likely to be answered (thus more downvotes).
Why are you making 3 programs. Here is how you do it. Make good use of OOP man !
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
bool gameOver;
const int width = 40;
const int height = 20;
int x, y, fruitX, fruitY, score;
int tailX[100], tailY[100];
int ntail;
enum edirecton { STOP = 0, LEFT, RIGHT, UP, DOWN };
edirecton dir;
void Setup()
{
gameOver = false;
dir = STOP;
x = width / 2;
y = height / 2;
fruitX = rand() % width;
fruitY = rand() % height;
score = 0;
}
void Draw()
{
system("cls");
for (int i = 0; i < width + 2; i++)
cout << "|";
cout << endl;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (j == 0)
cout << "|";
if (i == y && j == x)
cout << "O";
else if (i == fruitY && j == fruitX)
cout << "F";
else
{
bool print = false;
for (int k = 0; k < ntail; k++)
{
if (tailX[k] == j && tailY[k] == i)
{
cout << "o";
print = true;
}
}
if (!print)
cout << " ";
}
if (j == width - 1)
cout << "|";
}
cout << endl;
}
for (int i = 0; i < width + 2; i++)
cout << "|";
cout << endl;
cout << "Score= " << score << endl;
}
void Input()
{
if (_kbhit())
{
switch (_getch())
{
case 'a':
dir = LEFT;
break;
case 'd':
dir = RIGHT;
break;
case 'w':
dir = UP;
break;
case 's':
dir = DOWN;
break;
case 'x':
gameOver = true;
break;
}
}
}
void Logic()
{
int prevX = tailX[0];
int prevY = tailY[0];
int prev2X, prev2Y;
tailX[0] = x;
tailY[0] = y;
for (int i = 1; i < ntail; i++)
{
prev2X = tailX[i];
prev2Y = tailY[i];
tailX[i] = prevX;
tailY[i] = prevY;
prevX = prev2X;
prevY = prev2Y;
}
switch (dir)
{
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
case UP:
y--;
break;
case DOWN:
y++;
break;
default:
break;
}
//if (x > width || x<0 || y>height || y < 0)
//gameOver = true;
if (x >= width)
x = 0;
else if (x < 0)
x = width - 1;
if (y >= height)
y = 0;
else if (y < 0)
y = height - 1;
for (int i = 0; i < ntail; i++)
{
if (tailX[i] == x && tailY[i] == y)
gameOver = true;
}
if (x == fruitX && y == fruitY)
{
score += 10;
fruitX = rand() % width;
fruitY = rand() % height;
ntail++;
}
}
int main()
{
Setup();
while (!gameOver)
{
Draw();
Input();
Logic();
Sleep(80);
}
return 0;
}