C语言实战系列一:经典贪食蛇

这篇具有很好参考价值的文章主要介绍了C语言实战系列一:经典贪食蛇。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C语言学习必须实战,并且学完语法后就必须立即用实战来巩固。一般需要10来个比较复杂的程序才能掌握C语言。今天就教大家第一个小程序,贪食蛇。

首先上代码

一、代码

#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include <unistd.h>
#include <time.h>

#define WIDTH 20
#define HEIGHT 10

int score = 0;
int gameover;
int x, y, fruitX, fruitY, flag;

int tailX[100], tailY[100];
int nTail;

void setup() {
    gameover = 0;

    // 初始化蛇的位置
    x = WIDTH / 2;
    y = HEIGHT / 2;

    // 初始化食物的位置
    fruitX = rand() % WIDTH;
    fruitY = rand() % HEIGHT;
}

void draw() {
    clear(); // 清屏

    for (int i = 0; i < WIDTH + 2; i++)
        printw("#");

    printw("\n");

    for (int i = 0; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {
            if (j == 0)
                printw("#"); // 左墙
            if (i == y && j == x)
                printw("O"); // 蛇头
            else if (i == fruitY && j == fruitX)
                printw("F"); // 食物
            else {
                int isTail = 0;
                for (int k = 0; k < nTail; k++) {
                    if (tailX[k] == j && tailY[k] == i) {
                        printw("o"); // 蛇身
                        isTail = 1;
                    }
                }
                if (!isTail)
                    printw(" ");
            }

            if (j == WIDTH - 1)
                printw("#"); // 右墙
        }
        printw("\n");
    }

    for (int i = 0; i < WIDTH + 2; i++)
        printw("#");

    printw("\n");
    printw("Score:%d", score);
    refresh(); // 刷新屏幕
}

void input() {
    int ch = getch(); // 获取键盘输入
    switch (ch) {
        case 'a':
            flag = 1;
            break;
        case 'd':
            flag = 2;
            break;
        case 'w':
            flag = 3;
            break;
        case 's':
            flag = 4;
            break;
        case 'x':
            gameover = 1;
            break;
    }
}

void algorithm() {
    usleep(100000); // 休眠,控制蛇的速度
    int prevX = tailX[0];
    int prevY = tailY[0];
    int prev2X, prev2Y;
    tailX[0] = x;
    tailY[0] = y;

    for (int i = 1; i < nTail; i++) {
        prev2X = tailX[i];
        prev2Y = tailY[i];
        tailX[i] = prevX;
        tailY[i] = prevY;
        prevX = prev2X;
        prevY = prev2Y;
    }

    switch (flag) {
        case 1:
            x--;
            break;
        case 2:
            x++;
            break;
        case 3:
            y--;
            break;
        case 4:
            y++;
            break;
        default:
            break;
    }

    // 判断是否碰到墙
    if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT)
        gameover = 1;

    // 判断是否吃到食物
    if (x == fruitX && y == fruitY) {
        score += 10;
        fruitX = rand() % WIDTH;
        fruitY = rand() % HEIGHT;
        nTail++;
    }
}

int main() {
    srand(time(NULL)); // 设置随机数种子
    initscr(); // 初始化 curses
    keypad(stdscr, TRUE); // 启用键盘输入
    nodelay(stdscr, TRUE); // 非阻塞输入
    noecho(); // 关闭回显

    setup();

    while (!gameover) {
        draw();
        input();
        algorithm();
    }

    endwin(); // 关闭 curses
    return 0;
}

二、编译

代码的运行平台是ubuntu,代码用到了curses库,需要提前安装:

 sudo apt-get install libncurses5-dev

然后用下面命令编译

gcc snake_game.c -o snake_game -lncurses

执行程序:

./snake_game

注意!如果速度过快,就会结束,直接跳出程序到控制台,如何修改速度下面会讲到。

C语言实战系列一:经典贪食蛇,深入浅出C语言,c语言,算法,开发语言

三、编程指导

  1. 初始化 (setup 函数):

    • gameover: 游戏结束标志。
    • xy: 蛇头的初始坐标。
    • fruitXfruitY: 食物的初始坐标。
    • flag: 用于存储用户输入的方向。
    • score: 记录游戏得分。
    • nTail: 蛇身的长度。
    • tailXtailY: 用于存储蛇身各部分的坐标。
  2. 游戏主循环:

    while (!gameover) {
        draw();
        input();
        algorithm();
    }
    

    游戏在一个无限循环中进行,直到 gameover 变为真。在每次循环中,先绘制游戏画面,然后处理用户输入,最后执行游戏逻辑。

  3. 输入处理 (input 函数):

    • 使用 getch 函数获取键盘输入。
    • 根据用户输入的键值设置 flag 的值,表示蛇移动的方向。
    • 'a': 左,'d': 右,'w': 上,'s': 下,'x': 退出游戏。
  4. 游戏逻辑 (algorithm 函数):

    • 使用 usleep 函数添加一点延迟,以控制蛇的速度。(如果速度过快,游戏会很快结束,需要添加延时)
    • 更新蛇身的位置。
    • 根据用户输入的方向移动蛇头。
    • 判断是否碰到墙,如果是则游戏结束。
    • 判断是否吃到食物,如果是则增加得分,重新生成食物,增加蛇身的长度。
  5. 绘制 (draw 函数):

    • 使用 clear 函数清空屏幕。
    • 使用 printw 函数输出字符。
    • 使用 refresh 函数刷新屏幕。
    • 输出游戏画面,包括墙、蛇头、食物和蛇身。
    • 输出得分信息。
  6. 初始化和关闭 curses (initscrendwin 函数):

    • initscr: 初始化 curses 库。
    • keypad: 启用键盘输入。
    • nodelay: 设置非阻塞输入。
    • noecho: 关闭回显。
    • endwin: 关闭 curses 库。
  7. 编译和运行:

    • 使用 gcc 编译器编译程序,并链接 ncurses 库。
    • 运行生成的可执行文件。

四、继续完善

这段贪食蛇游戏代码已经基本完成了一个简单的实现,但仍然有一些方面可以改进和完善,具体包括:

  1. 边界检查:

    当蛇头移动到边界时,游戏会结束。可以考虑在边界处实现蛇穿越的效果,即从一侧穿越到另一侧。
  2. 游戏难度递增:

    目前游戏的难度保持不变,可以考虑逐渐增加蛇的移动速度或者加快食物的生成速度,使得游戏更具挑战性。
  3. 碰撞检测:

    目前只有边界碰撞检测和食物碰撞检测,可以考虑添加对蛇头与蛇身碰撞的检测,以防止游戏结束。
  4. 游戏结束提示:

    当游戏结束时,可以输出更友好的提示信息,告诉玩家是因为碰到墙还是碰到自己身体而导致游戏结束。
  5. 代码结构和模块化:

    将代码进一步模块化,使得各部分功能更清晰、易读、易于维护。可以考虑将一些功能性代码抽象成函数。
  6. 用户界面交互:

    添加开始界面和游戏结束后的界面,以提供更良好的用户体验。
  7. 更多游戏元素:

    考虑添加更多的游戏元素,如障碍物、特殊道具等,以增加游戏的趣味性和多样性。

这些功能给大家作为练习去实现。文章来源地址https://www.toymoban.com/news/detail-814974.html

到了这里,关于C语言实战系列一:经典贪食蛇的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【深入浅出系列】之代码可读性

    这是“深入浅出系列”文章的第一篇,主要记录和分享程序设计的一些思想和方法论,如果读者觉得所有受用,还请“一键三连”,这是对我最大的鼓励。 一句话:见名知其义。有人说好的代码必然有清晰完整的注释,我不否认;也有人说代码即注释,是代码简洁之道的最高

    2024年02月11日
    浏览(42)
  • CSDN首发 | 《深入浅出OCR系列》目录

    👨‍💻 作者简介: CSDN、阿里云人工智能领域博客专家,新星计划计算机视觉导师,百度飞桨PPDE,专注大数据与AI知识分享。✨ 公众号:GoAI的学习小屋 ,免费分享书籍、简历、导图等,更有交流群分享宝藏资料,关注公众号回复“加群”或➡️ 点击链接 加群。 🎉 专栏推

    2023年04月08日
    浏览(54)
  • 【SpringBoot深入浅出系列】SpringBoot之集成Elasticsearch

    网上 SpringBoot 集成 Elasticsearch 的文章很多,但随着 SpringBoot 和 Elasticsearch 版本的不断升级,绝大多数文章使用的集成方式和调用的方法已经过时,几乎找不到能真正适用最新 SpringBoot 版本和最新 Elasticsearch 版本的文章。 本文正是基于最新 SpringBoot 版本和最新 Elasticsearch 版本实

    2024年02月06日
    浏览(37)
  • 深入浅出分支语句—【C语言】

    目录 前言:为什么要学习分支和循环语句呢? 1. 语句的分类 2. 分支语句(选择语句) 2.1 if-else语句 注意点:if-else语句后面不加{},默认只能跟一条语句 2.2  switch语句  注意点: 因为C语言是一门结构化的程序设计语言,具有三种结构:顺序结构、选择结构、循环结构,这三

    2024年02月02日
    浏览(86)
  • 深入浅出C语言—【函数】下

    函数和函数之间可以根据实际的需求进行组合的,也就是互相调用的。 注意: 函数可以嵌套调用,但是不能嵌套定义。 把一个函数的返回值作为另外一个函数的参数。 上面的strlen函数是求数组长度的库函数, 特别注意的是,当数组为字符数组时,数组的末尾会自动放一个

    2024年02月17日
    浏览(76)
  • 深入浅出C语言—【函数】上

       目录 1.函数的概念 2.C语言函数的分类 2.1 库函数 2.1.1 strcpy库函数举例学习方式 2.1.2 库函数扩展知识 2.2 自定义函数 2.2.1求两个整数中的较大值 3. 函数的参数 3.1 实际参数(实参) 3.2 形式参数(形参) 4. 函数的调用 4.1 传值调用 4.2 传址调用 老铁们,网址自取,记得一键

    2024年02月07日
    浏览(70)
  • 深入浅出循环语句—【C语言】

      分支语句博客: http://t.csdn.cn/U2kZF 目录 ​编辑 前言:我们先来了解一下break 、continue在循环中的作用 1. while循环  while循环中的break  while循环中的continue  2. for循环 for循环省略出错举例:  for循环中的break  for循环中的continue 3. do   while循环 利用do while循环打印1~10   d

    2024年02月04日
    浏览(93)
  • 深入浅出git-log之代码统计实战

    – git-log 即查看 git 提交日志,本文会全面解析 git-log 使用并通过一个真实的 SpringBoot 项目进行实战。如果你是个技术管理者,你一定在乎手下做了什么,提了多少代码,是否有“佛祖保佑”,git-log 都可以帮你搞定。它还可帮你 code review,帮你 blame someone。你想 blame 吗?你想

    2024年04月23日
    浏览(24)
  • 深入浅出:大语言模型的视觉解析

    一系列工具与文章的汇编,直观易懂地解读复杂的 AI 概念 图片由作者利用 unDraw.co 的免费插图制作 在当今世界,大语言模型(LLM)成为了热门话题。几乎每天都有新的语言模型问世,让人们在 AI 领域怀有一种“不容错过”的紧迫感。尽管如此,许多人仍对大语言模型的基础

    2024年01月19日
    浏览(43)
  • FPGA信号处理系列文章——深入浅出理解多相滤波器

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 多相滤波是,按照相位均匀划分把数字滤波器的系统函数H(z)分解成若干个具有不同相位的组,形成多个分支,在每个分支上实现滤波。 采用多相滤波结构,可利用多个阶数较低的滤波来实现原本阶数较

    2024年02月05日
    浏览(62)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包