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

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

三、编程指导

  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. 更多游戏元素:

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

这些功能给大家作为练习去实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/339703.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode的AC指南 —— 栈与队列:20. 有效的括号

摘要&#xff1a; **Leetcode的AC指南 —— 栈与队列&#xff1a;20. 有效的括号 **。题目介绍&#xff1a;给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判断字符串是否有效。 有效字…

Linux系统中内核音频驱动实现

本文以I2S接口为例介绍Linux内核音频相关知识。 一、名词介绍 下面是音频调试中常见的名词缩略语。 1、AEC&#xff08;Acoustic Echo Cancellor&#xff09;&#xff1a;回声消除。 2、AGC&#xff08;Automatic Gain Control&#xff09;&#xff1a;自动增益补偿&#xf…

ZEM20台式扫描电子显微镜在三元材料锂电池中的应用

在当今环保能源需求日益增长的背景下&#xff0c;新型储能材料特别是锂离子电池在新能源汽车和移动互联网设备中的应用越来越广泛。其中&#xff0c;以镍钴锰三元素为基础的分层材质因具有体系能量密度高、原材料来源广、合成过程相对简单等优势&#xff0c;被公认为最有应用前…

字符串展开(Python)

展开字符串中用-压缩的连续小写字母或者数字&#xff0c;不是压缩形式的-不用理会&#xff0c;-没有压缩字符的去除-。 (笔记模板由python脚本于2024年01月21日 18:18:19创建&#xff0c;本篇笔记适合熟悉 p y t h o n python python字符串和列表的coder翻阅) 【学习的细节是欢…

Java线程池七大参数详解和配置(面试重点)

一、corePoolSize核心线程数 二、maximunPoolSize最大线程数 三、keepAliveTime空闲线程存活时间 四、unit空闲线程存活时间的单位 五、workQueue线程工作队列 1、ArrayBlockingQueue FIFO有界阻塞队列 2、LinkedBlockingQueue FIFO无限队列 3、PriorityBlockingQueue V…

2023年度环境电器行业数据分析(洗地机、扫地机器人、吸尘器等)

在家电行业整体消费不振的环境下&#xff0c;环境电器市场也受到影响&#xff0c;2023年度市场大盘销售呈下滑趋势。根据鲸参谋平台的数据显示&#xff0c;2023年京东平台环境电器市场的销量累计约7100万&#xff0c;同比下滑约12%&#xff1b;销售额约360亿&#xff0c;同比下…

二.用户和权限管理(一)

用户和管理权限 1.用户管理1.1登录MySQL服务器1.2创建用户1.3修改用户1.4删除用户1.5设置当前用户密码1.6 修改其它用户密码 2.权限管理2.1权限列表2.2授予权限的原则2.3授予权限2.4产看权限2.5收回权限 3.权限表3.1user表3.2db表3.3tables_priv表和columns_priv表3.4procs_pri…

【iOS】UICollectionView使用

使用UITableView作为表格来展示数据完全没有问题&#xff0c;但仍有许多局限性&#xff0c;对于一些更加复杂的布局样式&#xff0c;就有些力不从心了 比如&#xff0c;UITableView只允许表格每一行只能显示一个cell&#xff0c;而不能在一行中显示多个cell&#xff0c;对于这…

IN操作符

目录 IN NOT IN Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 IN IN 指的是根据一个指定的范围进行数据查询 1.查询出员工编号是 7369、7566、7788、9999 的员工信息 利用前面学的知识,得出: SQL> set linesize 250 SQL>…

​第14节-高质量简历写作求职通关-在线测试

在线测试主要包括性格测试、综合能力测试、技能测试三类 性格测试 性格测试主要用于考察个人与工岗位的匹配程度 考察内容包含性格、能力、动机、价值观等&#xff0c;考察形式一般为给出相应的工作场景&#xff0c;让你选择最喜欢或者最不喜欢的答案 技能考试 这类测试一般是针…

Windows云服务器如何配置多用户登录?(Windows 2012)华为云官方文档与视频地址

Windows云服务器如何配置多用户登录&#xff1f;&#xff08;Windows 2012&#xff09;_弹性云服务器 ECS_故障排除_多用户登录_华为云 打开任务栏左下角的“服务器管理器”&#xff0c;在左侧列表中选中“本地服务器” 然后将右侧“远程桌面”功能的选项修改为“启用”&#x…

LeetCode 13.罗马数字转整数(python版)

需求 罗马数字包含以下七种字符: I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如&#xff0c; 罗马数字 2 写做 II &#xff0c;即为两个并列的 1 。12 写做 XII &#xff0c;即为 X …

如何对遗留 C++ 代码进行现代化改造?

C 在过去的十年中进步很大&#xff0c;以至于有些人把它看作是一种完全不同的语言&#xff0c;而不是“老旧的遗留 C”。尽管现代 C 依然保留了与原来的准则和基本语法&#xff0c;但这些更新和进步对 C 语言和标准库意义重大。 不过&#xff0c;也不是每个人都在使用最新版本…

Unity 工厂方法模式(实例详解)

文章目录 在Unity中&#xff0c;工厂方法模式是一种创建对象的常用设计模式&#xff0c;它提供了一个接口用于创建对象&#xff0c;而具体的产品类是由子类决定的。这样可以将对象的创建过程与使用过程解耦&#xff0c;使得代码更加灵活和可扩展。 工厂模式的主要优点如下&…

快速排序(三)——hoare法

目录 ​一.前言 二.快速排序 hoare排法​ 三.结语 一.前言 本文给大家带来的是快速排序&#xff0c;快速排序是一种很强大的排序方法&#xff0c;相信大家在学习完后一定会有所收获。 码字不易&#xff0c;希望大家多多支持我呀&#xff01;&#xff08;三连&#xff0b;关…

PADS自动导出Gerber文件 —— 双面板

视频地址&#xff1a;PADS_2层PCB板(双面板) 快速出GERBER光绘文件实战视频教程_哔哩哔哩_bilibili 像pads做封装不用做阻焊层&#xff0c;因为在出GERBER文件的时候调用了焊盘&#xff0c;并在焊盘的基础上增加了几个mil来做阻焊层。 出Gerber文件之前一定要先铺铜并且检查无错…

双指针算法专题

前言 双指针算法入门&#xff0c;干就完了 下面的题目都是来自灵神的基础算法精讲&#xff0c;有思路不清晰的地方&#xff0c;可以去看讲解。 灵茶山艾府的个人空间-灵茶山艾府个人主页-哔哩哔哩视频 (bilibili.com) 相向双指针 1.两数之和 题目链接&#xff1a;167. 两数之…

清华大模型Chatglm2-6B的微调方法和微调模型使用方式(非常仔细,值得借鉴)

一、下载chatglm2-6b的项目代码和模型 1、下载chatglm2-6b的项目 方法一、chatglm2-6b的项目下载地址&#xff1a; https://github.com/THUDM/ChatGLM2-6B方法二、百度网盘提取chatglm2-6b的项目&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1BEwUhiIJlB4SJrGw7N…

力扣:474. 一和零(动态规划)(01背包)

题目&#xff1a; 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度&#xff0c;该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素&#xff0c;集合 x 是集合 y 的 子集 。 示例 1&#xff1a; 输入&#…

MacOS受欢迎的数据库开发工具 Navicat Premium 15 中文版

Navicat Premium 15 Mac是一款数据库管理工具&#xff0c;提供了一个全面的解决方案&#xff0c;用于连接、管理和维护各种数据库系统。以下是Navicat Premium 15 Mac的一些主要功能和特点&#xff1a; 软件下载&#xff1a;Navicat Premium 15 中文版下载 多平台支持&#xff…