iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言实现贪吃蛇小黑窗
  • 224
分享到

C语言实现贪吃蛇小黑窗

2024-04-02 19:04:59 224人浏览 安东尼
摘要

本文实例为大家分享了C语言实现贪吃蛇小黑窗的具体代码,供大家参考,具体内容如下 思路: 1.利用整型二维数组保存显示数据,小蛇每移动一次清屏并便利数组做到动态效果。每次移动(清屏)的

本文实例为大家分享了C语言实现贪吃蛇小黑窗的具体代码,供大家参考,具体内容如下

思路:

1.利用整型二维数组保存显示数据,小蛇每移动一次清屏并便利数组做到动态效果。每次移动(清屏)的间隔时间控制了游戏难度,这个时间应不断缩减,直到游戏结束。

2.需要保存小蛇移动的方向,然后写一个函数通过小蛇的移动方向去处理二维数组中的数据,达到移动小蛇的目的。

3.小蛇的移动可分解为两个过程:头部像前方生长一格然后尾部消去一格。如果蛇头吃到食物,尾部无需消去,此时应立即随机生成一个新的食物。

4.游戏开始时小蛇应随机生成在地图某一位置,此时小蛇的默认移动方向也应该是随机的。

5每次移动前应接收玩家由键盘输入的移动方向,如果接收到后,判断合法后将其设为小蛇的默认移动方向,如果玩家未进行任何输入,小蛇应按照默认方向移动。

个人难点:

1.小蛇移动

该函数需要拿到蛇头当时所在的位置坐标和小蛇的移动方向。随后可由蛇头位置往移动方向往前生长一格,即将二维数组中目标移动位置的数据设置为小蛇的数据。消去蛇尾另写一个函数,调用前需先判断是否吃到食物,是否撞到墙壁或者是自身,然后决定是否削去尾部。消去蛇尾需获得蛇尾的位置,所以我们在该函数内加入递归搜索蛇尾的算法:进入函数后先判断此时的位置是否为蛇尾,若不是就将自身位置往后移动一格(将蛇身往后一格的坐标输入给DeleteTail函数,然后继续此过程),直到遇到蛇尾,然后将其消去(置零)。

具体代码实现如下:


int MoveSnake(int trend, int* px, int* py, int data[ROW][COL], int* t)
{
    int ret = 1;//默认前进成功
    //printf("trend=%d\n", trend);
    switch (trend) {
    case 1:*py -= 1; break;//向上
    case 2:*px -= 1; break;//向左
    case 3:*py += 1; break;//向下
    case 4:*px += 1; break;//向右
    }//找到即将前进的坐标
    if (data[*py][*px] == 6) {
        data[*py][*px] = trend;
        CreatFood(data);
        *t *= 0.9;
    }//如果蛇头要前进的格子是食物,向前长一格,尾部不变;
    else if (data[*py][*px] == 0) {
        data[*py][*px] = trend;//向前长一格
        DeleteTail(*px, *py, data);//消去最后的尾巴
    }
    else {
        ret = 0;
        printf("前进失败\n");
    }//前进失败
    return ret;
}
 
int DeleteTail(int x, int y, int data[ROW][COL])
{
    //PrintTest(data);
    if (data[y][x] <= 4 && data[y][x] >= 1) {
        switch (data[y][x]) {
        case 1:
            if (DeleteTail(x, y + 1, data) == 0) {
                data[y][x] = 0;
            }
            break;
        case 2:
            if (DeleteTail(x + 1, y, data) == 0) {
                data[y][x] = 0;
            }
            break;
        case 3:
            if (DeleteTail(x, y - 1, data) == 0) {
                data[y][x] = 0;
            }
            break;
        case 4:
            if (DeleteTail(x - 1, y, data) == 0) {
                data[y][x] = 0;
            }
            break;
        }
        return 1;
    }
    else {
        return 0;
    }
}

2.输入

在实际代码实现的过程中,我发现scanf函数无法实现需求,理由是程序执行到scanf语句时,会停留在该位置,直到scanf函数扫描到输入后,程序才会继续进行。经学习查阅,决定使用kbhit函数扫描此时键盘缓冲区中是否有数据:如果有就读取第一个数据,并将后面的数据清空,避免后面使用该数据,若没有数据,缓冲区不做任何处理,程序也应当继续执行。

使用kbhit函数前应“#include<coNIO.h>”。清理缓冲区运用的是getch()循环。代码如下:

int Input() {
    int trend = 0;
    if (kbhit()) {
        char trend_ = getch();
        while (kbhit()) {
            getch();
        }//清空缓冲区
        //printf("已接收到%c ", trend_);
        switch (trend_) {
        case 'w':trend = 1; break;
        case 'a':trend = 2; break;
        case 's':trend = 3; break;
        case 'd':trend = 4; break;
        default:printf("请输入w,a,s,d以控制前进方向!!\n");
            break;
        }
    }
    else {
        printf("请输入w,a,s,d以控制前进方向!!\n");
    }
    return trend;
}

完整源代码:

#pragma once
#pragma warning(disable : 4996)
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<windows.h>
#include<conio.h>

#define ROW 30
#define COL 30
#define TIME 300

int Game();
int Menu();
int Input();
int CreatHead(int* px, int* py, int data[ROW][COL]);
void CreatFood(int data[ROW][COL]);
int MoveSnake(int trend, int* px, int* py, int data[ROW][COL], int* t);
int DeleteTail(int x, int y, int data[ROW][COL]);
void PrintShow(int data[ROW][COL]);
int GameOver(int score);
void PrintTest(int data[ROW][COL]);
#include"main.h"
int main()
{
    int ret = 1;
    while (ret) {
        int choose = Menu();
        int score = 0;
        switch (choose) {
        case 1:
            score = Game();
            ret = GameOver(score);
            break;
        case 2:
            system("cls");
            printf("==========================================================\n");
            printf("                      游戏说明                            \n");
            printf("  1.输入‘w'‘a'‘s'‘d'以控制小蛇的移动。\n");
            printf("  2.小蛇在固定时间内只移动一次,如一个时间段内输入多个方向\n则以第一次输入为准。\n");
            printf("  3.不能撞到墙壁或者是自身。\n");
            printf("  4.小蛇移动速度会在吃到食物后加快,直到游戏结束。\n");
            printf("  输入“1”继续...........\n");
            printf("==========================================================\n");
            int ok = 0;
            scanf("%d", &ok);
            if (ok) {
                system("cls");
                break;
            }
        case 3:
            ret = 0;
            break;
        }
    }
}

#include"main.h"

int Game()
{
    int data[ROW][COL] = { 0 };
    int time_ = TIME;
    for (int i = 0; i < COL; i++) {
        for (int j = 0; j < ROW; j++) {
            if (i == 0 || i == COL - 1) {
                data[i][j] = 5;//边界墙
            }
            if (j == 0 || j == ROW - 1) {
                data[i][j] = 5;//边界墙
            }
        }

    }//初始化数据存储数组
    //PrintShow(data);
    int x = 0, y = 0;
    int trend = CreatHead(&x, &y, data);
    //生成蛇头
    CreatFood(data);//生成食物
    int ret = 1;
    while (ret) {
        system("cls");
        PrintShow(data);
        Sleep(time_);
        int trend_ = Input();
        if (trend_ != 0) {
            trend = trend_;
        }
        ret = MoveSnake(trend, &x, &y, data, &time_);
    }
    int score = 0;
    for (int i = 0; i < ROW; i++) {
        for (int j = 0; j < COL; j++) {
            if (data[i][j] <= 4 && data[i][j] >= 1) {
                score++;
            }
        }
    }
    return score;
}

int Menu()
{
    int choose = 0;
    while (1) {
        printf("==========================\n");
        printf("===欢迎进入贪吃蛇游戏!===\n");
        printf("===   1、经典模式      ===\n");
        printf("===   2、游戏说明      ===\n");
        printf("===   3、退出游戏      ===\n");
        printf("=== 请输入您的选项...  ===\n");
        printf("==========================\n");
        scanf("%d", &choose);
        if (choose == 1 || choose == 2 || choose == 3) {
            break;
        }
    }
    return choose;
}

int MoveSnake(int trend, int* px, int* py, int data[ROW][COL], int* t)
{
    int ret = 1;//默认前进成功
    //printf("trend=%d\n", trend);
    switch (trend) {
    case 1:*py -= 1; break;//向上
    case 2:*px -= 1; break;//向左
    case 3:*py += 1; break;//向下
    case 4:*px += 1; break;//向右
    }//找到即将前进的坐标
    if (data[*py][*px] == 6) {
        data[*py][*px] = trend;
        CreatFood(data);
        *t *= 0.9;
    }//如果蛇头要前进的格子是食物,向前长一格,尾部不变;
    else if (data[*py][*px] == 0) {
        data[*py][*px] = trend;//向前长一格
        DeleteTail(*px, *py, data);//消去最后的尾巴
    }
    else {
        ret = 0;
        printf("前进失败\n");
    }//前进失败
    return ret;
}

void CreatFood(int data[ROW][COL])
{
    srand(time(NULL));
    while (1) {
        int x = rand() % (COL - 2) + 1;
        int y = rand() % (ROW - 2) + 1;
        if (data[y][x] == 0) {
            data[y][x] = 6;
            break;
        }
    }
}
 
int DeleteTail(int x, int y, int data[ROW][COL])
{
    //PrintTest(data);
    if (data[y][x] <= 4 && data[y][x] >= 1) {
        switch (data[y][x]) {
        case 1:
            if (DeleteTail(x, y + 1, data) == 0) {
                data[y][x] = 0;
            }
            break;
        case 2:
            if (DeleteTail(x + 1, y, data) == 0) {
                data[y][x] = 0;
            }
            break;
        case 3:
            if (DeleteTail(x, y - 1, data) == 0) {
                data[y][x] = 0;
            }
            break;
        case 4:
            if (DeleteTail(x - 1, y, data) == 0) {
                data[y][x] = 0;
            }
            break;
        }
        return 1;
    }
    else {
        return 0;
    }
}
int Input() {
    int trend = 0;
    if (kbhit()) {
        char trend_ = getch();
        while (kbhit()) {
            getch();
        }//清空缓冲区
        //printf("已接收到%c ", trend_);
        switch (trend_) {
        case 'w':trend = 1; break;
        case 'a':trend = 2; break;
        case 's':trend = 3; break;
        case 'd':trend = 4; break;
        default:printf("请输入w,a,s,d以控制前进方向!!\n");
            break;
        }
    }
    else {
        printf("请输入w,a,s,d以控制前进方向!!\n");
    }
    return trend;
}
 
void PrintShow(int data[ROW][COL])
{
    for (int i = 0; i < ROW; i++) {
        for (int j = 0; j < COL; j++) {
            if (data[i][j] == 0) {
                printf("  ");
            }
            if (data[i][j] == 5) {
                printf("■");
            }
            if (data[i][j] >= 1 && data[i][j] <= 4) {
                printf("□");
            }
            if (data[i][j] == 6) {
                printf("●");
            }
        }
        printf("\n");
    }
}
 
int CreatHead(int* px, int* py, int data[ROW][COL])
{
    srand(time(NULL));
    while (1) {
        *px = rand() % (COL - 8) + 4;
        *py = rand() % (ROW - 8) + 4;
        if (data[*py][*px] == 0) {
            break;
        }
    }//蛇头只能刷新在空格位置
    //x,y始终为蛇头的坐标
    int trend = rand() % 4 + 1;//1:上,2:左,3:下,4:右
    data[*py][*px] = trend;
    switch (trend) {
    case 1:data[*py + 1][*px] = 1;
        data[*py + 2][*px] = 1; break;
    case 2:data[*py][*px + 1] = 2;
        data[*py][*px + 2] = 2; break;
    case 3:data[*py - 1][*px] = 3;
        data[*py - 2][*px] = 3; break;
    case 4:data[*py][*px - 1] = 4;
        data[*py][*px - 2] = 4; break;
    }
    return trend;
}
void PrintTest(int data[ROW][COL])
{
    printf("\n");
    for (int i = 0; i < ROW; i++) {
        for (int j = 0; j < COL; j++) {
            printf("%d ", data[i][j]);
        }
        printf("\n");
    }
}
 
int GameOver(int score)
{
    system("cls");
    printf("==============================================\n");
    printf("游戏结束,您的小蛇最终长到了%d米长...\n", score);
    printf("输入1重新开始,输入其它退出游戏...\n");
    int ret = 0;
    scanf("%d", &ret);
    if (ret == 1) {
        return 1;
    }
    else {
        return 0;
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: C语言实现贪吃蛇小黑窗

本文链接: https://www.lsjlt.com/news/161548.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • c语言怎么计算字符串长度
    在C语言中,可以使用内置的strlen()函数来计算字符串的长度。该函数位于string.h头文件中。以下是一个示例代码: #inc...
    99+
    2024-05-14
    c语言
  • c语言怎么判断三个数的大小
    可以通过比较三个数之间的大小关系来判断它们的大小。以下是一个示例代码: #include <stdio.h> int ...
    99+
    2024-05-14
    c语言
  • c++排序函数sort怎么使用
    在C++中,使用sort函数对容器中的元素进行排序,可以按照默认的升序排列,也可以自定义排序规则。 下面是一个简单的例子,对一个ve...
    99+
    2024-05-14
    c++
  • c++中string的compare函数怎么使用
    在C++中,可以使用string的compare函数来比较两个string对象的大小。该函数的原型如下: int compare(c...
    99+
    2024-05-14
    c++
  • c++中string的compare函数有什么用
    c++中string的compare函数用于比较两个字符串的大小关系。该函数返回一个整数值,表示两个字符串的比较结果。 具体来说,如...
    99+
    2024-05-14
    c++
  • c++中print函数的功能有哪些
    在C++中,通常使用std::cout来进行输出操作,而不是使用print函数。std::cout是C++标准库中的一个输出流对象,...
    99+
    2024-05-14
    c++
  • c语言数据结构怎么使用
    在C语言中,数据结构可以通过定义结构体来实现。以下是一些常见的数据结构的使用方法示例: 链表: #include <std...
    99+
    2024-05-14
    c语言
  • c++中print函数的用法是什么
    在C++中没有内置的print函数,但可以使用cout来输出内容到控制台。cout是C++标准库中的一个输出流对象,可以使用<...
    99+
    2024-05-14
    c++
  • c++中concept的用法是什么
    在C++20中,Concept是一种新的语言特性,用于定义类型要求和约束。Concept可以被用来约束函数模板、类模板和普通函数的参...
    99+
    2024-05-14
    c++
  • c++中concept的作用是什么
    在C++中,concept的作用是定义一种通用的约束,用于限制模板参数的类型范围。通过使用concept,可以在编译时对模板参数进行...
    99+
    2024-05-14
    c++
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作