vendredi 27 janvier 2017

Snake console game with a twist

For an assignement I need to rewrite this code http://ift.tt/2kBDSyW to make the snake 2 characters thick.

My idea was to add new variables attached to the original coordinates, which basically produce a total mess without any consistence to it. How to avoid it? What seem to be the problems are:
1. I can't figure how to rotate the snake while going horizontally? Everything is okay when the snake goes up or down, horizontally it becomes a mess.
2. The tail breaks the map
3. The original code has a bug to it which allows the fruit to spawn on the snake's body

Just for the record, I know the game flickers, system() are evil, its functions are poorly designed and no OOP included whatsoever. That's what I have to work with and I'm stuck. This is what I came up with so far:

#include <iostream>
#include <conio.h>
#include <windows.h>
#include <array>
#include <random>

const int mapwidth = 40;
const int mapheight = 20;
int headX, headY, fruitX, fruitY;
int headX2, headY2;
bool gameover;
enum Direction { UP, LEFT, RIGHT, DOWN }; 
Direction dir;
int tailLenght;
std::array<int, 100> tailX, tailY;
std::array<int, 100> tailX2, tailY2;

void Start()
{
    gameover = false;
    headX = mapwidth / 2;
    headX2 = headX + 1;
    headY = mapheight / 2;
    headY2 = headY;
    std::random_device rd;
    std::uniform_int_distribution<int> dist{ 0, mapwidth };
    fruitX = dist(rd);
    std::uniform_int_distribution<int> distheight{ 0, mapheight };
    fruitY = distheight(rd);
    tailLenght = 0;
}

void Map()
{
    system("cls");
    for (int i = 0; i < mapwidth + 2; i++)
    {
        std::cout << "#";
    }
    std::cout << std::endl;

for (int i = 0; i < mapheight; i++)
    {
        for (int j = 0; j < mapwidth; j++)
        {
            if (j == 0)
                std::cout << "#";
            if ((i == headY && j == headX) || (i == headY2 && j == headX2))
                std::cout << "O";
            else if (i == fruitY && j == fruitX)
                std::cout << "*";
            else
            {
                bool printedSegment = false;
                for (int k = 0; k < tailLenght; k++)
                {
                    if ((tailX[k] == j && tailY[k] == i) || (tailX2[k] == j && tailY2[k] == i))
                    {
                        std::cout << "o";
                        printedSegment = true;
                    }
                }
                if (!printedSegment)
                    std::cout << " ";
            } 
            if (j == mapwidth - 1)
                std::cout << "#";
        }
        std::cout << std::endl;
    }
    for (int i = 0; i < mapwidth + 2; i++)
    {
        std::cout << "#";
    }
    std::cout << std::endl;
    std::cout << "Current score: " << tailLenght << std::endl;
}
void Controls()
{
    if (_kbhit()) {
        switch (_getch()) {
        case 'w':
        case 'W':
            dir = UP;
            break;
        case 'a':
        case 'A':
            dir = LEFT;
            break;
        case 's':
        case 'S':
            dir = DOWN;
            break;
        case 'd':
        case 'D':
            dir = RIGHT;
            break;
        case 'x':
        case 'X':
            gameover = true;
            break;

        default:
            break;
        }
    }
}
void Gameplay() 
{
    int prevX = tailX[0];
    int prevX2 = tailX2[0];
    int prevY = tailY[0];
    int prevY2 = tailY2[0];
    int prev2X, prev2Y, prev2X2, prev2Y2;
    tailX[0] = headX;
    tailX2[0] = headX2;
    tailY[0] = headY;
    tailY2[0] = headY2;
    for (int i = 1; i < tailLenght; i++)
    {
        prev2X = tailX[i];
        prev2X2 = tailX2[i];
        prev2Y = tailY[i];
        prev2Y2 = tailY2[i];
        tailX[i] = prevX;
        tailX2[i] = prevX2;
        tailY[i] = prevY;
        tailY2[i] = prevY2;
        prevX = prev2X;
        prevX2 = prev2X2;
        prevY = prev2Y;
        prevY2 = prev2Y2;
    }
    switch (dir)
    {
    case UP:
        headY--;
        headY2--;
        break;
    case LEFT:
        headX--;
        headX2--;
        break;
    case RIGHT:
        headX++;
        headX2++;
        break;
    case DOWN:
        headY++;
        headY2++;
        break;
    default:
        break;
    }

    if (headX > mapwidth || headX<0 || headY > mapheight || headY < 0)
        gameover = true;

    if ((headX == fruitX && headY == fruitY) || (headX2 == fruitX && headY2 == fruitY))
    {
        tailLenght++;
        std::random_device rd;
        std::uniform_int_distribution<int> fx{ 0, mapwidth };
        fruitX = fx(rd);
        std::uniform_int_distribution<int> fy{ 0, mapheight };
        fruitY = fy(rd);
    }
}
int main()
{
    Start();
    while (!gameover)
    {
        Map();
        Controls();
        Gameplay();
    }
    Sleep(100);
    return 0;
}

Aucun commentaire:

Enregistrer un commentaire