C++ Snake Game Tail Bug - c++

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

Related

Void Print() function from class is outputting memory address of 2D array instead of printing values

I am doing an assignment where we have to make a sliding tile puzzle. The issue is that my print method for printing the game board is outputting the memory address of my 2D array instead of the actual values, but I have no idea how to fix this. I've tried looking up solutions and all I can find is stuff about vectors which I'm not allowed to use.
code from driver.cpp:
#include <iostream>
#include <conio.h>
#include "Specification.h"
#include <windows.h> //For color in PrintBoard()
using namespace std;
// direction codes (part of the slideTile() interface)
#define SLIDE_UP 1 // pass to slideTile() to trigger UP movement
#define SLIDE_DOWN 2 // pass to slideTile() to trigger DOWN movement
#define SLIDE_LEFT 3 // pass to slideTile() to trigger LEFT movement
#define SLIDE_RIGHT 4 // pass to slideTile() to trigger RIGHT movement
int main() {
int tempHeight;
int tempWidth;
// instantiate the class
cout << "Please enter the height for the board: ";
cin >> tempHeight;
cout << "Please enter the width for the board: ";
cin >> tempWidth;
bool exit = false;
SlidingPuzzle somePuzzle(tempHeight, tempWidth);
char keyStroke = ' ';
somePuzzle.isBoardSolved();
cout << "Press any key to begin..." << endl;
_getch();
cout << endl << "Scrambling the tiles..." << endl;
somePuzzle.ScrambleBoard();
cout << "Scrambling complete, press any key to begin solving." << endl;
_getch();
somePuzzle.isBoardSolved();
do {
cout << endl << "(w = Up, s = Down, a = Left, d = Right, e = Exit Game)" << endl;
cout << "Which way to slide?" << endl;
keyStroke = _getch(); //sets the key used to continue as the move, keys that aren't options do nothing
switch (keyStroke) {
case 'w':
{
somePuzzle.SlideTile(SLIDE_UP);
break;
}
case 's':
{
somePuzzle.SlideTile(SLIDE_DOWN);
break;
}
case 'a':
{
somePuzzle.SlideTile(SLIDE_LEFT);
break;
}
case 'd':
{
somePuzzle.SlideTile(SLIDE_RIGHT);
break;
}
case 'e':
{
exit = true;
somePuzzle.~SlidingPuzzle();
break;
}
}
} while (!somePuzzle.isBoardSolved() || !exit);
// Exit
_getch();
return 0;
}
code from specification.h:
#ifndef __SlidingPuzzle__
#define __SlidingPuzzle__
#include <iostream>
#include <windows.h> //For color in PrintBoard()
using namespace std;
// CLASS SlidingPuzzle
class SlidingPuzzle {
private:
int height;
int width;
int** theBoard;
int** solvedBoard;
HANDLE currentConsoleHandle;
void cls(HANDLE);
public:
// CONSTRUCTOR
SlidingPuzzle(); //Gives default values to the SlidingPuzzle's attributes
SlidingPuzzle(int, int);
//Deconstructor
~SlidingPuzzle();
//Getter
int getHeight();
int getWidth();
int** getTheBoard();
int** getSolvedBoard();
//Methods
void InitializeBoard();
bool isBoardSolved();
bool SlideTile(int);
void ScrambleBoard();
void PrintBoard();
}; // end - SlidingPuzzle
#endif
code from implementation.cpp:
#include "Specification.h"
// CONSTRUCTOR
SlidingPuzzle::SlidingPuzzle() {
this->height = 0;
this->width = 0;
this->theBoard = NULL;
this->solvedBoard = NULL;
this->currentConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
}
// Overload
SlidingPuzzle::SlidingPuzzle(int newWidth, int newHeight) {
this->currentConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
if (newHeight > 0) {
this->height = newHeight;
}
else {
this->height = 0;
}
if (newWidth > 0) {
this->width = newWidth;
}
else {
this->width = 0;
}
this->theBoard = new int* [this->height];
for (int i = 0; i < this->height; i++) {
this->theBoard[i] = new int[this->width];
}
this->solvedBoard = new int* [this->height];
for (int i = 0; i < this->height; i++) {
this->solvedBoard[i] = new int [this->width];
}
}
//Getters
int SlidingPuzzle::getHeight() {
return this->height;
}
int SlidingPuzzle::getWidth() {
return this->width;
}
int** SlidingPuzzle::getTheBoard() {
return this->theBoard;
}
int** SlidingPuzzle::getSolvedBoard() {
return this->solvedBoard;
}
//Deconstructor
SlidingPuzzle::~SlidingPuzzle() {
for (int i = 0; i < this->height; ++i)
delete[] this->theBoard[i];
delete[] this->theBoard;
}
//Methods
void SlidingPuzzle::InitializeBoard() {
for (int i = 0; i < this->height; i++) {
for (int j = 0; j < this->width; j++) {
if (i == 0) {
this->theBoard[i][j] = i + j + 1;
}
else if (i == 1) {
this->theBoard[i][j] = i + j + 3;
}
else {
this->theBoard[i][j] = i + j + 5;
if (this->theBoard[i][j] == (this->width * this->height)) {
this->theBoard[i][j] = -1;
}
}
}
}
}
bool SlidingPuzzle::isBoardSolved() {
this->cls(currentConsoleHandle);
this->PrintBoard();
int correct = 0;
//Checks each position to see if the are identical
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (this->theBoard[i][j] != this->solvedBoard[i][j]) {
correct = 1;
}
}
}
if (correct == 0) {
cout << "isBoardSolved(): true" << endl;
return true;
}
else {
cout << "isBoardSolved(): false" << endl;
return false;
}
}
bool SlidingPuzzle::SlideTile(int directionCode) {
int row = 0;
int col = 0;
int rowSpace = 0;
int colSpace = 0;
//Finds the pivot space
for (int i = 0; i < height; ++i) {
for (int j = 0; j < width; ++j) {
if (this->theBoard[i][j] == -1) {
row = i;
col = j;
}
}
}
switch (directionCode) {
case 1:
{
rowSpace = row - 1;
colSpace = col;
break;
}
case 2:
{
rowSpace = row + 1;
colSpace = col;
break;
}
case 3:
{
rowSpace = row;
colSpace = col - 1;
break;
}
case 4:
{
rowSpace = row;
colSpace = col + 1;
break;
}
}
//Ensures that the program doesn't break from trying to move off the board
if (rowSpace >= 0 && rowSpace < height && colSpace >= 0 && colSpace < width) {
this->theBoard[row][col] = this->theBoard[rowSpace][colSpace];
this->theBoard[rowSpace][colSpace] = -1;
}
return false;
}
void SlidingPuzzle::ScrambleBoard() {
for (int i = 0; i < 10000; i++) {
int move = (rand() % 4);
move++; //Add 1 so the variable matches the values for the directions
this->SlideTile(move);
}
}
void SlidingPuzzle::PrintBoard() { //Refuses to print, no clue why
HANDLE hConsole;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (this->theBoard[i][j] == -1) {
cout << " *";
}
else {
if (this->theBoard[i][j] == this->solvedBoard[i][j]) {
SetConsoleTextAttribute(hConsole, 2); //changes the color to green for correct postion
cout << " " << this->theBoard[i][j];
SetConsoleTextAttribute(hConsole, 15); //reverts color to normal
}
else {
SetConsoleTextAttribute(hConsole, 4); //changes the color to red for incorrect postion
cout << " " << this->theBoard[i][j];
SetConsoleTextAttribute(hConsole, 15); //reverts color to normal
}
}
}
cout << endl;
}
}
void SlidingPuzzle::cls(HANDLE hConsole)
{
COORD coordScreen = { 0, 0 }; /* here's where we'll home the
cursor */
BOOL bSuccess;
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */
DWORD dwConSize; /* number of character cells in
the current buffer */
/* get the number of character cells in the current buffer */
bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
/* fill the entire screen with blanks */
bSuccess = FillConsoleOutputCharacter(hConsole, (TCHAR)' ',
dwConSize, coordScreen, &cCharsWritten);
/* get the current text attribute */
bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi);
/* now set the buffer's attributes accordingly */
bSuccess = FillConsoleOutputAttribute(hConsole, csbi.wAttributes,
dwConSize, coordScreen, &cCharsWritten);
/* put the cursor at (0, 0) */
bSuccess = SetConsoleCursorPosition(hConsole, coordScreen);
}
I have used the suggestions from the comments and now I am finally getting the array to display. However the values in the array are still displaying as memory addresses. I updated the code here to reflect the changes made so far.
I forgot to add somePuzzle.InitializeBoard(); to the driver.cpp and I feel like a goof now. Thank you all for helping me and sorry about not posting a minimal reproducible example. Thank you Igor Tandetnik and Retired Ninja for pointing out the issues I had and helping me out.

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.

C++ snake dont move

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 .

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