1.分析

  众所周知,贪吃蛇游戏是一款经典的益智游戏,有PC和手机等多平台版本,既简单又耐玩。该游戏通过控制蛇头方向吃食物,从而使得蛇变得越来越长,蛇不能撞墙,也不能装到自己,否则游戏结束。玩过贪吃蛇的朋友都知道这个小游戏有一圈“墙”、还有食物以及蛇,还有吃了食物之后的分数。所以通过C语言实现贪吃蛇,可以分为以下几个模块来实现:

  a)编程实现“墙”

  b)实现随机食物的生成

  c)蛇的构建

  d)以上三部分都实现了之后,实现游戏运行的部分,包括蛇的移动、吃食物、判断是否撞墙或者撞到自己。

  e)游戏结束时的相关操作

2.具体思路

  要通过C语言实现贪吃蛇,首先就要用C语言将贪吃蛇的相关信息描述出来。C语言提供了结构体类型,我们可以用结构体描述蛇的结点(结点的横纵坐标)、运动状态、总分数、每个食物的分数等等。

  首先实现进入游戏的"welcome"界面,为了将“欢迎来到贪吃蛇游戏”打印到屏幕的中间,可以运用库函数先设置窗口的大小(system("mode con cols=100 lines=30");将窗口设置为长100,宽30),再通过库函数中的GetStdHandle函数、SetConsoleCursorPosition函数(把光标定位到我们需要的位置)将这句话打印到屏幕中央。

  其次可以通过相同的方法将光标固定到我们需要的位置,用特殊字符‘■’打印实现墙(注意,‘■’在c中占用两个字符,所以在设置循环条件时要格外注意)

  接着通过编程实现蛇的移动,本文中蛇是通过单链表实现的,因此在实现蛇的移动时,如果蛇接下来走的位置(上下左右)为食物,将这个位置的用指针表示,可以将食物头插到用_psnake指针维护的蛇身中,如果接下来的位置不是食物,同样头插到蛇身中,再将蛇的最后一个结点打印时输出为空格字符,然后free最后一个节点。

3.代码如下

snake.h:

 #pragma once

 #include<Windows.h>
#include<stdio.h>
#include<time.h>
#include<stdlib.h> #define WALL "■"
#define FOOD "●" #define INIT_X 20
#define INIT_Y 18
typedef struct SnakeNode
{
int x;
int y;
struct SnakeNode *next;
}SnakeNode, *pSnakeNode; //蛇的方向
enum Diretion
{
UP,
DOWN,
LEFT,
RIGHT
}; //状态
enum GameState
{
OK,
NORMAL_END,
KILL_BY_WALL,
KILL_BY_SELF
};
//游戏结构体
typedef struct Snake
{
pSnakeNode _psnake;//维护蛇身的指针
pSnakeNode _pFood;//维护食物的位置
int _TotalScore;//总分数
int _AddScore;//增加的分数
int _SleepTime;//休眠时间
enum Direction _Dir;
enum GameStatus _Status;
}Snake, *pSnake; void GameStart(pSnake ps);
void WelcomeToGame();//欢迎界面函数
void SetPos(int x, int y);
void CreateMap();//创建地图
void InitSnake(pSnake ps);
void CreateFood(pSnake ps);//创建食物
void GameRun(pSnake ps);//运行游戏
void pause();//暂停函数 void snakmove(pSnake ps);
int NextHasFood(pSnakeNode pn, pSnakeNode pf);//判断下个结点是否为食物
void EatFood(pSnake ps,pSnakeNode pn);//吃食物
void NoFood(pSnake ps, pSnakeNode pn);//没有食物
void KillBYWALL(pSnake ps);
void KillBySelf(pSnake ps);
void GameEnd(pSnake ps);

snake.c:

 #include"snake.h"
void SetPos(int x, int y)
{
COORD pos = { };
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
pos.X = x; pos.Y = y;
SetConsoleCursorPosition(handle, pos);//把光标定位到我们需要的位置了
}
void WelcomeToGame()//欢迎界面函数
{
//设置窗口大小
system("mode con cols=100 lines=30");
SetPos(, );//分装的函数用来定位光标
printf("欢迎来到贪吃蛇小游戏\n");
SetPos(, );
system("pause");//暂停
system("cls");//清空屏幕
SetPos(, );
printf("用↑,↓,←,→来控制蛇的移动,F1为加速,F2为减速\n");
SetPos(, );
printf("加速获得分数更多\n");
SetPos(, );
system("pause");
system("cls");
} void CreateMap()
{
int i = ;
//上
for (i = ; i <= ; i += )
{
SetPos(i, );
printf(WALL);
}
//下
for (i = ; i <= ; i += )
{
SetPos(i, );
printf(WALL);
}
//左
for (i = ; i <= ; i++)
{
SetPos(, i);
printf(WALL);
}
//右
for (i = ; i <= ; i++)
{
SetPos(, i);
printf(WALL);
}
}
pSnakeNode BuyNode()
{
pSnakeNode pRet = (pSnakeNode)malloc(sizeof(SnakeNode));
if (pRet == NULL)
{
perror("BuyNode::malloc()");
exit(EXIT_FAILURE);
}
pRet->x = ;
pRet->y = ;
pRet->next = NULL;
return pRet;
}
void InitSnake(pSnake ps)
{
pSnakeNode first = BuyNode();//创建蛇头
pSnakeNode cur = NULL;
first->x = INIT_X;
first->y = INIT_Y;
int i = ;
for (i = ; i <= ; i++)
{
cur = BuyNode();//创建蛇身
cur->x = first->x + ;
cur->y = first->y;
cur->next = first;
first = cur;
}
//打印蛇
while (cur)
{
SetPos(cur->x, cur->y);
printf(FOOD);
cur = cur->next;
}
ps->_psnake = first;
} void CreateFood(pSnake ps)
{
pSnakeNode pfood = BuyNode();
pSnakeNode cur = ps->_psnake;
pfood->y = rand() % + ;
do
{
pfood->x = rand() % + ;//0-54,+2产生2-56
} while (pfood->x % != );
while (cur)
{
if (cur->x == pfood->x&&cur->y == pfood->y)
{
CreateFood(ps);
}
cur = cur->next;
}
ps->_pFood = pfood;
SetPos(pfood->x, pfood->y);
printf(FOOD);
} void GameStart(pSnake ps)
{
//打印欢迎界面
WelcomeToGame();
//创建地图,画墙
CreateMap();
//初始化蛇
InitSnake(ps);
//初始化食物
CreateFood(ps);
//游戏运行
ps->_AddScore = ;//每次增加的分数
ps->_TotalScore = ;//总分
ps->_Dir = RIGHT;//方向
ps->_SleepTime = ;//0.2秒
ps->_Status = OK;//状态
} void pause()//暂停函数
{
while ()
{
Sleep();
if (GetAsyncKeyState(VK_SPACE))
{
return;
}
}
} int NextHasFood(pSnakeNode pn, pSnakeNode pf)
{
return (pn->x == pf->x) && (pn->y == pf->y);
} void EatFood(pSnake ps, pSnakeNode pn)//吃食物
{
pSnakeNode cur = NULL;
pn->next = ps->_psnake;//头插
ps->_psnake = pn;
cur = ps->_psnake;
ps->_TotalScore += ps->_AddScore;
while (cur)
{
SetPos(cur->x, cur->y);
printf(FOOD);
cur = cur->next;
}
CreateFood(ps);
} void NoFood(pSnake ps, pSnakeNode pn)//没有食物
{
pSnakeNode cur = NULL;
pn->next = ps->_psnake;//头插
ps->_psnake = pn;
cur = ps->_psnake;
while (cur->next->next)
{
SetPos(cur->x, cur->y);
printf(FOOD);
cur = cur->next;
}
SetPos(cur->x, cur->y);
printf(FOOD);
SetPos(cur->next->x, cur->next->y);
printf(" ");
free(cur->next);
cur->next = NULL;
} void snakmove(pSnake ps)//蛇的移动
{
pSnakeNode pNextNode = BuyNode();
SetPos(, );
printf("总分:%d", ps->_TotalScore);
SetPos(, );
printf("每个食物的得分:%d ", ps->_AddScore);
//上
switch (ps->_Dir)
{
case UP:
{
pNextNode->x = ps->_psnake->x;
pNextNode->y = ps->_psnake->y - ;
if (NextHasFood(pNextNode,ps->_pFood))
{
//下一个节点是食物
EatFood(ps,pNextNode);
}
else
{
NoFood(ps,pNextNode);
}
break;
}
case DOWN:
{
pNextNode->x = ps->_psnake->x;
pNextNode->y = ps->_psnake->y + ;
if (NextHasFood(pNextNode, ps->_pFood))
{
//下一个节点是食物
EatFood(ps, pNextNode);
}
else
{
NoFood(ps, pNextNode);
}
break;
}
case LEFT:
{
pNextNode->x = ps->_psnake->x-;
pNextNode->y = ps->_psnake->y;
if (NextHasFood(pNextNode, ps->_pFood))
{
//下一个节点是食物
EatFood(ps, pNextNode);
}
else
{
NoFood(ps, pNextNode);
}
break;
}
case RIGHT:
{
pNextNode->x = ps->_psnake->x+;
pNextNode->y = ps->_psnake->y ;
if (NextHasFood(pNextNode, ps->_pFood))
{
//下一个节点是食物
EatFood(ps, pNextNode);
}
else
{
NoFood(ps, pNextNode);
}
break;
}
default:
{
break;
}
}
} void KillBYWALL(pSnake ps)
{
if ((ps->_psnake->x == ) ||
(ps->_psnake->x == ) ||
(ps->_psnake->y == ) ||
(ps->_psnake->y == ))
{
ps->_Status = KILL_BY_WALL;
}
} void KillBySelf(pSnake ps)
{
pSnakeNode tnext = ps->_psnake->next;
while (tnext)
{
if ((tnext->x == ps->_psnake->x) && (tnext->y == ps->_psnake->y))
{
ps->_Status = KILL_BY_SELF;
return;
}
tnext = tnext->next;
} }
void PrintHelpInfo()
{
SetPos(, );
printf("用↑,↓,←,→来控制蛇的移动");
SetPos(, );
printf("F1为加速,F2为减速\n");
SetPos(, );
printf("加速获得分数更多\n");
SetPos(, );
printf("按空格暂停游戏\n"); } void GameEnd(pSnake ps)
{
pSnakeNode cur = ps->_psnake;
SetPos(, );
if (ps->_Status == NORMAL_END)
{
SetPos(, );
printf("游戏正常接结束\n");
SetPos(, );
}
else if (ps->_Status == KILL_BY_SELF)
{
SetPos(, );
printf("蛇撞到自己了\n");
SetPos(, );
}
else if (ps->_Status == KILL_BY_WALL)
{
SetPos(, );
printf("撞到墙了\n");
SetPos(, );
}
while (cur)
{
pSnakeNode del = cur;
cur = cur->next;
free(del);
del = NULL;
}
ps->_psnake = NULL;
free(ps->_pFood);
ps->_pFood = NULL;
} void GameRun(pSnake ps)
{
PrintHelpInfo();
do
{
//确定方向
if (GetAsyncKeyState(VK_UP)&&(ps->_Dir!=DOWN))
{
ps->_Dir = UP;
}
else if (GetAsyncKeyState(VK_DOWN) && ps->_Dir != UP)
{
ps->_Dir = DOWN;
}
else if (GetAsyncKeyState(VK_LEFT) && ps->_Dir != RIGHT)
{
ps->_Dir = LEFT;
}
else if (GetAsyncKeyState(VK_RIGHT) && ps->_Dir != LEFT)
{
ps->_Dir = RIGHT;
}
else if (GetAsyncKeyState(VK_SPACE))
{
//暂停游戏
pause();
}
else if (GetAsyncKeyState(VK_ESCAPE))
{
//结束游戏
ps->_Status = NORMAL_END;
break;
}
else if (GetAsyncKeyState(VK_F1))
{
//加速
if (ps->_SleepTime >= )
{
ps->_SleepTime -= ;
ps->_AddScore += ;
}
}
else if (GetAsyncKeyState(VK_F2))
{
//减速
if (ps->_SleepTime <= )
{
ps->_SleepTime += ;
ps->_AddScore -= ;
}
if (ps->_SleepTime > )
{
ps->_AddScore = ;//不能一直减
}
}
Sleep(ps->_SleepTime);//睡眠
//蛇的移动
snakmove(ps);
KillBYWALL(ps);
KillBySelf(ps);
} while (ps->_Status == OK);
}

test.c:

 #include"snake.h"

 void test()
{
srand((unsigned)time(NULL));
Snake snake = { };//创建贪吃蛇
GameStart(&snake);
GameRun(&snake);
GameEnd(&snake);
} int main()
{
test();
system("pause");
return ;
}

贪吃蛇小游戏-----C语言实现的更多相关文章

  1. C++ 简单的控制台贪吃蛇小游戏

    由于比较懒,所以不怎么写,觉得这样不应该.我应该对自己学的做出整理,不管是高端低端,写出来是自己的. // 贪吃蛇.cpp : 定义控制台应用程序的入口点. // #include "std ...

  2. JS高级---案例:贪吃蛇小游戏

    案例:贪吃蛇小游戏 可以玩的小游戏,略复杂,过了2遍,先pass吧 先创建构造函数,再给原型添加方法.分别创建食物,小蛇和游戏对象. 食物,小蛇的横纵坐标,设置最大最小值,运动起来的函数,按上下左右键 ...

  3. Java GUI学习,贪吃蛇小游戏

    JAVA GUI练习 贪吃蛇小游戏 前几天虽然生病了,但还是跟着狂神学习了GUI的方面,跟着练习了贪吃蛇的小项目,这里有狂神写的源码点我下载,还有我跟着敲的点我下载,嘿嘿,也就注释了下重要的地方,这方 ...

  4. 用GUI实现java版贪吃蛇小游戏

    项目结构 新建一个JFrame窗口,作为程序入口 public class GameStart{ public static void main(String[] args) { JFrame jFr ...

  5. Java 用java GUI写一个贪吃蛇小游戏

    目录 主要用到 swing 包下的一些类 上代码 游戏启动类 游戏数据类 游戏面板类 代码地址 主要用到 swing 包下的一些类 JFrame 窗口类 JPanel 面板类 KeyListener ...

  6. html5面向对象做一个贪吃蛇小游戏

    canvas加面向对象方式的贪吃蛇 2016-08-25 这个小游戏可以增加对面向对象的理解,可以加强js逻辑能力,总之认真自己敲一两遍收获还是不少啊!!适合刚学canvas的同学练习!! 废话不多说 ...

  7. 用python+pygame写贪吃蛇小游戏

    因为python语法简单好上手,前两天在想能不能用python写个小游戏出来,就上网搜了一下发现了pygame这个写2D游戏的库.了解了两天再参考了一些资料就开始写贪吃蛇这个小游戏. 毕竟最开始的练手 ...

  8. Java贪吃蛇小游戏

    贪吃蛇 思路 首先构思游戏布局,计算合理的坐标系. 绘制静态数据(广告.初始小蛇.提示信息.棋盘) 添加键盘监听事件,改变游戏状态以及小蛇运动方向 添加定时器,让小蛇在一段时间内移动一定的距离 随机产 ...

  9. JavaScript-简单的贪吃蛇小游戏

    实现逻辑: //获取Html中的格子(行,列) //建立数组存储所有格子(x,y) //建立数组用于存储蛇身(x,y) //生成随机坐标(x,y)的函数 //随机创建蛇身并存储到蛇身数组 //创建食物 ...

随机推荐

  1. SQL0973N在 "<堆名>" 堆中没有足够的存储器可用来处理语句

    SQL0973N在 "<堆名>" 堆中没有足够的存储器可用来处理语句. 解释: 已使用此堆的所有可用内存.不能处理该语句. 用户响应: 接收到此消息(SQLCODE)后 ...

  2. Devexpress VCL Build v2013 vol 14.1.5 发布

    What's New in 14.1.5 (VCL Product Line)   New Major Features in 14.1 What's New in VCL Products 14.1 ...

  3. 2018.09.16 codeforces1041C. Coffee Break(双端队列)

    传送门 真心sb题啊. 考场上最开始看成了一道写过的原题... 仔细想了一会发现看错了. 其实就是一个sb队列. 每次插入到队首去就行了. 代码: #include<bits/stdc++.h& ...

  4. 2018.08.18 NOIP模拟 travel(贪心)

    Travel 题目背景 SOURCE:NOIP2015-SHY4 题目描述 小 A 要进行一次旅行.这回他要在序号为 1 到 n 的 n 个城市之间旅行.这 n 个城市之间共有 m 条连接两个城市的单 ...

  5. @GeneratedValue和@GenericGenerator(转)

    一.JPA通用策略生成器 通过annotation来映射hibernate实体的,基于annotation的hibernate主键标识为@Id, 其生成规则由@GeneratedValue设定的.这里 ...

  6. StackView实现叠加在一起的图片循环移动像循环队列一样

    MainActivity.java public class MainActivity extends Activity {   StackView stackView; int[] imageIds ...

  7. 新浪微博mid和url的互算

    我们在使用新浪微博API时,有时需要得到一个微博的url,但是如statuses/public_timeline等接口中取得的微博status的字段中并没有包含.不过,status中包含了一个mid字 ...

  8. 整数重复的第n位计算公式

    513不停的重复形成513513513....,求第n位是几的计算公式.

  9. codeforces 678C. Joty and Chocolate(容斥) 2016-10-15 21:49 122人阅读 评论(0) 收藏

    C. Joty and Chocolate time limit per test 1 second memory limit per test 256 megabytes input standar ...

  10. mongodb 问题

    启动mongodb时,提示Unclean shutdown detected mongodb,解决方法很简单 mongod --repair --dbpath D:\MongoDB\blog   不用 ...