[C++] Game Snake cơ bản cho người mới học C++

Giới thiệu

Game snake cơ bản:
– Di chuyển 4 phím mũi tên
– Rắn ăn thức ăn và lớn dẫn
– Score khởi đầu bằng 1 tương ứng độ dài khởi đầu của con rắn.

Dependences

Các class

  • Point.h
#pragma once
namespace SnakeGame {
    class Point
    {
    private:
        int x;
        int y;
    public:
        Point(int = 0, int = 0);
        void setXY(int, int);
        void draw(int, int,int,int) const;
        int getX() const;
        int getY() const;
        bool operator==(const Point&) const;
    };
};
  • Point.cpp
#include "Point.h"
#include <iostream>
#include <graphics.h>
using namespace std;
SnakeGame::Point::Point(int x, int y)
{
    this->setXY(x, y);
}
void SnakeGame::Point::setXY(int x, int y)
{
    this->x = x;
    this->y = y;
}
void SnakeGame::Point::draw(int cornerX, int corenrY, int unitWidth, int unitHeight) const
{
    fillellipse(cornerX+unitWidth / 2+this->x* unitWidth, cornerX + unitHeight / 2+ this->y* unitHeight, unitWidth/2, unitHeight/2);
}
int SnakeGame::Point::getX() const
{
    return this->x;
}
int SnakeGame::Point::getY() const
{
    return this->y;
}
bool SnakeGame::Point::operator==(const Point& other) const
{
    return this->getX() == other.getX() && this->getY() == other.getY();
}
  • Food.h
#pragma once
#include "Point.h"
namespace SnakeGame {
    class Food
    {
    private:
        SnakeGame::Point coord;
    public:
        Food(const SnakeGame::Point&);
        void draw(int,int,int,int) const;
        SnakeGame::Point getCoord() const;
    };
}
  • Food.cpp
#include "Food.h"
SnakeGame::Food::Food(const Point& coord)
{
    this->coord = coord;
}
void SnakeGame::Food::draw(int cornerX, int cornerY, int unitWidth, int unitHeight)const
{
    this->coord.draw(cornerX, cornerY, unitWidth, unitHeight);
}
SnakeGame::Point SnakeGame::Food::getCoord() const
{
    return this->coord;
}
  • Game.h
#pragma once
#include "Snake.h"
#include "Point.h"
#include "Food.h"
namespace SnakeGame{
    class Game
    {
    private:
        //objects
        Snake snake;
        Food food;
        //map
        Point leftCorner;
        int width;
        int height;
        int unitWidth;
        int unitHeight;
        //game state
        bool isGameOver;
        int score;
    public:
        Game();
        void run();
    };
}
  • Game.cpp
#include "Game.h"
#include <graphics.h>
#include <string>
#include <time.h>
using namespace std;
SnakeGame::Game::Game() :snake(Point(0, 0)), food(Point(10, 10))
{
    this->leftCorner.setXY(50, 50);
    this->width = 20;
    this->height = 20;
    this->unitHeight = 40;
    this->unitWidth = 40;
    this->isGameOver = false;
    this->score = 1;
    srand(time(NULL));
}
void SnakeGame::Game::run() 
{

    //set active page
    initwindow((this->width+1) * this->unitWidth +this->leftCorner.getX(), (this->height+1) * this->unitHeight + this->leftCorner.getY(), "Snake");
    setactivepage(1);
    setvisualpage(0);
    this->snake.setDirection(DIRECTIONS::RIGHT);
    while (!this->isGameOver) {
        cleardevice();
        //
        outtextxy(10, 10, _strdup("TOAN DEP TRAI - BLACKBLOG.NET"));
        outtextxy(10, 10+textheight(_strdup("BLACK MAN"))+5, _strdup(("Score:"+to_string(score)).c_str()));
        //draw grid
        setcolor(YELLOW);
        setlinestyle(DOTTED_LINE, 1, NORM_WIDTH);
        for (size_t i = 0; i <= this->width; i++)
        {
            line(this->leftCorner.getX() + i * this->unitWidth, this->leftCorner.getY(),
                this->leftCorner.getX() + i * this->unitWidth , this->leftCorner.getY()+ this->height * this->unitHeight);
        }
        for (size_t i = 0; i <= this->height; i++)
        {
            line(this->leftCorner.getX(), this->leftCorner.getY() + i * this->unitHeight,
                this->width * this->unitWidth+this->leftCorner.getX(),this->leftCorner.getY() + i * this->unitHeight);
        }
        //draw food
        setfillstyle(SOLID_FILL, GREEN);
        this->food.draw(this->leftCorner.getX(), this->leftCorner.getY(), this->unitWidth, this->unitHeight);
        //draw snake
        setfillstyle(SOLID_FILL, RED);
        this->snake.draw(this->leftCorner.getX(), this->leftCorner.getY(),this->unitWidth,this->unitHeight);

        //check direction
        if (kbhit()) {
            DIRECTIONS direction = DIRECTIONS::LEFT;
            if (getch() == 0) {
                int pressedKeyCode = getch();
                switch (pressedKeyCode)
                {
                case KEY_LEFT:
                    direction = DIRECTIONS::LEFT;
                    break;
                case KEY_RIGHT:
                    direction = DIRECTIONS::RIGHT;
                    break;
                case KEY_UP:
                    direction = DIRECTIONS::UP;
                    break;
                case KEY_DOWN:
                    direction = DIRECTIONS::DOWN;
                    break;
                }
                this->snake.setDirection(direction);
            }
        }

        //check if the snake can eat food
        if (this->snake.eatFood(this->food)) {
            //random new food location
            int newFoodIndex = rand() % (this->width*this->height);
            Point newFoodPoint(newFoodIndex % this->width, newFoodIndex % this->height);
            this->food = Food(newFoodPoint);
            this->score++;
        }
        this->snake.move();
        //check bounds
        if (this->snake.getHead().getX() < 0 || this->snake.getHead().getX() >= this->width || this->snake.getHead().getY() < 0 || this->snake.getHead().getY() >= this->height) {
            this->isGameOver = true;
        }

        setvisualpage((getvisualpage() + 1) % 2);
        setactivepage((getactivepage() + 1) % 2);
        delay(300);
    }
    //draw the last page
    setvisualpage((getvisualpage() + 1) % 2);
    setactivepage((getactivepage() + 1) % 2);
    outtextxy(this->leftCorner.getX()+getmaxx() / 2-textwidth(_strdup("The Stupid Snake!!!"))/2, this->leftCorner.getY() + getmaxy() / 2-textheight(_strdup("The Stupid Snake!!!")) / 2, _strdup("The Stupid Snake!!!"));
    //draw end game notification
    setvisualpage((getvisualpage() + 1) % 2);
    setactivepage((getactivepage() + 1) % 2);

    while (!kbhit()) {
        delay(300);
    }
}
  • main.cpp
#include "Game.h"
using namespace SnakeGame;
int main() {
    Game game;
    game.run();
    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *