hi so i have an error in my code and i don’t know how to fix it its in c++ and when i try to run my code it wont let me i debugged and i says “snake 4.0.exe has triggered a breakpoint.” could someone help???
Would need a lot more information than that.
ok so here’s the code
(yes its long sorry)
#include <iostream>
#include <list>
#include <thread>
using namespace std;
#include <Windows.h>
int x, y;
enum eDirecton { STOP = 0, LEFT, RIGHT, UP, DOWN };
eDirecton dir;
int nScreenWidth = 120;
int nScreenHeight = 30;
struct sSnakeSegment
{
int x;
int y;
};
int main()
{
// Create Screen Buffer
wchar_t* screen = new wchar_t[nScreenWidth * nScreenHeight];
for (int i = 0; i < nScreenWidth * nScreenHeight; i++) screen[i] = L' ';
HANDLE hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
SetConsoleActiveScreenBuffer(hConsole);
DWORD dwBytesWritten = 0;
while (1)
{
// Reset to known state
list<sSnakeSegment> snake = { {60,15},{61,15},{62,15},{63,15},{64,15},{65,15},{66,15},{67,15},{68,15},{69,15} };
int nFoodX = 30;
int nFoodY = 15;
int nScore = 0;
int nSnakeDirection = 3;
bool bDead = false;
while (!bDead)
{
// Frame Timing, compensate for aspect ratio of command line
auto t1 = chrono::system_clock::now();
switch ((chrono::system_clock::now() - t1) < ((nSnakeDirection % 2 == 1) ? 120ms : 200ms))
{
case 'a':
dir = LEFT;
break;
case 'd':
dir = RIGHT;
break;
case 'w':
dir = UP;
break;
case 's':
dir = DOWN;
break;
}
// ==== Logic
// Update Snake Position, place a new head at the front of the list in
// the right direction
switch (nSnakeDirection)
{
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
case UP:
y--;
break;
case DOWN:
y++;
break;
default:
break;
}
// Collision Detect Snake V Food
if (snake.front().x == nFoodX && snake.front().y == nFoodY)
{
nScore++;
while (screen[nFoodY * nScreenWidth + nFoodX] != L' ')
{
nFoodX = rand() % nScreenWidth;
nFoodY = (rand() % (nScreenHeight - 3)) + 3;
}
for (int i = 0; i < 5; i++)
snake.push_back({ snake.back().x, snake.back().y });
}
// Collision Detect Snake V World
if (snake.front().x < 0 || snake.front().x >= nScreenWidth)
bDead = true;
if (snake.front().y < 3 || snake.front().y >= nScreenHeight)
bDead = true;
// Collision Detect Snake V Snake
for (list<sSnakeSegment>::iterator i = snake.begin(); i != snake.end(); i++)
if (i != snake.begin() && i->x == snake.front().x && i->y == snake.front().y)
bDead = true;
// Chop off Snakes tail :-/
snake.pop_back();
// ==== Presentation
// Clear Screen
for (int i = 0; i < nScreenWidth * nScreenHeight; i++) screen[i] = L' ';
// Draw Stats & Border
for (int i = 0; i < nScreenWidth; i++)
{
screen[i] = L'=';
screen[2 * nScreenWidth + i] = L'=';
}
wsprintf(&screen[nScreenWidth + 5], L"jcta gaming - S N A K E ! ! SCORE: %d", nScore);
// Draw Snake Body
for (auto s : snake)
screen[s.y * nScreenWidth + s.x] = bDead ? L'+' : L'O';
// Draw Snake Head
screen[snake.front().y * nScreenWidth + snake.front().x] = bDead ? L'X' : L'@';
// Draw Food
screen[nFoodY * nScreenWidth + nFoodX] = L'%';
if (bDead)
wsprintf(&screen[15 * nScreenWidth + 40], L" PRESS 'SPACE' TO PLAY AGAIN ");
// Display Frame
WriteConsoleOutputCharacter(hConsole, screen, nScreenWidth * nScreenHeight, { 0,0 }, &dwBytesWritten);
}
// Wait for space
while ((0x8000 & GetAsyncKeyState((unsigned char)('\x20'))) == 0);
}
return 0;
}
ok so that’s the code and when I compile and run it it says i hit a break point and bring me here
could that help???
The message is pretty clear. You are accessing an empty list.
Why is it empty? Because you only ever remove from it, you never add to the direction the snake is going in.
ok so what should i do???
Are you following a tutorial by any chance?
i was but i stopped cause i wanted to see if i could finish it and the controls where weird so I’m traying to change them.
Add to the list
// Update Snake Position, place a new head at the front of the list in
// the right direction
switch (nSnakeDirection)
{
case LEFT:
x--;
break;
case RIGHT:
x++;
break;
case UP:
y--;
break;
case DOWN:
y++;
break;
default:
break;
}
This doesn’t do what the comment says, it just modifies x and y and the rest of your code doesn’t use them at all. This block is the only instance x
and y
are used.
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo i kind of get it now i see
soooooooooooooooooooooooooooo should i delete it???
sooooooooooo it still dint work im so confused
Could you link the tutorial you are following?
…hello?
Please allow for 48 hours before bumping your thread. As yours is not related to the course I’ve given you lower priority to others.
You’ve steered away quite a bit from what’s done in that tutorial which I guess explains some of the other issues I saw in your code.
I’ll try and get back to you regarding that tomorrow. I have a doctors appoint so might not be until the weekend, however. Sorry.
ok thanks and good luck with your doctors appointment
Let’s compare some of the code. To start, since I’m not familiar with the Win32 API I had to look up what
(0x8000 & GetAsyncKeyState((unsigned char)('\x27'))) != 0;
was for. looking at the docs, GetAsyncKeyState returns a SHORT (2 bytes) where the most significant bit is set if the key is pressed since the last call and if it’s currently pressed. The least significant bit is set if it was pressed since the last time GetAsyncState was called however it states you shouldn’t rely on that behaviour. So & 0x8000
is testing to see if the first part is true. And 0x27
is for the right arrow key.
Whilst looking at the docs there’s a macro for the right arrow key VK_RIGHT
so I substituted it in the code to make it easier to read. Others can be found here https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
So with that out of the way and after the initial setup of variables there’s this code
auto t1 = chrono::system_clock::now();
while ((chrono::system_clock::now() - t1) < ((nSnakeDirection % 2 == 1) ? 120ms : 200ms))
This is looping for 120ms or 200ms depending on the direction of the snake.
Within that loop you have this
// Get Input,
bKeyRight = 0x80'00 & GetAsyncKeyState(VK_RIGHT);
bKeyLeft = 0x80'00 & GetAsyncKeyState(VK_LEFT);
if (bKeyRight && !bKeyRightOld)
{
nSnakeDirection++;
if (nSnakeDirection == 4) nSnakeDirection = 0;
}
if (bKeyLeft && !bKeyLeftOld)
{
nSnakeDirection--;
if (nSnakeDirection == -1) nSnakeDirection = 3;
}
bKeyRightOld = bKeyRight;
bKeyLeftOld = bKeyLeft;
Which first gets whether the left and right arrow key is pressed, tests whether the right arrow key is pressed and wasn’t previously pressed and adds to the direction (clockwise) if true. Same with left and deducting. It then sets the variables that store the old values (remember that whilst you can get that by checking the least significant bit of GetAsyncKeyState you shouldn’t rely on it).
Instead of that you have this
auto t1 = chrono::system_clock::now();
switch ((chrono::system_clock::now() - t1) < ((nSnakeDirection % 2 == 1) ? 120ms : 200ms))
{
case 'a':
dir = LEFT;
break;
case 'd':
dir = RIGHT;
break;
case 'w':
dir = UP;
break;
case 's':
dir = DOWN;
break;
}
This is doing a switch statement on whether or not it’s been 120ms or 200ms since t1
which is likely to always be true. This also means you’re switching on bool
not char
as your case statements imply it is. So that should mean dir is always left.
Next OLC has
switch (nSnakeDirection)
{
case 0: // UP
snake.push_front({ snake.front().x, snake.front().y - 1 });
break;
case 1: // RIGHT
snake.push_front({ snake.front().x + 1, snake.front().y });
break;
case 2: // DOWN
snake.push_front({ snake.front().x, snake.front().y + 1 });
break;
case 3: // LEFT
snake.push_front({ snake.front().x - 1, snake.front().y });
break;
}
which uses the calculated direction and adds to the front of the snake in that calculated direction. And as from the last post, yours just increments some ints and never adds to the list.
ok so i did what you said i analyzed it and copied it into my code like i think you told me to BUT when I compile and run the program the snake bugs out and hits a wall immediately which ends the game.
it doesn’t show any errors tho…
this is what i added
`while (!bDead)
{
// Frame Timing, compensate for aspect ratio of command line
auto t1 = chrono::system_clock::now();
while ((chrono::system_clock::now() - t1) < ((nSnakeDirection % 2 == 1) ? 120ms : 200ms))
{
bKeyRight = 0x80’00 & GetAsyncKeyState(VK_RIGHT);
bKeyLeft = 0x80’00 & GetAsyncKeyState(VK_LEFT);
if (bKeyRight && !bKeyRightOld)
{
nSnakeDirection++;
if (nSnakeDirection == 4) nSnakeDirection = 0;
}
if (bKeyLeft && !bKeyLeftOld)
{
nSnakeDirection--;
if (nSnakeDirection == -1) nSnakeDirection = 3;
}
bKeyRightOld = bKeyRight;
bKeyLeftOld = bKeyLeft;
// ==== Logic
// Update Snake Position, place a new head at the front of the list in
// the right direction
switch (nSnakeDirection)
{
case 0: // UP
snake.push_front({ snake.front().x, snake.front().y - 1 });
break;
case 1: // RIGHT
snake.push_front({ snake.front().x + 1, snake.front().y });
break;
case 2: // DOWN
snake.push_front({ snake.front().x, snake.front().y + 1 });
break;
case 3: // LEFT
snake.push_front({ snake.front().x - 1, snake.front().y });
break;
}`