'Assistance with c++ map<> type
I'm trying to make a snake clone that runs through the command prompt (baby steps) and I'm not too familiar with c++. Right now the issue I'm having is that when the snake "eats" the fruit the game loop stops. Without the addition of elongating the snake, it works. What I'm trying to do is have the snake body be a map that has an int key, with a tuple (x, y) coordinate. I think the issue is in the Move() function:
tempHead = make_tuple(x, y);
for (int i = 0; i < snakeBody.size(); i++) {
tempBody = snakeBody.find(i+1)->second;
snakeBody.find(i+1)->second = tempHead;
tempHead = tempBody;
}
I'm probably trying to read and put values into the map wrong, which is what I think is the issue but I don't know how I'm supposed to do it. Any help is greatly appreciated. I'm also open to feedback on ways to be doing this better, but I couldn't think of one. Full code (in case I misidentified the issue):
#include <iostream>
#include <chrono>
#include <thread>
#include <string>
#include <Windows.h>
#include <map>
using namespace std;
//time waited before redrawing the screen in miliseconds
chrono::milliseconds timespan(100);
bool gameOver;
//size of the game
const int width = 20;
const int height = 20;
//number of squares
const int area = width * height;
int x, y, fruitX, fruitY, score;
//tuples for storing (x,y) coords for moving the snake along
tuple<int, int> tempHead;
tuple<int, int> tempBody;
enum class eDirection { STOP = 0, LEFT = 1, RIGHT = 2, UP = 3, DOWN = 4};
eDirection dir;
//a map containing key, value pairs of (segment, tuple<x, y>)
map<int, tuple<int, int>> snakeBody;
void Setup() {
//you're not losing the game yet
gameOver = false;
//snake isn't moving
dir = eDirection::STOP;
//centered snake
x = width / 2;
y = height / 2;
snakeBody.insert(make_pair(1, make_tuple(x, y)));
//random gen fruit
fruitX = rand() % width;
fruitY = rand() % height;
//clear score
score = 0;
}
void Draw() {
//clear the screen
system("cls");
//top row
for (int i = 0; i < width; i++) {
cout << "#";
}
cout << endl;
//draw the board
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
//fruit
if (j == fruitX && i == fruitY) {
cout << ".";
}
//walls
else if (j == 0 || j == width - 1) {
cout << "#";
}
//snake
else if (j == x && i == y) {
cout << "0";
}
//empty
else {
cout << " ";
}
}
cout << endl;
}
//bottom row
for (int i = 0; i < width; i++) {
cout << "#";
}
cout << endl;
cout << score;
}
//movement keys are wasd
void Input() {
if (GetAsyncKeyState('W') & 0x8000) {
dir = eDirection::UP;
}
if (GetAsyncKeyState('A') & 0x8000) {
dir = eDirection::LEFT;
}
if (GetAsyncKeyState('S') & 0x8000) {
dir = eDirection::DOWN;
}
if (GetAsyncKeyState('D') & 0x8000) {
dir = eDirection::RIGHT;
}
}
int Move(eDirection dir) {
//where to move the head to
if (dir == eDirection::UP) {
y -= 1;
}
if (dir == eDirection::DOWN) {
y += 1;
}
if (dir == eDirection::LEFT) {
x -= 1;
}
if (dir == eDirection::RIGHT) {
x += 1;
}
if (dir == eDirection::STOP) {
x = x;
y = y;
}
//replace each value in snakeBody with the one ahead of it
tempHead = make_tuple(x, y);
for (int i = 0; i < snakeBody.size(); i++) {
tempBody = snakeBody.find(i+1)->second;
snakeBody.find(i+1)->second = tempHead;
tempHead = tempBody;
}
return 0;
}
//adds the given x,y to the map with an auto-incremented key
int increaseSnake(map<int, tuple<int, int>> map, int x, int y) {
int mapSize = map.size();
while (map.size() < area){
map.insert(make_pair(mapSize + 1, make_tuple(x, y)));
}
return 0;
}
void Logic() {
Move(dir);
//if the snake "eats" fruit
if (x == fruitX && y == fruitY) {
score += 1;
fruitX = rand() % width;
fruitY = rand() % height;
increaseSnake(snakeBody, x, y);
}
//if the snake touches a wall
if (x == width - 1 || x == 0 || y == height - 1 || y == -2) {
gameOver = true;
}
}
int main() {
Setup();
//gameloop
while (!gameOver) {
Draw();
Input();
Logic();
//reduce flickering
this_thread::sleep_for(timespan);
}
//gameover screen
cout << endl;
cout << "Game over! You scored: " << score << endl;
cout << "pause";
return 0;
}
Solution 1:[1]
In here
while (map.size() < area){
map.insert(make_pair(mapSize + 1, make_tuple(x, y)));
}
At start
map.size() == 1
area == width * height == 40
When you get in increaseSnake(), wouldn't that loop add same (x, y) coordinates for 40 times.
You probably wanted an if condition.
If increaseSnake() always gonna return 0, why even have it.
You should use std::vector<std::pair<int, int>> instead.
When finding for a key in map, you should check if the key is really found before using the return value. But better use above suggestion instead.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | vikram |
