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");
}
}
Related
Me and my group is making a game for our project and I keep running into this error, after some testing, it looks like it happens at the end of the main function. I have no idea how this happen as most of the code is from our teacher, we need to fix the intentional bugs placed by him and add additional functionalities.
This is the code:
#include <winuser.h>
#include <iostream>
#include <time.h>
#include <conio.h>
#include <thread>
using namespace std;
#define MAX_CAR 5
#define MAX_CAR_LENGTH 40
#define MAX_SPEED 3
POINT** X;
POINT Y;
int cnt = 0;
int MOVING;
int SPEED;
int HEIGHT_CONSOLE = 29, WIDTH_CONSOLE = 119;
bool STATE;
void FixConsoleWindow() {
HWND consoleWindow = GetConsoleWindow();
LONG_PTR style = GetWindowLongPtr(consoleWindow, GWL_STYLE);
style = style & ~(WS_MAXIMIZEBOX) & ~(WS_THICKFRAME);
SetWindowLongPtr(consoleWindow, GWL_STYLE, style);
}
void GotoXY(int x, int y) {
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void ResetData() {
MOVING = 'D';
SPEED = 1;
Y = { 18, 19 };
if (X == NULL) {
X = new POINT * [MAX_CAR];
for (int i = 0; i < MAX_CAR; i++) {
X[i] = new POINT[MAX_CAR_LENGTH];
}
for (int i = 0; i < MAX_CAR; i++) {
int temp = rand() % (WIDTH_CONSOLE - MAX_CAR_LENGTH) + 1;
for (int j = 0; j < MAX_CAR_LENGTH; j++) {
X[i][j].x = temp + j;
X[i][j].y = 2 + 5 * i;
}
}
}
}
void DrawBoard(int x, int y, int width, int height, int curPosX = 0, int curPosY = 0) {
GotoXY(x, y);
for (int i = 1; i < width; i++) {
cout << 'X';
}
cout << 'X';
GotoXY(x, height + y);
for (int i = 1; i < width; i++) {
cout << 'X';
}
cout << 'X';
for (int i = y + 1; i < height + y; i++) {
GotoXY(x, i);
cout << 'X';
GotoXY(x + width, i);
cout << 'X';
}
GotoXY(curPosX, curPosY);
}
void StartGame() {
system("cls");
ResetData();
DrawBoard(0, 0, WIDTH_CONSOLE, HEIGHT_CONSOLE);
STATE = true;
}
void GabageCollect() {
for (int i = 0; i < MAX_CAR; i++) {
delete[] X[i];
}
delete[] X;
}
void ExitGame(HANDLE t) {
GabageCollect();
system("cls");
TerminateThread(t, 0);
}
void PauseGame(HANDLE t) {
SuspendThread(t);
}
void ProcessDeath() {
STATE = false;
GotoXY(0, HEIGHT_CONSOLE + 2);
cout << "Dead, type y to continue or any key to exit";
}
void ProcessFinish(POINT& p) {
SPEED == MAX_SPEED ? SPEED = 1 : SPEED++;
p = { 18,19 };
MOVING = 'D';
}
void DrawCars() {
for (int i = 0; i < MAX_CAR; i++) {
for (int j = 0; j < MAX_CAR_LENGTH; j++) {
GotoXY(X[i][j].x, X[i][j].y);
std::cout << '.';
}
}
}
void DrawPlayer(const POINT& p, char s) {
GotoXY(p.x, p.y);
cout << s;
}
bool IsImpact(const POINT& p) //d=Y.y p = Y
{
if (p.y == 1 || p.y == 19) return false;
for (int i = 0; i < MAX_CAR; i++)
{
for (int j = 0; j < MAX_CAR_LENGTH; j++)
{
if (p.x == X[i][j].x && p.y == X[i][j].y) return true;
}
}
return false;
}
void MoveCars(int x1, int y1)
{
for (int i = 1; i < MAX_CAR; i += 2)
{
cnt = 0;
do
{
cnt++;
for (int j = 0; j < MAX_CAR_LENGTH - 1; j++)
{
X[i][j] = X[i][j + 1];
}
X[i][MAX_CAR_LENGTH - 1].x + 1 == WIDTH_CONSOLE + x1 ? X[i][MAX_CAR_LENGTH - 1].x = 1 : X[i][MAX_CAR_LENGTH - 1].x++;
} while (cnt < SPEED);
}
for (int i = 0; i < MAX_CAR; i += 2)
{
cnt = 0;
do
{
cnt++;
for (int j = MAX_CAR_LENGTH - 1; j > 0; j--)
{
X[i][j] = X[i][j - 1];
}
X[i][0].x - 1 == 0 + x1 ? X[i][0].x = WIDTH_CONSOLE + x1 - 1 : X[i][0].x--;
} while (cnt < SPEED);
}
}
void EraseCars()
{
for (int i = 0; i < MAX_CAR; i += 2)
{
cnt = 0;
do
{
GotoXY(X[i][MAX_CAR_LENGTH - 1 - cnt].x, X[i][MAX_CAR_LENGTH - 1 - cnt].y);
cout << " ";
cnt++;
} while (cnt < SPEED);
}
for (int i = 1; i < MAX_CAR; i += 2)
{
cnt = 0;
do
{
GotoXY(X[i][0 + cnt].x, X[i][0 + cnt].y);
cout << " ";
cnt++;
} while (cnt < SPEED);
}
}
void MoveRight()
{
if (Y.x < WIDTH_CONSOLE - 1)
{
DrawPlayer(Y, ' ');
Y.x++;
DrawPlayer(Y, 'Y');
}
}
void MoveLeft()
{
if (Y.x > 1)
{
DrawPlayer(Y, ' ');
Y.x--;
DrawPlayer(Y, 'Y');
}
}
void MoveDown()
{
if (Y.y < HEIGHT_CONSOLE - 1)
{
DrawPlayer(Y, ' ');
Y.y++;
DrawPlayer(Y, 'Y');
}
}
void MoveUp()
{
if (Y.y > 1)
{
DrawPlayer(Y, ' ');
Y.y--;
DrawPlayer(Y, 'Y');
}
}
void SubThread()
{
while (1)
{
if (STATE)
{
switch (MOVING)
{
case 'A':
MoveLeft();
break;
case 'D':
MoveRight();
break;
case'W':
MoveUp();
break;
case'S':
MoveDown();
break;
}
MOVING = ' ';
EraseCars();
MoveCars(0, 0);
DrawCars();
if (IsImpact(Y))
{
ProcessDeath();
}
if (Y.y == 1)
{
ProcessFinish(Y);
Sleep(50);
}
}
}
}
void main()
{
int temp;
FixConsoleWindow();
srand(time(NULL));
StartGame();
thread t1(SubThread);
while (1)
{
temp = toupper(_getch());
if (STATE == 1)
{
EraseCars();
if (temp == 27)
{
ExitGame(t1.native_handle());
break;
}
else if (temp == 'P')
{
PauseGame(t1.native_handle());
temp = toupper(_getch());
if (temp == 'B')
ResumeThread((HANDLE)t1.native_handle());
}
else
{
if (temp == 'D' || temp == 'A' || temp == 'W' || temp == 'S')
{
MOVING = temp;
}
}
}
else
{
if (temp == 'Y') StartGame();
else
{
ExitGame(t1.native_handle());
break;
}
}
}
}
And this is the image of the error: https://imgur.com/PGJJX2w
Basically, this is a crossing road game, every time you go to the top, it saves the location and you cannot go that location again (still working on this), game finish when you run into the cars (lines of dots as of the moment). Thanks in advance
You created a std::thread object here:
thread t1(SubThread);
but you didn't call join() nor detach() for that.
This causes that std::terminate() is called (the program aborts) when the object is destructed.
Call t1.join() if you want to wait until the thread ends or t1.detach() if you want to let the thread run freely before returning from the main() function.
Another option is using CreateThread() directly instead of std::thread to create threads. This may be better because you are using t1.native_handle() for operations on the thread.
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.
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 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];
}
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.