纯c语言贪吃蛇游戏(三)——————彩色双人版

//由于代码技术得提升,注解基本就没有写了,(其中还用了cv大法,哈哈,仅供参考,如有不足,望指出。也可以加我QQ:2862841130讨论)

//废话不多说,上代码

#include<stdio.h>

#include<stdlib.h>
#include<conio.h>
#include<Windows.h>
#include<time.h>
#include <mmsystem.h>//播放音乐
#pragma comment(lib,"winmm.lib")

#define wideth 96
#define hghit 24
#define MaxLen 50

typedef struct  {
    int x;
    int y;
}coor;

typedef struct 
{
    int speed;
    char ch;
    int len;
    int flag;
    coor body[MaxLen];
}snak;

struct foodcoord {
    int x;
    int y;
    int flag;//定义食物的状态
}food;


enum 
{
    left = 1,
    up = 2,
    right = 3,
    down=4,
};

snak snk1, snk2;

void SetWindowSize();
void gotoxy(int x,int y);
void InitWindow();
void initImag();
void FlushSnk(snak *sn);
void changeCh1(snak *sn);
void changeCh2(snak *sn);
void drawSnak1(snak *sn);
void drawSnak2(snak *sn);
void playVoiceBg();
void creatfood(snak *sn, snak *sn2);
void eatfood(snak *sn);
void SnakeState(snak *sn1, snak *sn2);
void SetSnk1Color();
void SetSnk2Color();
void SetFoodClor();
void recoverColor();
void gameOver(int i);


void main()
{
    SetWindowSize();
    InitWindow();
    initImag();
    playVoiceBg();
    while (1)
    {
        Sleep(snk1.speed);
        FlushSnk(&snk1);
        changeCh1(&snk1);
        drawSnak1(&snk1);
        FlushSnk(&snk2);
        changeCh2(&snk2);
        drawSnak2(&snk2);

        creatfood(&snk1, &snk2);
        eatfood(&snk1);
        drawSnak1(&snk1);
        creatfood(&snk1, &snk2);
        SnakeState(&snk1, &snk2);
        if (!snk1.flag) { gameOver(2); break; }

        creatfood(&snk1, &snk2);
        eatfood(&snk2);
        drawSnak2(&snk2);
        creatfood(&snk1, &snk2);
        SnakeState(&snk2, &snk1);
        if (!snk2.flag) { gameOver(1); break; }
    }
    getchar();
}

void SetWindowSize()
{
    system("mode con cols=96 lines=24");        //cols  代表列    //lines   代表行                                        
    SetConsoleTitleA("双人贪吃蛇");                //设置标题
}

void gotoxy(int x, int y)
{
    COORD pos;
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}

void InitWindow()
{
    system("cls");
    for (int i = 0; i < wideth; i += 2)
    {
        gotoxy(i, 0);
        printf("■");
        gotoxy(i, hghit-1);
        printf("■");
    }
    for (int i = 0; i < hghit; i ++)
    {
        gotoxy(0, i);
        printf("■");
        gotoxy(wideth-2, i);
        printf("■");
    }
    recoverColor();
}

void initImag()
{
    snk1.len = snk2.len = 3;
    snk1.ch = right;
    snk2.ch = up;
    snk2.body[0].x = wideth / 4;
    snk2.body[0].y = hghit / 4;
    snk1.body[0].x = wideth / 4*3;
    snk1.body[0].y = hghit / 4*3;
    snk1.speed = snk2.speed = 500;
    snk1.flag = snk2.flag = 1;
    food.flag = 1;
    snk1.flag = snk2.flag = 1;
}

void FlushSnk(snak *sn)
{
    //反向遍历
    for (int i = sn->len-1; i >0; i--)
    {
        sn->body[i].x = sn->body[i - 1].x;
        sn->body[i].y = sn->body[i - 1].y;
    }
}

void changeCh1(snak *sn)
{
    //判断是否有按键操作
    if (GetAsyncKeyState(VK_UP))
    {
        if (sn->ch != down)sn->ch = up;
    }
    else if (GetAsyncKeyState(VK_DOWN))
    {
        if (sn->ch != up)sn->ch = down;
    }
    else if (GetAsyncKeyState(VK_RIGHT))
    {
        if (sn->ch != left)sn->ch = right;
    }
    else if (GetAsyncKeyState(VK_LEFT))
    {
        if (sn->ch != right)sn->ch = left;
    }
    else if (GetAsyncKeyState(VK_F1))
    {
        if (sn->speed >= 100)sn->speed -= 50;
    }
    else if (GetAsyncKeyState(VK_F2))
    {
        if (sn->speed <= 3000)sn->speed += 100;
    }
    //根据检测到的方向改变蛇头的位置
    switch (sn->ch)
    {
    case right:sn->body[0].x += 2; break;
    case left:sn->body[0].x -= 2; break;
    case up:sn->body[0].y -= 1; break;
    case down:sn->body[0].y += 1; break;
    }
}

void changeCh2(snak *sn)
{
    if (GetAsyncKeyState('W'))
    {
        if (sn->ch != down)sn->ch = up;
    }
    else if (GetAsyncKeyState('S'))
    {
        if (sn->ch != up)sn->ch = down;
    }
    else if (GetAsyncKeyState('D'))
    {
        if (sn->ch != left)sn->ch = right;
    }
    else if (GetAsyncKeyState('A'))
    {
        if (sn->ch != right)sn->ch = left;
    }
    //根据检测到的方向改变蛇头的位置
    switch (sn->ch)
    {
    case right:sn->body[0].x += 2; break;
    case left:sn->body[0].x -= 2; break;
    case up:sn->body[0].y -= 1; break;
    case down:sn->body[0].y += 1; break;
    }
}

void drawSnak1(snak *sn)
{
    SetSnk1Color();
    for (int i = 0; i < sn->len; i++)
    {
        gotoxy(sn->body[i].x, sn->body[i].y);
        printf("■");
    }
    recoverColor();
    //擦掉蛇的尾部
    gotoxy(sn->body[sn->len - 1].x, sn->body[sn->len - 1].y);
    printf(" ");
    gotoxy(0, 0);
    printf("■");
    gotoxy(wideth - 2,hghit-1);
}

void drawSnak2(snak *sn)
{
    SetSnk2Color();
    for (int i = 0; i < sn->len; i++)
    {
        gotoxy(sn->body[i].x, sn->body[i].y);
        printf("■");
    }
    recoverColor();
    //擦掉蛇的尾部
    gotoxy(sn->body[sn->len - 1].x, sn->body[sn->len - 1].y);
    printf(" ");
    gotoxy(0, 0);
    printf("■");
    gotoxy(wideth - 2, hghit - 1);
}

void playVoiceBg()
{
    mciSendString(TEXT("open bg.mp3 alias mysong"), NULL, 0, NULL);
    mciSendString(TEXT("play MySong"), NULL, 0, NULL);
}

void creatfood(snak *sn1, snak *sn2)
{
    //随机种子生成
    srand((unsigned)time(NULL));
    if (food.flag)
        while (1)
        {
            food.x = rand() % 96;
            food.y = rand() % 24;
            if (food.x % 2 == 0 && food.x >= 2 && food.x <= 92 && food.y > 1 && food.y < 23)
            {
                int flag1 = 0, flag2 = 0;
                //判断产生的食物可不可能在蛇的身体上
                for (int i = 0; i < sn1->len; i++)
                {
                    if (sn1->body[i].x == food.x&&sn1->body[i].y == food.y)
                    {
                        flag1 = 1;
                        break;
                    }
                }
                for (int i = 0; i < sn2->len; i++)
                {
                    if (sn2->body[i].x == food.x&&sn2->body[i].y == food.y)
                    {
                        flag2 = 1;
                        break;
                    }
                }
                if (flag1 == 1&&flag2 == 1)continue;
                //绘制食物
                else
                {
                    SetFoodClor();
                    gotoxy(food.x, food.y);
                    printf("⊙");
                    food.flag = 0;
                    recoverColor();
                    break;
                }
            }
        }
    food.flag = 0;
    gotoxy(wideth - 2, hghit - 1);
}

void eatfood(snak *sn)
{
    //只需要判断蛇头是否与食物重合
    if (food.x == sn->body[0].x&&food.y == sn->body[0].y)
    {
        sn->len+= 1;
        food.flag = 1;
    }
}

void SnakeState(snak *sn1, snak *sn2)
{
    if (sn1->body[0].x < 2 || sn1->body[0].x>94 || sn1->body[0].y < 1 || sn1->body[0].y>23)
        sn1->flag = 0;
    for (int i = 1; i < sn1->len; i++)
    {
        if (sn1->body[0].x == sn1->body[i].x&&sn1->body[0].y == sn1->body[i].y)
            sn1->flag = 0;
    }
    for(int i=0;i<sn1->len;i++)
        for (int j = 0; j < sn2->len-1; j++)
        {
            if (sn1->body[i].x == sn2->body[j].x&&sn1->body[i].y == sn2->body[j].y)
                sn1->flag = 0;
        }
}

void SetSnk1Color()
{
    //控制台也是一个窗口,首先拿到控制台这个窗口
    //得到一个窗口句柄,唯一的,每一个窗口都有一个
    //独有的句柄

    HANDLE     hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    //拿到标准输出的句柄
    //然后他会返回一个句柄值HANDLE     hConsole

    //MSDN微软官方提供的一个手册,里面介绍了每一个函数的用法
    //F1在线版    

    //有了这个句柄后就可以设置窗口的字体颜色(文本前景颜色)
    SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_INTENSITY);
    //带入参数就可以了
}

void SetSnk2Color()
{    
    HANDLE     hConsole = GetStdHandle(STD_OUTPUT_HANDLE);    
    SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN | FOREGROUND_INTENSITY );
}

void SetFoodClor()
{
    HANDLE     hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_RED);
}

void recoverColor()
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
}

void gameOver(int i)
{
    system("cls");
    system("color F0");
    if (i == 1)
    {
        gotoxy(wideth / 2, 2);
        printf("绿蛇输了");
    }
    if (i == 2)
    {
        gotoxy(wideth / 2, 2);
        printf("蓝蛇输了");
    }
    gotoxy(wideth/3, 4);
    printf("贪吃蛇");
    gotoxy(wideth / 3, 6);
    printf("2019//1//15");
    gotoxy(wideth / 3, 8);
    printf("作者:小豆芽");
    gotoxy(wideth / 3, 10);
    printf("F1:加速\tF2:减速");
    gotoxy(wideth / 3, 12);
    printf("CTRL:继续\t空格:暂停");
    gotoxy(wideth / 3, 14);
    printf("ESC:退出游戏");
    gotoxy(wideth / 3, 16);
    printf("建议:QQ:2862841130:::");
    Sleep(3000);
}

//所需音乐文件自己可以自定义添加

猜你喜欢

转载自blog.csdn.net/xiao_dou_ya_cool/article/details/85865202
今日推荐