zoukankan      html  css  js  c++  java
  • C++贪吃蛇小游戏 list版本 改进版本

    /*-----------------------------------------------
    自制简易版贪吃蛇 用list 取代了原先的vector结构 ,并且独立出了食物类,
    使食物和蛇区分开来产生 感觉这种框架更容易实现后续的蛇蛇大作战 。
    对于改变direction使用了多线程,玩家操作太快(比如方向是A,快速按了W和D)

    容易导致反方向运动,蛇蛇直接死亡。20191008

    添加change 变量修复了bug 20191009

    ------------------------------------------------*/

    //Food.h begin--------------------------------------------------------------------------------------
    #ifndef _FOOD_H_
    #define _FOOD_H_

    #include"Point.h"
    #include"Snake.h"
    #include<list>
    using namespace std;
    class Snake;

    class Food
    {
    private:
    Point food;
    public:
    Food();
    Food(Point F);
    void print();
    void set_food(Point F);
    Point get_food();
    //判断是否应该产生食物。
    bool IsFood(list<Point>body);
    };

    #endif // !_FOOD_H_

    //Food.h end--------------------------------------------------------------------------------------

    //Point.h begin--------------------------------------------------------------------------------------

    #ifndef _POINT_H_
    #define _POINT_H_
    class Point
    {
    private:
    int x;
    int y;
    public:
    Point() :x(0), y(0) {};
    Point(int X, int Y) :x(X), y(Y) {};
    int get_x();
    int get_y();
    void set_x(int);
    void set_y(int);
    //重载 == 用于判断吃到食物和死完。
    bool operator ==(const Point &A)const
    {
    if (this->x == A.x && this->y == A.y)
    return true;
    return false;
    }

    };

    #endif // !_POINT_H_

    //Point.h end--------------------------------------------------------------------------------------

    //Snake.h begin--------------------------------------------------------------------------------------

    #ifndef _SNAKE_H_
    #define _SNAKE_H_
    #include<list>
    #include"Point.h"
    #include"Food.h"

    #include<graphics.h>
    using namespace std;
    class Food;
    class Snake
    {
    private:
    list<Point>body;
    int len;
    int direction;
    public:
    Snake();
    Snake(Point head);
    int get_len();
    int get_direction();
    //改变方向
    void set_direction(int);
    //移动
    void move();
    //打印
    void print(PIMAGE snake_img);
    //返回身体
    list<Point> get_body();
    //吃饭
    void eat_food(Food);
    };

    #endif // !_SNAKE_H_

    //Snake.h end--------------------------------------------------------------------------------------

    //Point.cpp begin--------------------------------------------------------------------------------------

    #include"Point.h"

    int Point::get_x()
    {
    return x;
    }

    int Point::get_y()
    {
    return y;
    }

    void Point::set_x(int X)
    {
    x = X;
    }
    void Point::set_y(int Y)
    {
    y = Y;
    }

    //Point.cpp end--------------------------------------------------------------------------------------

    //Food.cpp begin--------------------------------------------------------------------------------------

    #include"Food.h"
    #include<graphics.h>
    Food::Food()
    {

    }
    Food::Food(Point F)
    {
    food.set_x(F.get_x());
    food.set_y(F.get_y());
    }
    void Food::print()
    {
    bar(food.get_x() * 10, food.get_y() * 10, food.get_x() * 10 + 10, food.get_y() * 10 + 10);
    }

    //设置食物
    void Food::set_food(Point F)
    {
    food.set_x(F.get_x());
    food.set_y(F.get_y());
    }

    //获取食物
    Point Food::get_food()
    {
    return food;
    }

    //判断是否加食物
    bool Food::IsFood(list<Point>body)
    {
    for (auto temp : body)
    {
    if (temp == food)
    {
    return false;
    }
    }
    return true;
    }

    //Food.cpp end--------------------------------------------------------------------------------------

    //Snake.cpp begin--------------------------------------------------------------------------------------

    #include"Snake.h"
    #include"Food.h"
    #include<graphics.h>
    #include<iostream>
    #include<mutex>
    using namespace std;
    extern Food food;
    extern bool ISFOOD;
    extern bool ISDEAD;
    extern int HEIGHT;
    extern int WIDTH;
    const int U = 0;
    const int D = 1;
    const int L = 2;
    const int R = 3;


    //初始化蛇
    Snake::Snake() :len(1), direction(0)
    {
    Point snake_head;
    body.push_back(snake_head);
    }

    //带起始位置的初始化
    Snake::Snake(Point head) :len(1), direction(0)
    {
    body.push_back(head);
    }

    //获取蛇身长度
    int Snake::get_len()
    {
    return this->len;
    }

    //获取移动方向
    int Snake::get_direction()
    {
    return this->direction;
    }

    //改变移动方向
    void Snake::set_direction(int Direction)
    {
    this->direction = Direction;
    }

    //移动
    int px = 0;
    int py = 0;
    Point head;
    void Snake::move()
    {
    px=0;
    py=0;
    head = body.front();
    if (food.get_food() == head)
    {
    eat_food(food);
    ISFOOD = true;
    }
    switch (direction)
    {
    case U:
    py = -1;
    break;
    case D:
    py = 1;
    break;
    case L:
    px = -1;
    break;
    case R:
    px = 1;
    break;
    default:
    break;
    }
    //改变蛇头
    body.front().set_x(body.front().get_x() + px);
    body.front().set_y(body.front().get_y() + py);
    if (body.front().get_x() > (HEIGHT / 10 - 1))
    {
    body.front().set_x(0);
    }
    if (body.front().get_x() < 0 )
    {
    body.front().set_x((HEIGHT / 10 - 1));
    }
    if (body.front().get_y() > (WIDTH / 10 - 1))
    {
    body.front().set_y(0);
    }
    if (body.front().get_y() < 0)
    {
    body.front().set_y((WIDTH / 10 - 1));
    }
    //蛇蛇移动的核心代码。
    if (len > 1)
    {
    body.insert(++body.begin(), head);
    body.pop_back();
    }
    }

    //打印

    void Snake::print(PIMAGE snake_img)
    {
    clearviewport(snake_img);
    settarget(snake_img);
    setfillcolor(RED); //设置蛇蛇颜色
    bar(body.front().get_x() * 10, body.front().get_y()*10, body.front().get_x()*10+10, body.front().get_y()*10+10);
    setfillcolor(BLUE);
    int flag = true; //跳过蛇头(需要区分蛇头和蛇身的颜色的情况下)
    for (auto temp : body)
    {
    if (flag)
    {
    flag = false;
    continue;
    }
    //绘制矩形
    bar(temp.get_x() * 10, temp.get_y() * 10, temp.get_x() * 10 + 10, temp.get_y() * 10 + 10);
    }
    setfillcolor(GREEN);//设置食物颜色
    bar(food.get_food().get_x() * 10, food.get_food().get_y() * 10, food.get_food().get_x() * 10 + 10, food.get_food().get_y() * 10 + 10);
    setfillcolor(WHITE);
    settarget(NULL);
    putimage(0,0,snake_img);
    }

    //获取蛇身,用来判断是否加食物和判断是否死亡
    list<Point> Snake::get_body()
    {
    return body;
    }

    //蛇蛇吃饭
    void Snake::eat_food(Food f)
    {
    body.push_back(f.get_food());
    ++len;
    }

    //Snake.cpp end--------------------------------------------------------------------------------------

    //main.cpp begin--------------------------------------------------------------------------------------

    #include<iostream>
    #include<thread>
    #include<time.h>
    #include<graphics.h>
    #include<conio.h>
    #include<Windows.h>
    #include"Point.h"
    #include"Snake.h"
    #include"Food.h"
    #include<string>
    #include<mutex>
    using namespace std;
    int HEIGHT = 600;
    int WIDTH = 400;

    bool ISDEAD= false; //判断死亡
    bool ISFOOD = false; //判断食物
    bool change = false; //判断能否改变方向。


    Food food(Point(rand()%(HEIGHT/10-1), rand() % (WIDTH / 10 - 1)));
    mutex my_mutex;
    //方向
    char ch;

    void change_direction(Snake *snake)
    {
    while (true)
    {
    ch = getch();
    if (change == false)
    {
    continue;
    }
    unique_lock<mutex>my_unique(my_mutex);
    switch (ch)
    {
    case 'W':
    case 'w':
    if (snake->get_direction() == 1 || snake->get_direction() == 0)
    break;
    else
    {
    snake->set_direction(0);
    break;
    }
    case 'S':
    case 's':
    if (snake->get_direction() == 1 || snake->get_direction() == 0)
    break;
    else
    {
    snake->set_direction(1);
    break;
    }
    case 'A':
    case 'a':
    if (snake->get_direction() == 2 || snake->get_direction() == 3)
    break;
    else
    {
    snake->set_direction(2);
    break;
    }
    case 'D':
    case 'd':
    if (snake->get_direction() == 2 || snake->get_direction() == 3)
    break;
    else
    {
    snake->set_direction(3);
    break;
    }
    default:
    break;
    }
    my_unique.unlock();
    change = false;
    }
    }

    int main()
    {
    unsigned int Srand = time(0);
    srand(Srand);
    initgraph(HEIGHT, WIDTH);
    HWND hwnd = getHWnd();
    HDC hdc = GetDC(hwnd);
    SetWindowText(hwnd, "贪吃蛇小游戏");
    Snake snake(Point(30,20));

    //改变蛇移动方向的线程。
    thread my_thread(change_direction, &snake);

    PIMAGE snake_img = newimage(HEIGHT, WIDTH);
    Point f(rand() % (HEIGHT / 10 - 1), rand() % (WIDTH / 10 - 1));

    int i = 0; // 跳过头部
    //游戏开始
    while (true)
    {
    //蛇在移动
    my_mutex.lock();
    snake.move();
    my_mutex.unlock();

    change=true;
    //产生食物
    while (ISFOOD)
    {
    f.set_x(rand() % (HEIGHT / 10 - 1));
    f.set_y(rand() % (WIDTH / 10 - 1));
    food.set_food(f);
    if (food.IsFood(snake.get_body()))
    {
    ISFOOD = false;
    }
    }

    //打印蛇
    snake.print();

    i = 0;
    //判断蛇是否死亡。
    for (auto sk : snake.get_body())
    {
    if (i == 0)
    {
    i = 1;
    continue;
    }
    if (snake.get_body().front() == sk)
    {
    int len = snake.get_len();
    len *= 10;
    string s = "少侠你的得分是";
    s += to_string(len);
    s += "分!";
    char *score = (char*)s.c_str();
    MessageBox(hwnd, score, "对不起!", MB_YESNO);
    exit(0);
    }
    }
    Sleep(100);
    }
    getch();

    delimage(snake_img);

    closegraph();
    return 0;
    }

    //main.cpp end--------------------------------------------------------------------------------------

  • 相关阅读:
    ECharts
    JSON(及其在ajax前后端交互的过程)小识
    fullpage.js全屏滚动插件使用小结
    php json_encode数据格式化
    jQuery的DOM操作实例(3)——创建节点&&编写一个弹窗
    jQuery的DOM操作实例(2)——拖拽效果&&拓展插件
    jQuery的DOM操作实例(1)——选项卡&&Tab切换
    日常css技巧小结(2)-- inline-block带来的迷惑
    日常css技巧小结(1)--背景透明度改变对内容无影响
    浅析JavaScript事件流——冒泡
  • 原文地址:https://www.cnblogs.com/yangshengjing/p/11636838.html
Copyright © 2011-2022 走看看