/ Vijos / 讨论 / 游戏 /

c++贪吃蛇(1.正常 2.破解)

正常版:

#include <iostream>
#include <list>
#include <cstdio>
#include <string>
#include <vector>
#include <ctime>
#include <algorithm>
#include <conio.h>
#include <windows.h>
using namespace std;

class Node { 
public:
    int x, y;
    Node(int x1, int y1); 
};

class UserData { 
public:
    string name;
    long long score;
    int gt;
    int gr; 
    UserData(string s, long long sc,int gametime,int grade); 
    friend bool operator < (UserData a, UserData b); 
};

#define RIGHT 0x4d
#define LEFT 0x4b  
#define UP 0x48  
#define DOWN 0x50 
#define YELLOW FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define CYAN FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define ORANGE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define PURPLE FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY
#define RED  FOREGROUND_RED | FOREGROUND_INTENSITY
const int STARTX = 8; 
const int STARTY = 4; 
const int RANGEX = 60; 
const int RANGEY = 20;
int point=10; 
const int ENDX = STARTX + RANGEX; 
const int ENDY = STARTY + RANGEY; 
bool isSnake[RANGEY + 10 ][RANGEX + 10];
int speed; 
int sysj;
int gametime;
list<Node> snake;
int curDiraction; //蛇的当前前进方向, 1上, 2下, 3左, 4右
int score; //当前分数
int grade;
int snakeLen; //蛇的长度
int foodx, foody; //食物坐标
int gox, goy; //蛇头坐标
int mj;
void GoTo(short x, short y); //定位光标
void DrawBoard(); //绘制边框
void ShowInformation(); //展示游戏信息
void Init(); //初始化游戏
void RunSnake(int x, int y); //绘制蛇身
void Try(int& x, int& y); //试走
bool IsGoodCoord(int x, int y); //前进坐标是否合法
void AddFood(); //增加食物
void EartFood(); //吃食物
void InitSnake(); //初始化蛇身
bool EndGame(); //结束游戏
bool StartGame(); //启动游戏
bool GameMenu(); //游戏菜单
void ShowRanking(); //排行榜
void ShowAbout(); //相关信息
void InputData(); //输入玩家名字

int main() {
    system("title 贪吃蛇小游戏 by 李凯昱");
    while (true) {
        if (!GameMenu()) return 0;
    }
    return 0;
}

Node::Node(int x1, int y1) { //构造Node对象
    x = x1; y = y1; 
}

bool operator < (UserData a, UserData b) { //重载运算符,按分数由大到小排列
    if(a.score != b.score)
    return a.score > b.score;
    if(a.gt !=b.gt)
    return a.gt > b.gt;
    else
    return a.gr > b.gr;
}
UserData::UserData(string s, long long sc,int gametime_,int _grade) { //构造UserData对象
    name = s; score = sc; gt=gametime_; gr=_grade;
}

void color(WORD A)
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), A);
} 

void Color(int score_)
{
    if(score_%4==1)
    {
        color(PURPLE);
    }
    else if(score_%4==2)
    {
        color(RED);
    }
    else if(score_%4==3)
    {
        color(YELLOW);
    }
    else if(score_%4==0) 
    {
        color(CYAN);
    }
}

void GoTo(short x, short y) { //定位光标
    COORD coord = { x, y };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

void ShowInformation() { //输出游戏信息
    color(YELLOW);
    GoTo(78, 5);
    printf("贪吃蛇游戏");
    GoTo(78,18);
    gametime=(clock()-mj)/1000;
    grade=snakeLen-3; 
    printf("生存时间:%3d 秒",(clock()-mj)/1000);
    GoTo(78, 8);
    printf("游戏规则:");
    GoTo(78, 10);
    printf("请按 ↑ ↓ ← →  来控制您的蛇吃东西");
    GoTo(78, 12);
    printf("吃的越多,蛇就越长,您的等级也将越高");
    GoTo(78, 14);
    printf("当蛇吃到自己或撞上墙时,游戏结束。");
    GoTo(78,16);
    printf("自动前进时间:%3dms",speed);
    GoTo(78, 20);
    printf("当前等级: %8d", snakeLen-3);
    GoTo(78, 23);
    printf("您的分数: %d", score);
    color(CYAN);
    printf("+%d=%d",score/3,score*3/2);
    color(YELLOW);
    GoTo(78,25);
    printf("剩余时间:%d秒",10+(snakeLen-3)*4-gametime);
    sysj=10+(snakeLen-3)*4-gametime; 
}

void DrawBoard() { //绘制墙体

    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); //获得输出句柄

    CONSOLE_CURSOR_INFO cursor_info = { 1, 0 }; //光标信息
    SetConsoleCursorInfo(hOut, &cursor_info); //隐藏光标

    COORD size = { 120, 30 };
    SetConsoleScreenBufferSize(hOut, size); //重设缓冲区大小

    SMALL_RECT rc = { 0 , 0, 120, 30 };
    SetConsoleWindowInfo(hOut, true, &rc); //重设窗口大小

    SetConsoleTextAttribute(hOut, CYAN);

    for (int i = STARTX - 2; i <= ENDX + 2; i += 2) { //横向墙体
        GoTo(i, STARTY - 1);
        printf("■");
        GoTo(i, ENDY + 1);
        printf("■");
    }
    for (int i = STARTY - 1; i <= ENDY + 1; ++i) { //竖向墙体
        GoTo(STARTX - 2, i);
        printf("■");
        GoTo(ENDX + 2, i);
        printf("■");
    }
}
void draw()
{
    char m=snakeLen+62;
    Color(score);
    cout<<"■";
 } 
void Init() { //初始化游戏
    system("cls");
    memset(isSnake, 0, sizeof(isSnake));
    speed = 200;
    curDiraction = 4;
    score = 0;
    DrawBoard();
    InitSnake();
    ShowInformation();
    AddFood();
    mj=clock();
    point=10;
    sysj=10;
}

void RunSnake(int x, int y) { //绘制蛇身
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    score += snakeLen + 1;
    if (x == foodx && y == foody) {
        EartFood();
        AddFood();
        return;
    }
    snake.push_front(Node(x, y));
    isSnake[y][x] = true;
    GoTo(x, y);
    draw();
    Node back = snake.back();
    snake.pop_back();
    isSnake[back.y][back.x] = false;
    GoTo(back.x, back.y);
    printf(" ");
}

void Try(int& x, int& y) { //试走
    int key, cnt = 100;
    while (cnt--) { //多次检测键盘状态
        if (_kbhit()) {
            key = getch();
            switch (key) {
            case UP: 
                if (curDiraction == 1 || curDiraction == 2) break;
                --y; curDiraction = 1; return;
            case DOWN: 
                if (curDiraction == 1 || curDiraction == 2) break;
                ++y; curDiraction = 2; return;
            case LEFT: 
                if (curDiraction == 3 || curDiraction == 4) break;
                x -= 2; curDiraction = 3; return;
            case RIGHT: 
                if (curDiraction == 3 || curDiraction == 4) break;
                x += 2; curDiraction = 4; return;
            }
        }
    }
    if (curDiraction == 1) --y; //用户没有输入时
    else if (curDiraction == 2) ++y;
    else if (curDiraction == 3) x -= 2;
    else x += 2;
}

bool IsGoodCoord(int x, int y) { //判断光标是否合法
    if (x <= ENDX && y <= ENDY && x >= STARTX && y >= STARTY)
        return true;
    else
        return false;
}

void AddFood() { //增加食物
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), PURPLE);
    srand((unsigned)time(NULL));
    while (true) {
        foodx = (rand()%ENDX) + 1;
        foody = (rand()%ENDY) + 1;
        if (foodx&1) foodx++;
        if (!isSnake[foody][foodx] && IsGoodCoord(foodx, foody)) break;
    }
    GoTo(foodx, foody);
    int a=rand()%5;
    if(a>=4) 
    printf("★");
    else if(a<=1) 
    printf("○");
    else
    printf("▲");
}

void EartFood() { //吃东西
    point+=4;
    int sb=gametime=(clock()-mj)/1000;
    sysj=point-sb;
    score+=score/2;
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    snake.push_front(Node(foodx, foody));
    isSnake[foody][foodx] = true;
    ++snakeLen;
    if (speed >= 55) speed -= 5;

    GoTo(foodx, foody);
    draw();
    AddFood(); 
}

void InitSnake() { //初始化蛇身
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    snakeLen = 3, gox = 18, goy = 14;
    snake.clear();
    snake.push_front(Node(12, 14));
    snake.push_front(Node(14, 14));
    snake.push_front(Node(16, 14));
    for (int i = 12; i <= 16; i += 2) {
        GoTo(i, 14);
        draw();
        isSnake[14][i] = true;
    }
}
bool EndGame() { //结束游戏
    system("cls");
    DrawBoard();
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    GoTo(28, 10);
    printf("您的本局游戏得分: %d分", score);
    GoTo(32, 18);
    printf("....你挂了....");
    GoTo(27, 20);
    printf("是否继续游戏: 是(1), 否(0)");
    GoTo(27, 22);
    char key = getch();
    while (true) {
        if (key == '1') return false;
        else if (key == '0') 
        {GoTo(ENDX+1,ENDY+2);
        exit(0);return true;
        }
        else key = getch();
    }
}

bool StartGame() { //启动游戏

    Init();

    while (IsGoodCoord(gox, goy) && !isSnake[goy][gox]&&sysj>0) { //当试走合法时
        RunSnake(gox, goy);
        ShowInformation();
        Try(gox, goy);
        Sleep(speed);
    }
    InputData(); 
    return true;
}

bool GameMenu() { //游戏菜单
    system("cls");
    DrawBoard();
    GoTo(STARTX + 22, STARTY + 4);
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    printf("欢迎进入贪吃蛇游戏!");
    GoTo(STARTX + 24, STARTY + 10);
    printf("1: 新游戏");
    GoTo(STARTX + 24, STARTY + 12);
    printf("2: 排行榜");
    GoTo(STARTX + 24, STARTY + 14);
    printf("3: 关于游戏");
    GoTo(STARTX + 24, STARTY + 16);
    printf("4: 退出游戏");

    while (true) {
        if (_kbhit()) {
            char key = getch();
            switch (key) {
            case '1':
                if (!StartGame()) return false; 
                else return true;
            case '2':
                ShowRanking(); return true;
            case '3':
                ShowAbout(); return true;
            case '4':
                GoTo(1,ENDY+2);
                return false;
            default:
                return true;
            }
        }
    }
}

void ShowRanking() { //展示排行榜
    vector<UserData> vu;
    FILE *fp = fopen("GameData.txt", "r");
    if (fp == NULL) fp = fopen("GameData.txt", "w+");
    char name[20];
    int len = 0;
    while (fscanf(fp, "%s", name) != EOF) {
        ++len;
        int score,g=grade;
        fscanf(fp, "%d%d%d%*c", &score,&gametime,&g);
        vu.push_back(UserData(string(name), score,gametime,grade));
    }
    fclose(fp);
    sort(vu.begin(), vu.end()); //对得分进行排名
    system("cls");
    DrawBoard();
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), CYAN);
    GoTo(STARTX + 8, STARTY + 2);
    printf("用户");
    GoTo(STARTX + 20, STARTY + 2);
    printf("分数");
    GoTo(STARTX + 32, STARTY + 2);
    printf("生存时间");
    GoTo(STARTX + 44, STARTY + 2);
    printf("排行");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);

    for (int i = 0; i < len && i < 10; ++i) { //打印前十名用户数据
        char const *p = vu[i].name.c_str();
        Color(vu[i].score);
        GoTo(STARTX + 8, STARTY + 4 + i);
        printf("%s", p);
        GoTo(STARTX + 20, STARTY + 4 + i);
        printf("%d分", vu[i].score);
        GoTo(STARTX + 32, STARTY + 4 + i);
        printf("%d秒", vu[i].gt);
        GoTo(STARTX + 44, STARTY + 4 + i);
        printf(" %d", i + 1);
    }

    GoTo(STARTX + 4, ENDY - 2);
    printf("-----------------  按'1'返回游戏菜单  ---------------");
    while (true) {
        if (_kbhit()) {
            char key = getch();
            if (key == '1') break;
        }
    }
}

void ShowAbout() { //展示游戏相关
    system("cls");
    DrawBoard();
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);

    GoTo(STARTX + 4, STARTY + 2);
    printf("-------------------  贪吃蛇游戏  -------------------");
    GoTo(STARTX + 10, STARTY + 4);
    printf("制作人: ");
    GoTo(STARTX + 10, STARTY + 6);
    printf("李凯昱");
    GoTo(STARTX + 10,STARTY + 8);
    printf("贪吃蛇游戏");
    GoTo(STARTX + 10,STARTY + 10);
    printf("游戏规则:");
    GoTo(STARTX + 10,STARTY + 12);
    printf("请按 ↑ ↓ ← →  来控制您的蛇吃东西");
    GoTo(STARTX + 10,STARTY + 14);
    printf("吃的越多,蛇就越长,您的等级也将越高");
    GoTo(STARTX + 10,STARTY + 16);
    printf("当蛇吃到自己或撞上墙时,游戏结束。");

    GoTo(STARTX + 4, ENDY - 2);
    printf("-----------------  按'1'返回游戏菜单  ---------------");
    while (true) {
        if (_kbhit()) {
            char key = getch();
            if (key == '1') break;
        }
    }
}

void InputData() { //用户输入名字
    char name[20];
    if(score>=1000)
    {
    GoTo(STARTX + 10, STARTY + 10);
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), RED);
    printf("请输入你的名字: ");
    COORD coord = { STARTX + 10, STARTY + 12 };
    SetConsoleCursorPosition(GetStdHandle(STD_INPUT_HANDLE), coord);
    while (true) { //忽略非法字符
        scanf("%s", name);
        if (name[0] != 0 && name[0] != ' ') break; 
    }FILE *fp = fopen("Gamedata.txt", "a");
    if (fp == NULL) fp = fopen("GameData.txt", "w+");
    fprintf(fp, "%s %d %d \n", name, score,gametime);
    fclose(fp);
    }
    else 
    {
        GoTo(STARTX + 20, STARTY + 10);
        cout<<"哟!这分数也能上榜??"<<endl; 
        Sleep(1000);
     }  
    EndGame(); 
    
}

破解版:

#include <iostream>
#include <list>
#include <cstdio>
#include <string>
#include <vector>
#include <ctime>
#include <algorithm>
#include <conio.h>
#include <windows.h>
using namespace std;
class Node { 
public:
    int x, y;
    Node(int x1, int y1); 
};

class UserData { 
public:
    string name;
    long long score;
    int gt;
    int gr; 
    UserData(string s, long long sc,int gametime,int grade); 
    friend bool operator < (UserData a, UserData b); 
};

#define RIGHT 0x4d
#define LEFT 0x4b  
#define UP 0x48  
#define DOWN 0x50 
#define YELLOW FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define CYAN FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define ORANGE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define PURPLE FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY
#define RED  FOREGROUND_RED | FOREGROUND_INTENSITY
const int STARTX = 8; 
const int STARTY = 4; 
const int RANGEX = 60; 
const int RANGEY = 20;
int point=10; 
const int ENDX = STARTX + RANGEX; 
const int ENDY = STARTY + RANGEY; 
bool isSnake[RANGEY + 10 ][RANGEX + 10];
int speed; 
int sysj;
int gametime;
list<Node> snake;
int curDiraction; //蛇的当前前进方向, 1上, 2下, 3左, 4右
int score; //当前分数
int grade;
int snakeLen; //蛇的长度
int foodx, foody; //食物坐标
int gox, goy; //蛇头坐标
int mj;
void GoTo(short x, short y); //定位光标
void DrawBoard(); //绘制边框
void ShowInformation(); //展示游戏信息
void Init(); //初始化游戏
void RunSnake(int x, int y); //绘制蛇身
void Try(int& x, int& y); //试走
bool IsGoodCoord(int x, int y); //前进坐标是否合法
void AddFood(); 
void EartFood();
void InitSnake(); 
bool EndGame(); 
bool StartGame();
bool GameMenu(); //游戏菜单
void ShowRanking(); //排行榜
void ShowAbout(); //相关信息
void InputData(); //输入玩家名字

int main() {
    system("title 贪吃蛇小游戏 by 李凯昱");
    while (true) {
        if (!GameMenu()) return 0;
    }
    return 0;
}

Node::Node(int x1, int y1) { //构造Node对象
    x = x1; y = y1; 
}

int SuiJi()
{
srand((unsigned)time(NULL));
return (rand()*rand()+rand()*rand())%14;
}

bool operator < (UserData a, UserData b) { //重载运算符,按分数由大到小排列
    if(a.score != b.score)
    return a.score > b.score;
    if(a.gt !=b.gt)
    return a.gt > b.gt;
    else
    return a.gr > b.gr;
}
UserData::UserData(string s, long long sc,int gametime_,int _grade) { //构造UserData对象
    name = s; score = sc; gt=gametime_; gr=_grade;
}

void color(WORD A)
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), A);
} 

void Color(int a)
{
    switch (a%4)
    {
        case 0:color(RED);break;
        case 1:color(CYAN);break;
        case 2:color(YELLOW);break;
        case 3:color(PURPLE);break;
    }
}

void GoTo(short x, short y) { //定位光标
    COORD coord = { x, y };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

void ShowInformation() { //输出游戏信息
    color(YELLOW);
    GoTo(78, 5);
    printf("贪吃蛇游戏");
    GoTo(78,18);
    gametime=(clock()-mj)/1000;
    grade=snakeLen-3; 
    printf("生存时间:%3d 秒",(clock()-mj)/1000);
    GoTo(78, 8);
    printf("游戏规则:");
    GoTo(78, 10);
    printf("请按 ↑ ↓ ← →  来控制您的蛇吃东西");
    GoTo(78, 12);
    printf("吃的越多,蛇就越长,您的等级也将越高");
    GoTo(78, 14);
    printf("当蛇吃到自己或撞上墙时,游戏结束。");
    GoTo(78,16);
    printf("自动前进时间:%3dms",speed);
    GoTo(78, 20);
    printf("当前等级: %8d", snakeLen-3);
    GoTo(78, 23);
    printf("您的分数: %d", score);
    color(CYAN);
    printf("+%d=%d",score/3,score*3/2);
    color(YELLOW);
    GoTo(78,25);
    printf("剩余时间:%d秒",20+(snakeLen-3)*5-gametime);
    sysj=20+(snakeLen-3)*5-gametime; 
}

void DrawBoard() { //绘制墙体

    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); //获得输出句柄

    CONSOLE_CURSOR_INFO cursor_info = { 1, 0 }; //光标信息
    SetConsoleCursorInfo(hOut, &cursor_info); //隐藏光标

    COORD size = { 120, 30 };
    SetConsoleScreenBufferSize(hOut, size); //重设缓冲区大小

    SMALL_RECT rc = { 0 , 0, 120, 30 };
    SetConsoleWindowInfo(hOut, true, &rc); //重设窗口大小

    SetConsoleTextAttribute(hOut, CYAN);

    for (int i = STARTX - 2; i <= ENDX + 2; i += 2) { //横向墙体
        GoTo(i, STARTY - 1);
        printf("■");
        GoTo(i, ENDY + 1);
        printf("■");
    }
    for (int i = STARTY - 1; i <= ENDY + 1; ++i) { //竖向墙体
        GoTo(STARTX - 2, i);
        printf("■");
        GoTo(ENDX + 2, i);
        printf("■");
    }
}
void draw()
{
    char m=snakeLen+62;
    Color(score);
    cout<<m;
 } 
void Init() { //初始化游戏
    system("cls");
    memset(isSnake, 0, sizeof(isSnake));
    speed = 200;
    curDiraction = 4;
    score = 0;
    DrawBoard();
    InitSnake();
    ShowInformation();
    AddFood();
    mj=clock();
    point=20;
    sysj=20;
}

void RunSnake(int x, int y) { //绘制蛇身
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    score += snakeLen + 1;
    if (x == foodx && y == foody) {
        EartFood();
        AddFood();
        return;
    }
    DrawBoard();
    snake.push_front(Node(x, y));
    isSnake[y][x] = true;
    GoTo(x, y);
    draw();
    Node back = snake.back();
    snake.pop_back();
    isSnake[back.y][back.x] = false;
    GoTo(back.x, back.y);
    printf(" ");
}

void Try(int& x, int& y) { //试走
    int key, cnt = 100;
    while (cnt--) { //多次检测键盘状态
        if (_kbhit()) {
            key = getch();
            switch (key) {
            case UP: 
//                if (curDiraction == 1 || curDiraction == 2) break;
                --y; curDiraction = 1; return;
            case DOWN: 
//                if (curDiraction == 1 || curDiraction == 2) break;
                ++y; curDiraction = 2; return;
            case LEFT: 
//                if (curDiraction == 3 || curDiraction == 4) break;
                x -= 2; curDiraction = 3; return;
            case RIGHT: 
//                if (curDiraction == 3 || curDiraction == 4) break;
                x += 2; curDiraction = 4; return;
            }
        }
    }
    if (curDiraction == 1) --y; //用户没有输入时
    else if (curDiraction == 2) ++y;
    else if (curDiraction == 3) x -= 2;
    else x += 2;
}

bool IsGoodCoord(int x, int y) { //判断光标是否合法
    if (x <= ENDX && y <= ENDY && x >= STARTX && y >= STARTY)
        return true;
    else
        return false;
}

void AddFood() { //增加食物
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), PURPLE);
    srand((unsigned)time(NULL));
    while (true) {
        foodx = (rand()%ENDX) + 1;
        foody = (rand()%ENDY) + 1;
        if (foodx&1) foodx++;
        if (!isSnake[foody][foodx] && IsGoodCoord(foodx, foody)) break;
    }
    GoTo(foodx, foody);
    int a=rand()%5;
    if(a>=4) 
    printf("★");
    else if(a<=1) 
    printf("○");
    else
    printf("▲");
}

void EartFood() { //吃东西
    point+=4;
    int sb=gametime=(clock()-mj)/1000;
    sysj=point-sb;
    score+=score/2;
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    snake.push_front(Node(foodx, foody));
    isSnake[foody][foodx] = true;
    ++snakeLen;
    if (speed >= 55) speed -= 5;

    GoTo(foodx, foody);
    draw();
    AddFood(); 
}

void InitSnake() { //初始化蛇身
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    snakeLen = 3, gox = 18, goy = 14;
    snake.clear();
    snake.push_front(Node(12, 14));
    snake.push_front(Node(14, 14));
    snake.push_front(Node(16, 14));
    for (int i = 12; i <= 16; i += 2) {
        GoTo(i, 14);
        draw();
        isSnake[14][i] = true;
    }
}
bool EndGame() { //结束游戏
    system("cls");
    DrawBoard();
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    GoTo(28, 10);
    printf("您的本局游戏得分: %d分", score);
    GoTo(32, 18);
    printf("....你挂了....");
    GoTo(27, 20);
    printf("是否继续游戏: 是(1), 否(0)");
    GoTo(27, 22);
    char key = getch();
    while (true) {
        if (key == '1') return false;
        else if (key == '0') 
        {GoTo(ENDX+1,ENDY+2);
        exit(0);return true;
        }
        else key = getch();
    }
}

bool StartGame() { //启动游戏

    Init();

    while (sysj>0) { //开挂
        RunSnake(gox, goy);
        ShowInformation();
        Try(gox, goy);
        Sleep(speed);
    }
    InputData(); 
    return true;
}

bool GameMenu() { //游戏菜单
    system("cls");
    DrawBoard();
    GoTo(STARTX + 22, STARTY + 4);
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    printf("欢迎进入贪吃蛇游戏!");
    GoTo(STARTX + 24, STARTY + 10);
    printf("1: 新游戏");
    GoTo(STARTX + 24, STARTY + 12);
    printf("2: 排行榜");
    GoTo(STARTX + 24, STARTY + 14);
    printf("3: 关于游戏");
    GoTo(STARTX + 24, STARTY + 16);
    printf("4: 退出游戏");

    while (true) {
        if (_kbhit()) {
            char key = getch();
            switch (key) {
            case '1':
                if (!StartGame()) return false; 
                else return true;
            case '2':
                ShowRanking(); return true;
            case '3':
                ShowAbout(); return true;
            case '4':
                GoTo(1,ENDY+2);
                return false;
            default:
                return true;
            }
        }
    }
}

void ShowRanking() { //展示排行榜
    vector<UserData> vu;
    FILE *fp = fopen("Gamedata2.txt", "r");
    if (fp == NULL) fp = fopen("Gamedata2.txt", "w+");
    char name[20];
    int len = 0;
    while (fscanf(fp, "%s", name) != EOF) {
        ++len;
        int score,g=grade;
        fscanf(fp, "%d%d%d%*c", &score,&gametime,&g);
        vu.push_back(UserData(string(name), score,gametime,g));
    }
    fclose(fp);
    sort(vu.begin(), vu.end()); //对得分进行排名
    system("cls");
    DrawBoard();
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), CYAN);
    GoTo(STARTX + 8, STARTY + 2);
    printf("用户");
    GoTo(STARTX + 20, STARTY + 2);
    printf("分数");
    GoTo(STARTX + 32, STARTY + 2);
    printf("生存时间");
    GoTo(STARTX + 44, STARTY + 2);
    printf("排行");
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);

    for (int i = 0; i < len && i < 10; ++i) { //打印前十名用户数据
        char const *p = vu[i].name.c_str();
        Color(score);
        GoTo(STARTX + 8, STARTY + 4 + i);
        printf("%s", p);
        GoTo(STARTX + 20, STARTY + 4 + i);
        printf("%d分", vu[i].score);
        GoTo(STARTX + 32, STARTY + 4 + i);
        printf("%d秒", vu[i].gt);
        GoTo(STARTX + 44, STARTY + 4 + i);
        printf(" %d", i + 1);
    }

    GoTo(STARTX + 4, ENDY - 2);
    printf("-----------------  按'1'返回游戏菜单  ---------------");
    while (true) {
        if (_kbhit()) {
            char key = getch();
            if (key == '1') break;
        }
    }
}

void ShowAbout() { //展示游戏相关
    system("cls");
    DrawBoard();
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);

    GoTo(STARTX + 4, STARTY + 2);
    printf("-------------------  贪吃蛇游戏  -------------------");
    GoTo(STARTX + 10, STARTY + 4);
    printf("制作人: ");
    GoTo(STARTX + 10, STARTY + 6);
    printf("李凯昱");
    GoTo(STARTX + 10,STARTY + 8);
    printf("贪吃蛇游戏");
    GoTo(STARTX + 10,STARTY + 10);
    printf("游戏规则:");
    GoTo(STARTX + 10,STARTY + 12);
    printf("请按 ↑ ↓ ← →  来控制您的蛇吃东西");
    GoTo(STARTX + 10,STARTY + 14);
    printf("吃的越多,蛇就越长,您的等级也将越高");
    GoTo(STARTX + 10,STARTY + 16);
    printf("当蛇吃到自己或撞上墙时,游戏结束。");

    GoTo(STARTX + 4, ENDY - 2);
    printf("-----------------  按'1'返回游戏菜单  ---------------");
    while (true) {
        if (_kbhit()) {
            char key = getch();
            if (key == '1') break;
        }
    }
}

void InputData() { //用户输入名字
    char name[20];
    if(score>=1000)
    {
    GoTo(STARTX + 10, STARTY + 10);
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), RED);
    printf("请输入你的名字: ");
    COORD coord = { STARTX + 10, STARTY + 12 };
    SetConsoleCursorPosition(GetStdHandle(STD_INPUT_HANDLE), coord);
    while (true) { //忽略非法字符
        scanf("%s", name);
        if (name[0] != 0 && name[0] != ' ') break; 
    }FILE *fp = fopen("Gamedata2.txt", "a");
    if (fp == NULL) fp = fopen("Gamedata2.txt", "w+");
    fprintf(fp, "%s %d %d \n", name, score,gametime);
    fclose(fp);
    }
    else 
    {
        GoTo(STARTX + 20, STARTY + 10);
        cout<<"哟!这分数也能上榜??"<<endl; 
        Sleep(1000);
     }  
    EndGame(); 
    
}

6 条评论

  • @ 2018-08-25 09:35:04

    乱码?不存在的

  • @ 2018-08-25 09:34:25
    #include <iostream>
    #include <list>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <ctime>
    #include <algorithm>
    #include <conio.h>
    #include <windows.h>
    using namespace std;
    
    class Node { 
    public:
        int x, y;
        Node(int x1, int y1); 
    };
    
    class UserData { 
    public:
        string name;
        long long score;
        int gt;
        int gr; 
        UserData(string s, long long sc,int gametime,int grade); 
        friend bool operator < (UserData a, UserData b); 
    };
    
    #define RIGHT 0x4d
    #define LEFT 0x4b  
    #define UP 0x48  
    #define DOWN 0x50 
    #define YELLOW FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
    #define CYAN FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY
    #define ORANGE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
    #define PURPLE FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY
    #define RED  FOREGROUND_RED | FOREGROUND_INTENSITY
    const int STARTX = 8; 
    const int STARTY = 4; 
    const int RANGEX = 60; 
    const int RANGEY = 20;
    int point=10; 
    const int ENDX = STARTX + RANGEX; 
    const int ENDY = STARTY + RANGEY; 
    bool isSnake[RANGEY + 10 ][RANGEX + 10];
    int speed; 
    int sysj;
    int gametime;
    list<Node> snake;
    int curDiraction; //蛇的当前前进方向, 1上, 2下, 3左, 4右
    int score; //当前分数
    int grade;
    int snakeLen; //蛇的长度
    int foodx, foody; //食物坐标
    int gox, goy; //蛇头坐标
    int mj;
    void GoTo(short x, short y); //定位光标
    void DrawBoard(); //绘制边框
    void ShowInformation(); //展示游戏信息
    void Init(); //初始化游戏
    void RunSnake(int x, int y); //绘制蛇身
    void Try(int& x, int& y); //试走
    bool IsGoodCoord(int x, int y); //前进坐标是否合法
    void AddFood(); //增加食物
    void EartFood(); //吃食物
    void InitSnake(); //初始化蛇身
    bool EndGame(); //结束游戏
    bool StartGame(); //启动游戏
    bool GameMenu(); //游戏菜单
    void ShowRanking(); //排行榜
    void ShowAbout(); //相关信息
    void InputData(); //输入玩家名字
    
    int main() {
        system("title 贪吃蛇小游戏 by 李凯昱");
        while (true) {
            if (!GameMenu()) return 0;
        }
        return 0;
    }
    
    Node::Node(int x1, int y1) { //构造Node对象
        x = x1; y = y1; 
    }
    
    bool operator < (UserData a, UserData b) { //重载运算符,按分数由大到小排列
        if(a.score != b.score)
        return a.score > b.score;
        if(a.gt !=b.gt)
        return a.gt > b.gt;
        else
        return a.gr > b.gr;
    }
    UserData::UserData(string s, long long sc,int gametime_,int _grade) { //构造UserData对象
        name = s; score = sc; gt=gametime_; gr=_grade;
    }
    
    void color(WORD A)
    {
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), A);
    } 
    
    void Color(int score_)
    {
        if(score_%4==1)
        {
            color(PURPLE);
        }
        else if(score_%4==2)
        {
            color(RED);
        }
        else if(score_%4==3)
        {
            color(YELLOW);
        }
        else if(score_%4==0) 
        {
            color(CYAN);
        }
    }
    
    void GoTo(short x, short y) { //定位光标
        COORD coord = { x, y };
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    }
    
    void ShowInformation() { //输出游戏信息
        color(YELLOW);
        GoTo(78, 5);
        printf("贪吃蛇游戏");
        GoTo(78,18);
        gametime=(clock()-mj)/1000;
        grade=snakeLen-3; 
        printf("生存时间:%3d 秒",(clock()-mj)/1000);
        GoTo(78, 8);
        printf("游戏规则:");
        GoTo(78, 10);
        printf("请按 ↑ ↓ ← →  来控制您的蛇吃东西");
        GoTo(78, 12);
        printf("吃的越多,蛇就越长,您的等级也将越高");
        GoTo(78, 14);
        printf("当蛇吃到自己或撞上墙时,游戏结束。");
        GoTo(78,16);
        printf("自动前进时间:%3dms",speed);
        GoTo(78, 20);
        printf("当前等级: %8d", snakeLen-3);
        GoTo(78, 23);
        printf("您的分数: %d", score);
        color(CYAN);
        printf("+%d=%d",score/3,score*3/2);
        color(YELLOW);
        GoTo(78,25);
        printf("剩余时间:%d秒",10+(snakeLen-3)*4-gametime);
        sysj=10+(snakeLen-3)*4-gametime; 
    }
    
    void DrawBoard() { //绘制墙体
    
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); //获得输出句柄
    
        CONSOLE_CURSOR_INFO cursor_info = { 1, 0 }; //光标信息
        SetConsoleCursorInfo(hOut, &cursor_info); //隐藏光标
    
        COORD size = { 120, 30 };
        SetConsoleScreenBufferSize(hOut, size); //重设缓冲区大小
    
        SMALL_RECT rc = { 0 , 0, 120, 30 };
        SetConsoleWindowInfo(hOut, true, &rc); //重设窗口大小
    
        SetConsoleTextAttribute(hOut, CYAN);
    
        for (int i = STARTX - 2; i <= ENDX + 2; i += 2) { //横向墙体
            GoTo(i, STARTY - 1);
            printf("■");
            GoTo(i, ENDY + 1);
            printf("■");
        }
        for (int i = STARTY - 1; i <= ENDY + 1; ++i) { //竖向墙体
            GoTo(STARTX - 2, i);
            printf("■");
            GoTo(ENDX + 2, i);
            printf("■");
        }
    }
    void draw()
    {
        char m=snakeLen+62;
        Color(score);
        cout<<"■";
     } 
    void Init() { //初始化游戏
        system("cls");
        memset(isSnake, 0, sizeof(isSnake));
        speed = 200;
        curDiraction = 4;
        score = 0;
        DrawBoard();
        InitSnake();
        ShowInformation();
        AddFood();
        mj=clock();
        point=10;
        sysj=10;
    }
    
    void RunSnake(int x, int y) { //绘制蛇身
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
        score += snakeLen + 1;
        if (x == foodx && y == foody) {
            EartFood();
            AddFood();
            return;
        }
        snake.push_front(Node(x, y));
        isSnake[y][x] = true;
        GoTo(x, y);
        draw();
        Node back = snake.back();
        snake.pop_back();
        isSnake[back.y][back.x] = false;
        GoTo(back.x, back.y);
        printf(" ");
    }
    
    void Try(int& x, int& y) { //试走
        int key, cnt = 100;
        while (cnt--) { //多次检测键盘状态
            if (_kbhit()) {
                key = getch();
                switch (key) {
                case UP: 
                    if (curDiraction == 1 || curDiraction == 2) break;
                    --y; curDiraction = 1; return;
                case DOWN: 
                    if (curDiraction == 1 || curDiraction == 2) break;
                    ++y; curDiraction = 2; return;
                case LEFT: 
                    if (curDiraction == 3 || curDiraction == 4) break;
                    x -= 2; curDiraction = 3; return;
                case RIGHT: 
                    if (curDiraction == 3 || curDiraction == 4) break;
                    x += 2; curDiraction = 4; return;
                }
            }
        }
        if (curDiraction == 1) --y; //用户没有输入时
        else if (curDiraction == 2) ++y;
        else if (curDiraction == 3) x -= 2;
        else x += 2;
    }
    
    bool IsGoodCoord(int x, int y) { //判断光标是否合法
        if (x <= ENDX && y <= ENDY && x >= STARTX && y >= STARTY)
            return true;
        else
            return false;
    }
    
    void AddFood() { //增加食物
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), PURPLE);
        srand((unsigned)time(NULL));
        while (true) {
            foodx = (rand()%ENDX) + 1;
            foody = (rand()%ENDY) + 1;
            if (foodx&1) foodx++;
            if (!isSnake[foody][foodx] && IsGoodCoord(foodx, foody)) break;
        }
        GoTo(foodx, foody);
        int a=rand()%5;
        if(a>=4) 
        printf("★");
        else if(a<=1) 
        printf("○");
        else
        printf("▲");
    }
    
    void EartFood() { //吃东西
        point+=4;
        int sb=gametime=(clock()-mj)/1000;
        sysj=point-sb;
        score+=score/2;
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
        snake.push_front(Node(foodx, foody));
        isSnake[foody][foodx] = true;
        ++snakeLen;
        if (speed >= 55) speed -= 5;
    
        GoTo(foodx, foody);
        draw();
        AddFood(); 
    }
    
    void InitSnake() { //初始化蛇身
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
        snakeLen = 3, gox = 18, goy = 14;
        snake.clear();
        snake.push_front(Node(12, 14));
        snake.push_front(Node(14, 14));
        snake.push_front(Node(16, 14));
        for (int i = 12; i <= 16; i += 2) {
            GoTo(i, 14);
            draw();
            isSnake[14][i] = true;
        }
    }
    bool EndGame() { //结束游戏
        system("cls");
        DrawBoard();
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
        GoTo(28, 10);
        printf("您的本局游戏得分: %d分", score);
        GoTo(32, 18);
        printf("....你挂了....");
        GoTo(27, 20);
        printf("是否继续游戏: 是(1), 否(0)");
        GoTo(27, 22);
        char key = getch();
        while (true) {
            if (key == '1') return false;
            else if (key == '0') 
            {GoTo(ENDX+1,ENDY+2);
            exit(0);return true;
            }
            else key = getch();
        }
    }
    
    bool StartGame() { //启动游戏
    
        Init();
    
        while (IsGoodCoord(gox, goy) && !isSnake[goy][gox]&&sysj>0) { //当试走合法时
            RunSnake(gox, goy);
            ShowInformation();
            Try(gox, goy);
            Sleep(speed);
        }
        InputData(); 
        return true;
    }
    
    bool GameMenu() { //游戏菜单
        system("cls");
        DrawBoard();
        GoTo(STARTX + 22, STARTY + 4);
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
        printf("欢迎进入贪吃蛇游戏!");
        GoTo(STARTX + 24, STARTY + 10);
        printf("1: 新游戏");
        GoTo(STARTX + 24, STARTY + 12);
        printf("2: 排行榜");
        GoTo(STARTX + 24, STARTY + 14);
        printf("3: 关于游戏");
        GoTo(STARTX + 24, STARTY + 16);
        printf("4: 退出游戏");
    
        while (true) {
            if (_kbhit()) {
                char key = getch();
                switch (key) {
                case '1':
                    if (!StartGame()) return false; 
                    else return true;
                case '2':
                    ShowRanking(); return true;
                case '3':
                    ShowAbout(); return true;
                case '4':
                    GoTo(1,ENDY+2);
                    return false;
                default:
                    return true;
                }
            }
        }
    }
    
    void ShowRanking() { //展示排行榜
        vector<UserData> vu;
        FILE *fp = fopen("GameData.txt", "r");
        if (fp == NULL) fp = fopen("GameData.txt", "w+");
        char name[20];
        int len = 0;
        while (fscanf(fp, "%s", name) != EOF) {
            ++len;
            int score,g=grade;
            fscanf(fp, "%d%d%d%*c", &score,&gametime,&g);
            vu.push_back(UserData(string(name), score,gametime,grade));
        }
        fclose(fp);
        sort(vu.begin(), vu.end()); //对得分进行排名
        system("cls");
        DrawBoard();
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), CYAN);
        GoTo(STARTX + 8, STARTY + 2);
        printf("用户");
        GoTo(STARTX + 20, STARTY + 2);
        printf("分数");
        GoTo(STARTX + 32, STARTY + 2);
        printf("生存时间");
        GoTo(STARTX + 44, STARTY + 2);
        printf("排行");
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    
        for (int i = 0; i < len && i < 10; ++i) { //打印前十名用户数据
            char const *p = vu[i].name.c_str();
            Color(vu[i].score);
            GoTo(STARTX + 8, STARTY + 4 + i);
            printf("%s", p);
            GoTo(STARTX + 20, STARTY + 4 + i);
            printf("%d分", vu[i].score);
            GoTo(STARTX + 32, STARTY + 4 + i);
            printf("%d秒", vu[i].gt);
            GoTo(STARTX + 44, STARTY + 4 + i);
            printf(" %d", i + 1);
        }
    
        GoTo(STARTX + 4, ENDY - 2);
        printf("-----------------  按'1'返回游戏菜单  ---------------");
        while (true) {
            if (_kbhit()) {
                char key = getch();
                if (key == '1') break;
            }
        }
    }
    
    void ShowAbout() { //展示游戏相关
        system("cls");
        DrawBoard();
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    
        GoTo(STARTX + 4, STARTY + 2);
        printf("-------------------  贪吃蛇游戏  -------------------");
        GoTo(STARTX + 10, STARTY + 4);
        printf("制作人: ");
        GoTo(STARTX + 10, STARTY + 6);
        printf("李凯昱");
        GoTo(STARTX + 10,STARTY + 8);
        printf("贪吃蛇游戏");
        GoTo(STARTX + 10,STARTY + 10);
        printf("游戏规则:");
        GoTo(STARTX + 10,STARTY + 12);
        printf("请按 ↑ ↓ ← →  来控制您的蛇吃东西");
        GoTo(STARTX + 10,STARTY + 14);
        printf("吃的越多,蛇就越长,您的等级也将越高");
        GoTo(STARTX + 10,STARTY + 16);
        printf("当蛇吃到自己或撞上墙时,游戏结束。");
    
        GoTo(STARTX + 4, ENDY - 2);
        printf("-----------------  按'1'返回游戏菜单  ---------------");
        while (true) {
            if (_kbhit()) {
                char key = getch();
                if (key == '1') break;
            }
        }
    }
    
    void InputData() { //用户输入名字
        char name[20];
        if(score>=1000)
        {
        GoTo(STARTX + 10, STARTY + 10);
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), RED);
        printf("请输入你的名字: ");
        COORD coord = { STARTX + 10, STARTY + 12 };
        SetConsoleCursorPosition(GetStdHandle(STD_INPUT_HANDLE), coord);
        while (true) { //忽略非法字符
            scanf("%s", name);
            if (name[0] != 0 && name[0] != ' ') break; 
        }FILE *fp = fopen("Gamedata.txt", "a");
        if (fp == NULL) fp = fopen("GameData.txt", "w+");
        fprintf(fp, "%s %d %d \n", name, score,gametime);
        fclose(fp);
        }
        else 
        {
            GoTo(STARTX + 20, STARTY + 10);
            cout<<"哟!这分数也能上榜??"<<endl; 
            Sleep(1000);
         }  
        EndGame(); 
        
    }
    Copy
    破解版:
    #include <iostream>
    #include <list>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <ctime>
    #include <algorithm>
    #include <conio.h>
    #include <windows.h>
    using namespace std;
    class Node { 
    public:
        int x, y;
        Node(int x1, int y1); 
    };
    
    class UserData { 
    public:
        string name;
        long long score;
        int gt;
        int gr; 
        UserData(string s, long long sc,int gametime,int grade); 
        friend bool operator < (UserData a, UserData b); 
    };
    
    #define RIGHT 0x4d
    #define LEFT 0x4b  
    #define UP 0x48  
    #define DOWN 0x50 
    #define YELLOW FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
    #define CYAN FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY
    #define ORANGE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
    #define PURPLE FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY
    #define RED  FOREGROUND_RED | FOREGROUND_INTENSITY
    const int STARTX = 8; 
    const int STARTY = 4; 
    const int RANGEX = 60; 
    const int RANGEY = 20;
    int point=10; 
    const int ENDX = STARTX + RANGEX; 
    const int ENDY = STARTY + RANGEY; 
    bool isSnake[RANGEY + 10 ][RANGEX + 10];
    int speed; 
    int sysj;
    int gametime;
    list<Node> snake;
    int curDiraction; //蛇的当前前进方向, 1上, 2下, 3左, 4右
    int score; //当前分数
    int grade;
    int snakeLen; //蛇的长度
    int foodx, foody; //食物坐标
    int gox, goy; //蛇头坐标
    int mj;
    void GoTo(short x, short y); //定位光标
    void DrawBoard(); //绘制边框
    void ShowInformation(); //展示游戏信息
    void Init(); //初始化游戏
    void RunSnake(int x, int y); //绘制蛇身
    void Try(int& x, int& y); //试走
    bool IsGoodCoord(int x, int y); //前进坐标是否合法
    void AddFood(); 
    void EartFood();
    void InitSnake(); 
    bool EndGame(); 
    bool StartGame();
    bool GameMenu(); //游戏菜单
    void ShowRanking(); //排行榜
    void ShowAbout(); //相关信息
    void InputData(); //输入玩家名字
    
    int main() {
        system("title 贪吃蛇小游戏 by 李凯昱");
        while (true) {
            if (!GameMenu()) return 0;
        }
        return 0;
    }
    
    Node::Node(int x1, int y1) { //构造Node对象
        x = x1; y = y1; 
    }
    
    int SuiJi()
    {
    srand((unsigned)time(NULL));
    return (rand()*rand()+rand()*rand())%14;
    }
    
    bool operator < (UserData a, UserData b) { //重载运算符,按分数由大到小排列
        if(a.score != b.score)
        return a.score > b.score;
        if(a.gt !=b.gt)
        return a.gt > b.gt;
        else
        return a.gr > b.gr;
    }
    UserData::UserData(string s, long long sc,int gametime_,int _grade) { //构造UserData对象
        name = s; score = sc; gt=gametime_; gr=_grade;
    }
    
    void color(WORD A)
    {
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), A);
    } 
    
    void Color(int a)
    {
        switch (a%4)
        {
            case 0:color(RED);break;
            case 1:color(CYAN);break;
            case 2:color(YELLOW);break;
            case 3:color(PURPLE);break;
        }
    }
    
    void GoTo(short x, short y) { //定位光标
        COORD coord = { x, y };
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    }
    
    void ShowInformation() { //输出游戏信息
        color(YELLOW);
        GoTo(78, 5);
        printf("贪吃蛇游戏");
        GoTo(78,18);
        gametime=(clock()-mj)/1000;
        grade=snakeLen-3; 
        printf("生存时间:%3d 秒",(clock()-mj)/1000);
        GoTo(78, 8);
        printf("游戏规则:");
        GoTo(78, 10);
        printf("请按 ↑ ↓ ← →  来控制您的蛇吃东西");
        GoTo(78, 12);
        printf("吃的越多,蛇就越长,您的等级也将越高");
        GoTo(78, 14);
        printf("当蛇吃到自己或撞上墙时,游戏结束。");
        GoTo(78,16);
        printf("自动前进时间:%3dms",speed);
        GoTo(78, 20);
        printf("当前等级: %8d", snakeLen-3);
        GoTo(78, 23);
        printf("您的分数: %d", score);
        color(CYAN);
        printf("+%d=%d",score/3,score*3/2);
        color(YELLOW);
        GoTo(78,25);
        printf("剩余时间:%d秒",20+(snakeLen-3)*5-gametime);
        sysj=20+(snakeLen-3)*5-gametime; 
    }
    
    void DrawBoard() { //绘制墙体
    
        HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); //获得输出句柄
    
        CONSOLE_CURSOR_INFO cursor_info = { 1, 0 }; //光标信息
        SetConsoleCursorInfo(hOut, &cursor_info); //隐藏光标
    
        COORD size = { 120, 30 };
        SetConsoleScreenBufferSize(hOut, size); //重设缓冲区大小
    
        SMALL_RECT rc = { 0 , 0, 120, 30 };
        SetConsoleWindowInfo(hOut, true, &rc); //重设窗口大小
    
        SetConsoleTextAttribute(hOut, CYAN);
    
        for (int i = STARTX - 2; i <= ENDX + 2; i += 2) { //横向墙体
            GoTo(i, STARTY - 1);
            printf("■");
            GoTo(i, ENDY + 1);
            printf("■");
        }
        for (int i = STARTY - 1; i <= ENDY + 1; ++i) { //竖向墙体
            GoTo(STARTX - 2, i);
            printf("■");
            GoTo(ENDX + 2, i);
            printf("■");
        }
    }
    void draw()
    {
        char m=snakeLen+62;
        Color(score);
        cout<<m;
     } 
    void Init() { //初始化游戏
        system("cls");
        memset(isSnake, 0, sizeof(isSnake));
        speed = 200;
        curDiraction = 4;
        score = 0;
        DrawBoard();
        InitSnake();
        ShowInformation();
        AddFood();
        mj=clock();
        point=20;
        sysj=20;
    }
    
    void RunSnake(int x, int y) { //绘制蛇身
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
        score += snakeLen + 1;
        if (x == foodx && y == foody) {
            EartFood();
            AddFood();
            return;
        }
        DrawBoard();
        snake.push_front(Node(x, y));
        isSnake[y][x] = true;
        GoTo(x, y);
        draw();
        Node back = snake.back();
        snake.pop_back();
        isSnake[back.y][back.x] = false;
        GoTo(back.x, back.y);
        printf(" ");
    }
    
    void Try(int& x, int& y) { //试走
        int key, cnt = 100;
        while (cnt--) { //多次检测键盘状态
            if (_kbhit()) {
                key = getch();
                switch (key) {
                case UP: 
    //                if (curDiraction == 1 || curDiraction == 2) break;
                    --y; curDiraction = 1; return;
                case DOWN: 
    //                if (curDiraction == 1 || curDiraction == 2) break;
                    ++y; curDiraction = 2; return;
                case LEFT: 
    //                if (curDiraction == 3 || curDiraction == 4) break;
                    x -= 2; curDiraction = 3; return;
                case RIGHT: 
    //                if (curDiraction == 3 || curDiraction == 4) break;
                    x += 2; curDiraction = 4; return;
                }
            }
        }
        if (curDiraction == 1) --y; //用户没有输入时
        else if (curDiraction == 2) ++y;
        else if (curDiraction == 3) x -= 2;
        else x += 2;
    }
    
    bool IsGoodCoord(int x, int y) { //判断光标是否合法
        if (x <= ENDX && y <= ENDY && x >= STARTX && y >= STARTY)
            return true;
        else
            return false;
    }
    
    void AddFood() { //增加食物
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), PURPLE);
        srand((unsigned)time(NULL));
        while (true) {
            foodx = (rand()%ENDX) + 1;
            foody = (rand()%ENDY) + 1;
            if (foodx&1) foodx++;
            if (!isSnake[foody][foodx] && IsGoodCoord(foodx, foody)) break;
        }
        GoTo(foodx, foody);
        int a=rand()%5;
        if(a>=4) 
        printf("★");
        else if(a<=1) 
        printf("○");
        else
        printf("▲");
    }
    
    void EartFood() { //吃东西
        point+=4;
        int sb=gametime=(clock()-mj)/1000;
        sysj=point-sb;
        score+=score/2;
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
        snake.push_front(Node(foodx, foody));
        isSnake[foody][foodx] = true;
        ++snakeLen;
        if (speed >= 55) speed -= 5;
    
        GoTo(foodx, foody);
        draw();
        AddFood(); 
    }
    
    void InitSnake() { //初始化蛇身
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
        snakeLen = 3, gox = 18, goy = 14;
        snake.clear();
        snake.push_front(Node(12, 14));
        snake.push_front(Node(14, 14));
        snake.push_front(Node(16, 14));
        for (int i = 12; i <= 16; i += 2) {
            GoTo(i, 14);
            draw();
            isSnake[14][i] = true;
        }
    }
    bool EndGame() { //结束游戏
        system("cls");
        DrawBoard();
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
        GoTo(28, 10);
        printf("您的本局游戏得分: %d分", score);
        GoTo(32, 18);
        printf("....你挂了....");
        GoTo(27, 20);
        printf("是否继续游戏: 是(1), 否(0)");
        GoTo(27, 22);
        char key = getch();
        while (true) {
            if (key == '1') return false;
            else if (key == '0') 
            {GoTo(ENDX+1,ENDY+2);
            exit(0);return true;
            }
            else key = getch();
        }
    }
    
    bool StartGame() { //启动游戏
    
        Init();
    
        while (sysj>0) { //开挂
            RunSnake(gox, goy);
            ShowInformation();
            Try(gox, goy);
            Sleep(speed);
        }
        InputData(); 
        return true;
    }
    
    bool GameMenu() { //游戏菜单
        system("cls");
        DrawBoard();
        GoTo(STARTX + 22, STARTY + 4);
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
        printf("欢迎进入贪吃蛇游戏!");
        GoTo(STARTX + 24, STARTY + 10);
        printf("1: 新游戏");
        GoTo(STARTX + 24, STARTY + 12);
        printf("2: 排行榜");
        GoTo(STARTX + 24, STARTY + 14);
        printf("3: 关于游戏");
        GoTo(STARTX + 24, STARTY + 16);
        printf("4: 退出游戏");
    
        while (true) {
            if (_kbhit()) {
                char key = getch();
                switch (key) {
                case '1':
                    if (!StartGame()) return false; 
                    else return true;
                case '2':
                    ShowRanking(); return true;
                case '3':
                    ShowAbout(); return true;
                case '4':
                    GoTo(1,ENDY+2);
                    return false;
                default:
                    return true;
                }
            }
        }
    }
    
    void ShowRanking() { //展示排行榜
        vector<UserData> vu;
        FILE *fp = fopen("Gamedata2.txt", "r");
        if (fp == NULL) fp = fopen("Gamedata2.txt", "w+");
        char name[20];
        int len = 0;
        while (fscanf(fp, "%s", name) != EOF) {
            ++len;
            int score,g=grade;
            fscanf(fp, "%d%d%d%*c", &score,&gametime,&g);
            vu.push_back(UserData(string(name), score,gametime,g));
        }
        fclose(fp);
        sort(vu.begin(), vu.end()); //对得分进行排名
        system("cls");
        DrawBoard();
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), CYAN);
        GoTo(STARTX + 8, STARTY + 2);
        printf("用户");
        GoTo(STARTX + 20, STARTY + 2);
        printf("分数");
        GoTo(STARTX + 32, STARTY + 2);
        printf("生存时间");
        GoTo(STARTX + 44, STARTY + 2);
        printf("排行");
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    
        for (int i = 0; i < len && i < 10; ++i) { //打印前十名用户数据
            char const *p = vu[i].name.c_str();
            Color(score);
            GoTo(STARTX + 8, STARTY + 4 + i);
            printf("%s", p);
            GoTo(STARTX + 20, STARTY + 4 + i);
            printf("%d分", vu[i].score);
            GoTo(STARTX + 32, STARTY + 4 + i);
            printf("%d秒", vu[i].gt);
            GoTo(STARTX + 44, STARTY + 4 + i);
            printf(" %d", i + 1);
        }
    
        GoTo(STARTX + 4, ENDY - 2);
        printf("-----------------  按'1'返回游戏菜单  ---------------");
        while (true) {
            if (_kbhit()) {
                char key = getch();
                if (key == '1') break;
            }
        }
    }
    
    void ShowAbout() { //展示游戏相关
        system("cls");
        DrawBoard();
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), YELLOW);
    
        GoTo(STARTX + 4, STARTY + 2);
        printf("-------------------  贪吃蛇游戏  -------------------");
        GoTo(STARTX + 10, STARTY + 4);
        printf("制作人: ");
        GoTo(STARTX + 10, STARTY + 6);
        printf("李凯昱");
        GoTo(STARTX + 10,STARTY + 8);
        printf("贪吃蛇游戏");
        GoTo(STARTX + 10,STARTY + 10);
        printf("游戏规则:");
        GoTo(STARTX + 10,STARTY + 12);
        printf("请按 ↑ ↓ ← →  来控制您的蛇吃东西");
        GoTo(STARTX + 10,STARTY + 14);
        printf("吃的越多,蛇就越长,您的等级也将越高");
        GoTo(STARTX + 10,STARTY + 16);
        printf("当蛇吃到自己或撞上墙时,游戏结束。");
    
        GoTo(STARTX + 4, ENDY - 2);
        printf("-----------------  按'1'返回游戏菜单  ---------------");
        while (true) {
            if (_kbhit()) {
                char key = getch();
                if (key == '1') break;
            }
        }
    }
    
    void InputData() { //用户输入名字
        char name[20];
        if(score>=1000)
        {
        GoTo(STARTX + 10, STARTY + 10);
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), RED);
        printf("请输入你的名字: ");
        COORD coord = { STARTX + 10, STARTY + 12 };
        SetConsoleCursorPosition(GetStdHandle(STD_INPUT_HANDLE), coord);
        while (true) { //忽略非法字符
            scanf("%s", name);
            if (name[0] != 0 && name[0] != ' ') break; 
        }FILE *fp = fopen("Gamedata2.txt", "a");
        if (fp == NULL) fp = fopen("Gamedata2.txt", "w+");
        fprintf(fp, "%s %d %d \n", name, score,gametime);
        fclose(fp);
        }
        else 
        {
            GoTo(STARTX + 20, STARTY + 10);
            cout<<"哟!这分数也能上榜??"<<endl; 
            Sleep(1000);
         }  
        EndGame(); 
        
    }
    
  • @ 2018-04-06 17:02:33

    这破解版真是666啊

  • @ 2018-02-01 08:56:07

    ······

  • @ 2018-01-31 23:15:46

    666sixsixsix

  • @ 2018-01-30 10:23:17

    啊啊啊乱码啊啊啊ε=ε=ε=(#>д<)ノ

  • 1