c语言贪吃蛇(简易版本含完整代码)

c语言贪吃蛇(简易版本含完整代码)这个贪吃蛇是在我学完C语言的基本部分在跟着哈工大的c语言程序设计Mooc课程完了之后做的因为学完C语言很迷茫不晓得应该学什么学校里面的题库感觉刷起来又没有实际我能看到的东西我认为在阶段性的学习过程中应该找到自己能够看得到的成果才能刺激自己继续往前进继续学习不然很枯燥的学习谁都坚持不下去这也是在看了视频教程后自己一步步敲出来的其实还是建议大家在看懂了代码后自己实现因为不要怕自己忘不忘这又不是理论知识敲出来的代码就是自己的一步步的提升加油qwq这里是head.h头文件因为

大家好,又见面了,我是你们的朋友全栈君。


前引


这个贪吃蛇是在我学完C语言的基本部分 在跟着哈工大的c语言程序设计Mooc课程完了之后做的 因为学完C语言很迷茫 不晓得应该学什么 学校里面的题库感觉刷起来又没有实际我能看到的东西 我认为在阶段性的学习过程中应该找到自己能够看得到的成果 才能刺激自己继续往前进 继续学习 不然很枯燥的学习谁都坚持不下去

这也是在看了视频教程后 自己一步步敲出来的 其实还是建议大家在看懂 了代码后自己实现 因为不要怕自己忘不忘 这又不是理论知识 敲出来的代码就是自己的 一步步的提升 加油qwq

另外 此代码保证可以运行
在这篇博客发布后一年 我需要用这个交大作业时用的还是这个博客的代码
编译无错 依然能够流畅无阻的运行
主要问题部分集中于头文件部分
详情多看一下头文件注释部分


头文件注释部分


这里是head.h头文件 因为可以使主文件看起来更整洁更清晰
因为我用的是code:blocks 头文件的创建是在File->New->Class中 然后点击创建就ok了 记得如果想看一下这个代码的实现效果 自己也创建头文件名字是head哦 不然头文件名字匹配不了hhhh 或者大家自己把代码一起copy到主程序里面也可以qwq 还有记得要把cpp给取消掉qwq

头文件创建截图
在这里插入图片描述


头文件部分


#ifndef HEAD_H
#define HEAD_H
#define SnakeMaxLength 20
typedef int bool;
#define true 1
#define false -1

//背景布置
//这里解释一下 一个特殊字符实线格子在横列是占两格
//所以空白格子在圈中要以两倍的间隔空格隔开

char MyBackGround[22][80]={ 
     "■■■■■■■■■■■■■■■■■■■■\n",
							 "■ ■\n",
							 "■ ■\n",
							 "■ ■\n",
							 "■ ■\n",
							 "■ ■\n",
							 "■ ■\t\t\t欢乐时光就要开始了\n",
							 "■ ■\n",
							 "■ ■\t\t\tW A S D控制操作\n",
							 "■ ■\n",
							 "■ ■\t\t\t碰到墙壁死亡\n",
							 "■ ■\n",
							 "■ ■\t\t\t祝好运\n",
							 "■ ■\n",
							 "■ ■\n",
							 "■ ■\n",
							 "■ ■\n",
							 "■ ■\n",
							 "■ ■\n",
							 "■■■■■■■■■■■■■■■■■■■■\n"};
//这里使用了枚举 为什么这里go_ease = -2 因为这里特殊字符在横向占两格 
//数列只占一个格子

enum Direction{ 
   go_east = -2,go_west = 2,go_north = -1,go_south = 1};
int ArrSnake[SnakeMaxLength][3]={ 
   { 
   0,0,0}};

//判断蛇默认开始方向
int SnakeDirection = go_east;

//判断食物是否还存在
bool OptionFoodAlive = false;
int x,y;
#endif

这里是主函数main.h的实现
里面有音乐播放功能 但只能用WAV文件格式
wav格式的音乐文件甩到你的exe文件旁边
因为用的是相对路径 然后歌名改成1.wav就ok了如果不想改音乐文件的话就把程序中的MyMusic那里1.wav改成你的音乐名字即可


主函数部分


#include <stdio.h>
#include <stdlib.h>
#include <string.h>//使用strncpy函数
#include <conio.h>//_getch()要用
#include <windows.h>//这个是有些函数要用
#include "head.h"//包含头文件
#include <time.h>//随机值懂得奥
#define true 1
#define false -1
typedef int bool;
int scores = 0;

//首页
void FirstPage();
//播放音乐
void MyMusic();
//按回车键进入游戏
void EnterGame();
//停止音乐
void StopMusic();
//清空页面
void CleanScreen();
//背景基础函数
void BackGround();
//蛇爹的初始位置
void SetSnakePos();
//画蛇的位置
bool GiveSnake();
//给蛇的位置赋值
void MoveSnake();
//删除蛇
void DeleteSnake();
//控制蛇
void ControlSnake();
//判断蛇是否死亡
bool IsSnakeAlive();
//制造食物
void ProduceFood();
//蛇变长
void LengthenSnake();


//首页
void FirstPage()
{ 
   
    printf("\n\n\n\n\n\n");
    printf("\t\t\t\t\t 《欢迎来到贪吃蛇的世界》\n\n\n");
    printf("\t\t\t\t\t 《W A S D 控制蛇前进后退》\n\n\n");
    printf("\t\t\t\t\t 《按下ENTER键开始新游戏》\n\n\n\n");
    printf("\t\t\t\t\t 《再次感谢游玩此游戏》\n");
}

//播放音乐
//这里可以删除功能 不想添加因为删掉就ok了
void MyMusic()
{ 
   
    PlaySound("1.wav",NULL,SND_FILENAME | SND_ASYNC );
}

//按回车键进入游戏
void EnterGame()
{ 
   
    while('\r'!=_getch());
}

//停止音乐
void StopMusic()
{ 
   
    PlaySound(NULL, 0, 0);
}

//清空页面
void CleanScreen()
{ 
   
    system("cls");
}

//背景基础函数
//布置背景嗷 头文件里面的背景
void BackGround()
{ 
   
    int i;
    for(i=0; i<20; i++)
    { 
   
        printf("%s",MyBackGround[i]);
    }
}

//蛇爹的初始位置
void SetSnakePos()
{ 
   
	//其实这里的x , y我在后面加备注的时候我觉得会错意了
	//这里的x 我想表示的是他的行数
	//这里的y 我想表示的是他的列数 就是第几列
	//如果大家想改程序可以改成
	//x是rows y是lines即可 我懒我就懒得改了 大家懂的就ok了

    int x=-1;
    int y=-1;
    srand(time(NULL));
    y = rand()%16+1;//给蛇的位置赋值 默认蛇初始有三个格子
    x = rand()%16+1;
        ArrSnake[0][0] = x;
        ArrSnake[0][1] = y*2;//为什么乘以二呢 因为特殊格子在横向是占两格
        ArrSnake[0][2] = go_east;

        ArrSnake[1][0] = x;
        ArrSnake[1][1] = y*2 + 2;//加二是因为一个字符两个格子
        ArrSnake[1][2] = go_east;

        ArrSnake[2][0] = x;
        ArrSnake[2][1] = y*2 + 4;
        ArrSnake[2][2] = go_east;
}

//画蛇的位置
bool GiveSnake()
{ 
   
    int i;
    for(i=0; ArrSnake[i][0] != 0;i++)
    { 
   
    	//为什么使用strncpy呢 因为更安全hhhh 可以限制格子数
        strncpy(&MyBackGround[ArrSnake[i][0]][ArrSnake[i][1]],"■",2);
        if(i && ArrSnake[0][0] == ArrSnake[i][0] &&  ArrSnake[0][1] == ArrSnake[i][1])   return false;
    }
    return true;
}

//删除蛇
//为什么要删除蛇呢 因为这个蛇的移动就是一个 赋值 删除 赋值 删除的过程
//删除掉原来的蛇 然后再把现在的蛇表示出来 不然的话
//原来的蛇和现在的蛇就一直重复 导致原来的蛇一直在屏幕上
void DeleteSnake()
{ 
   
    int i;
    for(i=0; ArrSnake[i][0] != 0;i++)
    { 
   
        strncpy(&MyBackGround[ArrSnake[i][0]][ArrSnake[i][1]]," ",2);
    }
}

//蛇的坐标赋值
void MoveSnake()
{ 
   
    int i=SnakeMaxLength-1;
    ArrSnake[0][2]=SnakeDirection;
    for(;i>=1;i--)
    { 
   
        //过滤坐标为0
        if(0 == ArrSnake[i][0])
        { 
   
            continue;
        }
        //将上一个物块的值赋值给下一个物块(除蛇头)
        ArrSnake[i][0]=ArrSnake[i-1][0];
        ArrSnake[i][1]=ArrSnake[i-1][1];
        ArrSnake[i][2]=ArrSnake[i-1][2];
    }
    //处理蛇头
        if( go_east == ArrSnake[0][2] || go_west == ArrSnake[0][2])
        { 
   
            ArrSnake[0][1]+=ArrSnake[0][2];
        }
        else
        { 
   
            ArrSnake[0][0]+=ArrSnake[0][2];
        }
}

//控制蛇的方向
//这里是控制蛇的方向
//具体为什么用这个函数 大家可以自急查询一下
//这个Asyn的意思就是 异步的意思 表示你在操作的时候同时读入你键盘的值
//如果是同步的话 大家可以想象一下 需要你敲下回车 蛇才移动 不是嘛hhhh
void ControlSnake()
{ 
   
    if(GetAsyncKeyState('W'))
    { 
   
        if(SnakeDirection != go_south)
        SnakeDirection=go_north;
    }
    else if(GetAsyncKeyState('S'))
    { 
   
        if(SnakeDirection != go_north)
        SnakeDirection=go_south;
    }
    else if(GetAsyncKeyState('A'))
    { 
   
        if(SnakeDirection != go_west)
        SnakeDirection=go_east;
    }
    else if(GetAsyncKeyState('D'))
    { 
   
        if(SnakeDirection != go_east)
        SnakeDirection=go_west;
    }
}

//判断蛇是否死亡
bool IsSnakeAlive()
{ 
   
    if(0 == strncmp(&MyBackGround[ArrSnake[0][0]][ArrSnake[0][1]],"■",2))
    { 
   
        return false;
    }
    else
    { 
   
        return true;
    }
}

//制造食物
void ProduceFood()
{ 
   
    //蛇的坐标
    int i;
    srand(time(NULL));
    //蛇的坐标给予
    if(true == OptionFoodAlive)
    { 
   
        return;
    }
    while(1)
    { 
   
        bool tempbool = true;
        x=rand()%18 + 1;
        y=rand()%18 + 1;
        for(i=0 ; i<ArrSnake[i][0] ; i++)
        { 
   
            if(x == ArrSnake[i][0] && 2*y == ArrSnake[i][1])
            { 
   
                tempbool = false;
                break;
            }
        }
        if(true == tempbool)
        { 
   
            break;
        }
    }
        strncpy(&MyBackGround[x][y*2],"★",2);
        OptionFoodAlive = true;
}

//这里就是加长蛇的长度了
void LengthenSnake()
{ 
   
    int i=0;
    if(x == ArrSnake[0][0] && 2*y == ArrSnake[0][1])
    { 
   
        OptionFoodAlive = false;
        scores += 10;
        for(; ;i++)
        { 
   
            if(ArrSnake[i][0] == 0)
            { 
   
                if(ArrSnake[i][2] == go_north || ArrSnake[i][2] == go_south)
                { 
   
                    ArrSnake[i][0]=ArrSnake[i-1][0]-ArrSnake[i-1][2];
                    ArrSnake[i][1]=ArrSnake[i-1][1];
                    ArrSnake[i][2]=ArrSnake[i-1][2];
                }
                else
                { 
   
                    ArrSnake[i][0]=ArrSnake[i-1][0];
                    ArrSnake[i][1]=ArrSnake[i][1]-ArrSnake[i][2];
                    ArrSnake[i][2]=ArrSnake[i][2];
                }
                break;
            }
        }
    }
}


//这里就是主函数具体怎么实现的了
//这个贪吃蛇还包含了重启功能
//这个注释还是挺详细的了 希望能对大家有所帮助 大家一起加油
int main()
{ 
   
    FirstPage();//首页显示
    MyMusic();//音乐播放
    EnterGame();//按回车键进入游戏
    StopMusic();//停止音乐
    CleanScreen();//清空屏幕(为正式游戏做铺垫)
    SetSnakePos();//设置蛇的初始坐标
    while(1)
    { 
   
        int flag = 0;
        ProduceFood();//制造食物
        DeleteSnake();//删除蛇
        ControlSnake();//控制蛇的移动
        MoveSnake();//蛇移动图案
        if(false == IsSnakeAlive()) flag = 1;
        LengthenSnake();
        if(false == GiveSnake())    flag = 1;//给予蛇在背景中图案
        BackGround();//布置背景
        Sleep(300);
        system("cls");
        if(flag)
        { 
   
            printf("Ur scores = %d\n",scores);
            printf("Thanks for playing this game!\n");
            break;
        }
        system("pause");
    }
    return 0;
}


实现效果


一年后 重新复制本篇博客到
新的文件 codeblocks 本地运行 运行编译正确 运行流畅

在这里插入图片描述
在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/154066.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • java线程优先级_java线程优先级有几级

    java线程优先级_java线程优先级有几级1.yield方法yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。当放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。2.线程的优先级在操作系统中,线程可以划分优先级,优先级较高的线程得到的CPU资源越多,也就是CPU优先执行优先级较高的线程对象中的任务。在Java中,线程的优先级分为1~10这10个等级,如果小于1或大于10,则JDK抛出异常thrownewIllegalArgumentException()。JDK中使用3个

    2022年10月15日
  • powermodule_getsocketopt

    powermodule_getsocketopt严格模式ES6的模块自动采用严格模式,不管你有没有在模块头部加上"usestrict";。严格模式的限制如下变量必须声明后再使用函数的参数不能有同名属性,否则报错不能

  • pki密码技术_PKI体系管理

    pki密码技术_PKI体系管理HTTPS的诞生可先参考网络协议、HTTPS协议等文章明文传输对称加密“加密”和“解密”使用【相同的】密钥,如果密钥可以安全的传输,那么消息也应该可以安全的传输。非对称加密上述非对称加密与对称加密效果基本一样,如果公钥可以安全的传输,那么消息也应该可以安全的传输,接下来看看被劫持的情况。窃听者可以伪造服务器的公钥与客户端通讯,客户端以为是跟服务器通讯,其实是与窃听者在通讯。无论是对称加密还是非对称加密,都遗留了一个问题没有解决,那就是如何证明我们访问的网站就是我们

  • tomcat配置虚拟主机

    tomcat配置虚拟主机

    2021年11月16日
  • Protostuff序列化分析

    Protostuff序列化分析Protostuff序列化分析最近项目中需要将业务对象直接序列化,然后存数据库;考虑到序列化、反序列化的时间以及生产文件的大小觉得Protobuf是一个很好的选择,但是Protobuf有的问题就是需要有一个.proto的描述文件,而且由Protobuf生成的对象用来作为业务对象并不是特别友好,往往业务对象和Protobuf对象存在一个互相转换的过程;考虑到我们仅仅是将业务对象直接序列化到数据库,发现Protobuf在这种情况下并不是特别的好;这时候发现了Protostuff,protostuff不需

  • kernel: TCP: time wait bucket table overflow 问题分析和解决[通俗易懂]

    kernel: TCP: time wait bucket table overflow 问题分析和解决[通俗易懂]目录一问题描述二问题分析三问题解决四问题扩展4.1timewait连接过高有什么影响?4.2如何减少timewait连接数?一问题描述工作中的一台数据库打印如下日志:二问题分析查看当时TCP连接数状态:netstat-n|awk’/^tcp/{++S[$NF…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号