C++ snake dont move - c++

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 .

Related

Separating the code in header.h, main.cpp and implementation.cpp

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.

How to update console without flickering and get keyboard input in C++

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");
}
}

C++ Snake Game Tail Bug

I want to create a simple snake game using console C++. I'm currently creating the tail part of the snake. When the snake eats the fruit, it adds a section to its tail. The problem is that the game runs well until the 3rd fruit. At this moment, though a tail section is added to the snake, it will move awkwardly and will shift the right wall.
here's the code :
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include<time.h>
using namespace std;
// =========== VARIABLES ===========
bool gameOver;
const int width = 20;
const int height = 20;
int x, y, fruitX, fruitY, score;
enum eDirection {STOP = 0, LEFT, RIGHT, UP, DOWN};
eDirection dir;
//arrays
int tailx[50],taily[50];
int ntail=0;
// =========== INITIALIZATION ===========
void setup()
{
gameOver = false;
//snake is not moving
srand(time(0));
dir = STOP ;
// center the snake on the map
x = width/2;
y = height/2;
// randomize fruit position
fruitX = rand()%width;
fruitY = rand()%height;
score = 0;
}
void Draw()
{
//clear screen
system("cls");
// ======== DRAW MAP ========
//display top border of map
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)
cout <<"#";
//display the head
if (x==j && y==i)
cout << "o";
// display the fruit
else if (fruitX == j && fruitY == i)
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;
}
//display bottom border
for (int i =0; i< width+2; i++)
cout << "#" ;
cout<<endl;
//display score
cout<< "Score : " << score<<endl;
//debug
cout << "ntail : " << ntail << endl ;
cout << "width : " << width << endl ;
}
void Input()
{
if (_kbhit())
{
//leyboard control input
switch (_getch())
{
case 'q':
dir = LEFT;
break;
case 'z':
dir = UP;
break;
case 's':
dir = DOWN;
break;
case 'd':
dir = RIGHT;
break;
case 'x':
gameOver = true;
break;
default :
break;
}
}
}
void logic()
{
//remember previous position
int prevx = tailx[0];
int prevy = taily[0];
int prev2x,prev2y;
tailx[0] = x;
taily[0] = y;
for (int i=1; i<ntail; i++)
{
//remember current position
prev2x = tailx[i];
prev2y = taily[i];
// change value
tailx[i] = prevx;
taily[i] = prevy;
prevx = tailx[i];
prevy = taily[i];
}
// movement management
switch (dir)
{
case DOWN :
if (y<=height)
y++;
break;
case UP:
if (y>=0)
y--;
break;
case LEFT:
if (x>=0)
x--;
break;
case RIGHT:
if (x<=width)
x++;
break;
default :
break;
}
// if the snake hits the wall
//if (x == width || y =z= height || x == 0 || y == 0)
// gameOver = true;
//if the snake eats a fruit
// score display and new fruit apparition
if (x==fruitX && y==fruitY)
{
score += 10;
fruitX = rand()%width;
fruitY = rand()%height;
ntail++;
}
}
int main()
{
setup();
while (!gameOver)
{
Draw();
Input();
logic();
Sleep(100);
}
return 0;
}
Got it in void logic() function, it should've been :
for (int i=1; i<ntail; i++)
{
//remember current position
prev2x = tailx[i];
prev2y = taily[i];
// change value
tailx[i] = prevx;
taily[i] = prevy;
prevx = prev2x;
prevy = prev2y;
}
instead of
for (int i=1; i<ntail; i++)
{
//remember current position
prev2x = tailx[i];
prev2y = taily[i];
// change value
tailx[i] = prevx;
taily[i] = prevy;
prevx = tailx[i];
prevy = taily[i];
}

Why my keyboard hit is evaluating false

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.

Making Snake Game in Cpp Movement of Snake

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;
}