自制C++ 贪吃蛇

用了一整天时间,终于做出了双人对战的贪吃蛇,找了几个同学试了试,还是很有趣的。在做这些小游戏的时候学会了不少知识,有机会我会多尝试的。下面就把代码发出来,我用的是VS2013,把代码复制过去应该可以直接编译运行。
学完系统网络编程的我再回来看了看,感觉如果有时间可以做成局域网的,而且游戏的内容也因为多线程的加入变得更加丰富。


QQ图片20161114212714.jpg
QQ图片20161114212814.jpg

#include<windows.h>
#include<conio.h>
#include<time.h>
#include<string>
using namespace std;

/*=============== all the structures ===============*/

typedef struct Frame
{
    COORD position[2];//位置
    int flag;
}Frame;//帧


/*=============== all the functions ===============*/

void SetPos(COORD a)// set cursor 设置光标
{
    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(out, a);
}

/* set cursor设置光标*/void SetPos(int i, int j)
{
    COORD pos = { i, j };
    SetPos(pos);
}

void HideCursor()
{
    CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}

//把第y行,[x1, x2) 之间的坐标填充为 ch
void drawRow(int y, int x1, int x2, char ch)
{
    SetPos(x1, y);
    for (int i = 0; i <= (x2 - x1); i++)
        cout << ch;
}

//在a, b 纵坐标相同的前提下,把坐标 [a, b] 之间填充为 ch
void drawRow(COORD a, COORD b, char ch)
{
    if (a.Y == b.Y)
        drawRow(a.Y, a.X, b.X, ch);
    else
    {
        SetPos(0, 25);
        cout << "error code 01:无法填充行,因为两个坐标的纵坐标(x)不相等";
        system("pause");
    }
}

//把第x列,[y1, y2] 之间的坐标填充为 ch
void drawCol(int x, int y1, int y2, char ch)
{
    int y = y1;
    while (y != y2 + 1)
    {
        SetPos(x, y);
        cout << ch;
        y++;
    }
}

//在a, b 横坐标相同的前提下,把坐标 [a, b] 之间填充为 ch
void drawCol(COORD a, COORD b, char ch)
{
    if (a.X == b.X)
        drawCol(a.X, a.Y, b.Y, ch);
    else
    {
        SetPos(0, 25);
        cout << "error code 02:无法填充列,因为两个坐标的横坐标(y)不相等";
        system("pause");
    }
}

//左上角坐标、右下角坐标、用row填充行、用col填充列
void drawFrame(COORD a, COORD  b, char row, char col)
{
    drawRow(a.Y, a.X + 1, b.X - 1, row);
    drawRow(b.Y, a.X + 1, b.X - 1, row);
    drawCol(a.X, a.Y + 1, b.Y - 1, col);
    drawCol(b.X, a.Y + 1, b.Y - 1, col);
}
//点覆盖
void drawFrame(COORD a, char r)
{
    SetPos(a.X, a.Y);
    cout << r;
}

void drawFrame(int x1, int y1, int x2, int y2, char row, char col)
{
    COORD a = { x1, y1 };
    COORD b = { x2, y2 };
    drawFrame(a, b, row, col);
}

void drawFrame(Frame frame, char row, char col)
{
    COORD a = frame.position[0];
    COORD b = frame.position[1];
    drawFrame(a, b, row, col);
}

void drawPlaying()
{
    drawFrame(0, 0, 48, 24, '=', '|');//    draw map frame;
    drawFrame(49, 0, 77, 24, '-', '|');//       draw output frame
    SetPos(52, 6);
    cout << "玩家1长度:";
    SetPos(52, 8);
    cout << "玩家2长度:";
    SetPos(52, 14);
    cout << "操作方式:";
    SetPos(52, 16);
    cout << " 玩家1 上下左右";
    SetPos(52, 17);
    cout << " 玩家2 a,s,d,w";
    SetPos(52, 19);
    cout << "  p 暂停游戏。";
    SetPos(52, 20);
    cout << "  esc 退出游戏。";
}

//在[a, b)之间产生一个随机整数
int random(int a, int b)
{
    int c = (rand() % (a - b)) + a;
    return c;
}

//在两个坐标包括的矩形框内随机产生一个坐标
COORD random(COORD a, COORD b)
{
    int x = random(a.X, b.X);
    int y = random(a.Y, b.Y);
    COORD c = { x, y };
    return c;
}

//判断是否撞到蛇身或者墙壁 点对点
bool  judgeCoordSnake(COORD spot1, COORD spot2)
{
    if (spot1.X == spot2.X)
        if (spot1.Y == spot2.Y)
            return true;
    if (spot1.X == 0 || spot1.X == 48 || spot1.Y == 0 || spot1.Y == 24)
        return true;
    return false;
}

//判断是否撞到蛇身或者墙壁 头对身子
bool  judgeCoordSnake(COORD spot1, COORD *snake1, COORD *snake2)
{
    for (int i = 1; i < 250; i++)
    {
        if (spot1.X == snake1[i].X)
            if (spot1.Y == snake1[i].Y)
                return false;
        if (spot1.X == snake2[i].X)
            if (spot1.Y == snake2[i].Y)
                return false;
        if (spot1.X == 0 || spot1.X == 48 || spot1.Y == 0 || spot1.Y == 24)
            return false;
    }
    return true;
}
bool  judgeCoordSnakeFood(COORD spot1, COORD spot2, COORD spot3,int& a)
{
    if (spot1.X == spot2.X)
        if (spot1.Y == spot2.Y)
        {
            a = 0;
            return true;
        }
    if (spot1.X == spot3.X)
        if (spot1.Y == spot3.Y)
        {
            a = 1;
            return true;
        }
            
    return false;
}
//因为在判断时头部的问题所以单列出来



void printCoord(COORD a)
{
    cout << "( " << a.X << " , " << a.Y << " )";
}

int drawMenu()
{
    SetPos(30, 1);
    cout << "贪吃的大蟒蛇";
    drawRow(3, 0, 79, '-');
    drawRow(5, 0, 79, '-');
    SetPos(28, 4);
    cout << "w 和 s 选择, k 确定";
    SetPos(15, 11);
    cout << "开始游戏";
    SetPos(15, 13);
    cout << "结束游戏";
    drawRow(20, 0, 79, '-');
    drawRow(22, 0, 79, '-');
    SetPos(47, 11);
    cout << "本游戏为双人游戏:";
    SetPos(51, 13);
    cout << "wasd和ijkl控制";
    SetPos(24, 21);
    cout << "制作: 威微游戏制造厂厂长  唐宇威";
    int j = 11;
    SetPos(12, j);
    cout <<"->";
    while (1)
    {
        if (_kbhit())
        {
            char x = _getch();
            switch (x)
            {
            case 'w':
            {
                if (j == 13)
                {
                    SetPos(12, j);
                    cout << " ";
                    j = 11;
                    SetPos(12, j);
                    cout << "->";
                    SetPos(51, 13);
                    cout << "            ";
                    SetPos(47, 11);
                    cout << "准备好了吗?";
                    SetPos(51, 13);
                    cout << "wasd和ijkl控制";
                }
                break;
            }
            case 's':
            {
                if (j == 11)
                {
                    SetPos(12, j);
                    cout << " ";
                    j = 13;
                    SetPos(12, j);
                    cout << "->";
                    SetPos(51, 13);
                    cout << "              ";
                    SetPos(47, 11);
                    cout << "结束游戏:";
                    SetPos(51, 13);
                    cout << "要走了吗?";
                }
                break;
            }
            case 'k':
            {
                if (j == 11)    
                    return 1;
                else exit(0);
            }
            }
        }
    }
}

/*
DWORD WINAPI MusicFun(LPVOID lpParamte)
{
//DWORD OBJ;
sndPlaySound(TEXT("bgm.wav"), SND_FILENAME|SND_ASYNC);
return 0;
}
*/


/*================== the Game Class ==================*/

class Game
{
public:
    COORD snake1[250];
    COORD snake2[250];
    COORD food[2];
    int length1;
    int length2;
    int direction1;//蛇1的头 1上2下3左4右
    int direction2;//蛇2的头 1上2下3左4右
    string title;
    //初始化所有
    void initFood();
    COORD randomFood();
    //初始化其中一个
    //void initThisBullet( COORD );
    //void initThisEnemy( Frame );
    void Playing();
    void Pause();
    void judgeSnake();
    void GameOver();
    void snake1ChangeDirection(char x);
    void snake2ChangeDirection(char x);
    void drawSnake1(int direction);
    void drawSnake2(int direction);
    void drawSnake1ToNull();
    void drawSnake2ToNull();
    void drawFood();
    void drawFoodToNull();
    Game()
    {
        direction1 = 1,direction2 = 1;
        snake1[0] = { 8, 15 }, snake1[1] = { 8, 16 }, snake1[2] = { 8, 17 };
        snake2[0] = { 40, 15 }, snake2[1] = { 40, 16 }, snake2[2] = { 40, 17 };
        length1 = 3, length2 = 3;
        for (int i = 3; i < 249; i++)
        {
            snake1[i] = { 0, 0 };
            snake2[i] = { 0, 0 };
        }
    }
    
};

//画第一条蛇
void Game::drawSnake1(int direction)
{
    for (int i = 0; i<240; i++)
    {
        SetPos(snake1[i]);
        if (i != 0)
            cout << "O";
        else if (i == 0)
        {
            if (direction==1)
            {
                cout << "^";
            }
            else if(direction == 2)
            {
                cout << "v";
            }
            else if (direction == 3)
            {
                cout << "<";
            }
            else if (direction == 4)
            {
                cout << ">";
            }
    
        }
            
    }
}
void Game::drawSnake2(int direction)
{
    for (int i = 0; i<240; i++)
    {
        SetPos(snake2[i]);
        if (i != 0)
            cout << "X";
        else if (i == 0)
        {
            if (direction == 1)
            {
                cout << "^";
            }
            else if (direction == 2)
            {
                cout << "v";
            }
            else if (direction == 3)
            {
                cout << "<";
            }
            else if (direction == 4)
            {
                cout << ">";
            }

        }

    }
}
//把第一条蛇消失,行动时使用,只让蛇头蛇尾消失,这样不会一闪一闪
void Game::drawSnake1ToNull()
{
    SetPos(snake1[0]);
    cout << " ";
    SetPos(snake1[length1]);
    cout << " ";    
}
void Game::drawSnake2ToNull()
{
    /*for (int i = length2; i<240; i++)
    {
        SetPos(snake2[i]);
        cout << " ";
    }*/
    SetPos(snake2[0]);
    cout << " ";
    SetPos(snake2[length2]);
    cout << " ";
}
//初始食物
void Game::initFood()
{
    COORD a = { 2, 2  };
    COORD b = { 24,12 };
    COORD c = { 25, 2 };
    COORD d = { 47,14 };
    food[0] = random(a, b);
    food[1] = random(c, d);
}
//随机食物,如果有墙需要修改。
COORD Game::randomFood()
{
    COORD food;
    COORD a = { 2, 2 };
    COORD b = { 47, 23 };
    while (1)
    {
        food = random(a, b);
        if (judgeCoordSnake(food, snake1, snake2))
            return food;
    }
}
//画出食物
void Game::drawFood()
{
    for (int i = 0; i<2; i++)
        drawFrame(food[i], '@');
}
//判断蛇是否吃到东西

/*不用这个也行,蛇吃过了就没了*/void Game::drawFoodToNull()
{
    for (int i = 0; i<2; i++)
    {
        drawFrame(food[i], ' ');
    }
}
//暂停游戏
void Game::Pause()
{
    SetPos(61, 2);
    cout << "               ";
    SetPos(61, 2);
    cout << "暂停中...";
    char c = _getch();
    while (c != 'p')
        c = _getch();
    SetPos(61, 2);
    cout << "         ";
}

void Game::snake1ChangeDirection(char x)
{
    
        if (x == 'w')//是上箭头;
        {
            if (direction1!=2)
            direction1 = 1;
        }
        else if (x == 's') //是 下箭头;
        {
            if (direction1 != 1)
            direction1 = 2;
        }
        else if (x == 'a')  //是 左箭头;
        {
            if (direction1 != 4)
            direction1 = 3;
        }
        else if (x == 'd') // 是 右箭头;
        {
            if (direction1 != 3)
            direction1 = 4;
        }
        
}
void Game::snake2ChangeDirection(char x)
{

    if (x == 'i')//是上箭头;
    {
        if (direction2 != 2)
            direction2 = 1;
    }
    else if (x == 'k') //是 下箭头;
    {
        if (direction2 != 1)
            direction2 = 2;
    }
    else if (x == 'j')  //是 左箭头;
    {
        if (direction2 != 4)
            direction2 = 3;
    }
    else if (x == 'l') // 是 右箭头;
    {
        if (direction2 != 3)
            direction2 = 4;
    }

}

void Game::judgeSnake()
{
    for (int i = 0; i < 250; i++)
    {
        if (judgeCoordSnake(snake1[0], snake1, snake2) == false )
        {
            for (int i = 1; i < 500; i++)
            {
                Sleep(2);
                SetPos(random(1,79), random(1,24));
                cout << "玩家一输了";
            }
            Sleep(1000);
            GameOver();
            break;
        }
        if (judgeCoordSnake(snake2[0], snake1, snake2) == false)
        {
            for (int i = 1; i < 500; i++)
            {
                Sleep(2);
                SetPos(random(1, 79), random(1, 24));
                cout << "玩家二输了";
            }
            Sleep(1000);
            GameOver();
            break;
        }
    }
    


}


void Game::Playing()
{
    //HANDLE MFUN;
    //MFUN= CreateThread(NULL, 0, MusicFun, NULL, 0, NULL); 

    drawSnake1(direction1);
    drawSnake2(direction2);
    initFood();
    drawFood();
    int numfood;
    
    while (1)
    {
        Sleep(10);
        SetPos(52, 7);
        cout << length1;
        SetPos(52, 9);
        cout << length2;
        drawSnake1ToNull();
        drawSnake2ToNull();
        if (_kbhit())
        {
            char x = _getch();
            if ('a' == x || 's' == x || 'd' == x || 'w' == x)
            {
                snake1ChangeDirection(x);   
            }
            else if ('p' == x)
                Pause();
            else if ('j' == x || 'k' == x || 'l' == x || 'i' == x)
            {
                snake2ChangeDirection(x);
            }
            else if (27 == x)
            {
                //CloseHandle(MFUN);
                GameOver();
                break;
            }
        }
        if(judgeCoordSnakeFood(snake1[0], food[0], food[1],numfood)==true)
        {
        
            if (direction1 == 1)
            {
                for (int i = length1; i > 0; i--)
                    snake1[i+1] = snake1[i];
                snake1[0].Y--;
                length1++;
            }
            if (direction1 == 2)
            {
                for (int i = length1; i >= 0; i--)
                    snake1[i+1] = snake1[i];
                snake1[0].Y++;
                length1++;
            }
            if (direction1 == 3)
            {
                for (int i = length1; i >= 0; i--)
                    snake1[i+1] = snake1[i];
                snake1[0].X--;
                length1++;
            }
            if (direction1 == 4)
            {
                for (int i = length1; i >= 0; i--)
                    snake1[i+1] = snake1[i];
                snake1[0].X++;
                length1++;
            }
            food[numfood] = randomFood();
            drawFood();
        }
        else
        {
            if (direction1 == 1)
            {
                for (int i = length1; i > 0; i--)
                    snake1[i] = snake1[i - 1];
                snake1[0].Y--;
            }
            if (direction1 == 2)
            {
                for (int i = length1; i > 0; i--)
                    snake1[i] = snake1[i - 1];
                snake1[0].Y++;
            }
            if (direction1 == 3)
            {
                for (int i = length1; i > 0; i--)
                    snake1[i] = snake1[i - 1];
                snake1[0].X--;
            }
            if (direction1 == 4)
            {
                for (int i = length1; i > 0; i--)
                    snake1[i] = snake1[i - 1];
                snake1[0].X++;
            }
            judgeSnake();
        }
        if (judgeCoordSnakeFood(snake2[0], food[0], food[1], numfood) == true)
        {

            if (direction2 == 1)
            {
                for (int i = length2; i > 0; i--)
                    snake2[i + 1] = snake2[i];
                snake2[0].Y--;
                length2++;
            }
            if (direction2 == 2)
            {
                for (int i = length2; i >= 0; i--)
                    snake2[i + 1] = snake2[i];
                snake2[0].Y++;
                length2++;
            }
            if (direction2 == 3)
            {
                for (int i = length2; i >= 0; i--)
                    snake2[i + 1] = snake2[i];
                snake2[0].X--;
                length2++;
            }
            if (direction2 == 4)
            {
                for (int i = length2; i >= 0; i--)
                    snake2[i + 1] = snake2[i];
                snake2[0].X++;
                length2++;
            }
            food[numfood] = randomFood();
            drawFood();
        }
        else
        {
            if (direction2 == 1)
            {
                for (int i = length2; i > 0; i--)
                    snake2[i] = snake2[i - 1];
                snake2[0].Y--;
            }
            if (direction2 == 2)
            {
                for (int i = length2; i > 0; i--)
                    snake2[i] = snake2[i - 1];
                snake2[0].Y++;
            }
            if (direction2 == 3)
            {
                for (int i = length2; i > 0; i--)
                    snake2[i] = snake2[i - 1];
                snake2[0].X--;
            }
            if (direction2 == 4)
            {
                for (int i = length2; i > 0; i--)
                    snake2[i] = snake2[i - 1];
                snake2[0].X++;
            }
            judgeSnake();
        }
        drawSnake1(direction1);
        drawSnake2(direction2);

    }
}

void Game::GameOver()
{
    system("cls");
    COORD p1 = { 28, 9 };
    COORD p2 = { 53, 15 };
    drawFrame(p1, p2, '=', '|');
    SetPos(36, 12);
    string str = "Game Over!";
    for (int i = 0; i<str.size(); i++)
    {
        Sleep(80);
        cout << str[i];
    }
    Sleep(1000);
    system("cls");
    drawFrame(p1, p2, '=', '|');
    SetPos(31, 11);
    cout << "玩家一长度:" ;
    SetPos(31, 12);
    cout << length1;
    SetPos(31, 13);
    cout << "玩家二长度:";
    SetPos(31, 14);
    cout << length2;
    SetPos(30, 16);
    Sleep(1000);
    cout << "继续? 是(y)| 否(n)";
as:
    char x = _getch();
    if (x == 'n')
        exit(0);
    else if (x == 'y')
    {
        system("cls");
        Game game;
        int a = drawMenu(); 
        system("cls");
        drawPlaying();
        game.Playing();
    }
    else goto as;
}

/*================== the main function ==================*/
int main()
{
    //游戏准备
    srand((int)time(0));    //随机种子
    HideCursor();   //隐藏光标

    Game game;
    int a = drawMenu();
    system("cls");
    drawPlaying();
    game.Playing();
}```
****
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容