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. EnrichPipeline文档

    https://sourceforge.net/projects/enrichmentpipeline/

  2. s28 LNMP架构服务搭建

    nginx-location使用 location语法 location使用的语法例子为: location [=|~|~*|^~] uri{ 对location语法列表说明. |1ocation | ...

  3. The class cn.itcast.web.common.util.UtilFuns specified in TLD for the function selffn:htmlNewline cannot be found: cn.itcast.web.common.util.UtilFuns

    我的一个Util方法的包名更改了,运行时候报这个错误.找到tld文件,把包名重新改为我改的名字就好使了.

  4. HDU 1756 Cupid's Arrow (几何问题,判定点在多边形内部)

    题意:中文的么,自己看喽. 析:很容易明白是判定点是不是在多边形内部,一般是向量来判定,我一开始用点在向量的右侧,因为是顺时针给的,只要点全在外侧或边上, 就可以,暴力一下就ok.由于这个是浮点数,一 ...

  5. 仿iPhone滑屏操作

    <!DOCTYPE html> <html> <head>     <meta charset="utf-8">     <m ...

  6. (转)EF Power tool用法

    转自:http://msdn.microsoft.com/zh-cn/data/jj593170.aspx 命令摘要 安装 EF Power Tools 后,将提供以下上下文菜单项.本演练将详细讨论这 ...

  7. TensorFlow入门案例

    入门小案例,分别是回归模型建立和mnist数据集的模型建立 1.回归案例: import tensorflow as tf import numpy as np from tensorflow.exa ...

  8. Date日期操作

    获取年月日时分秒: package com.util; import java.text.DateFormat; import java.util.Calendar; import java.util ...

  9. [php] try - catch exceptiong handler

    //http://stackoverflow.com/questions/1241728/can-i-try-catch-a-warningOne possibility is to set your ...

  10. Beta版本使用说明

    一.产品介绍 我们做的是一个基于安卓的手机app,通过连接图书馆的数据库,实现查询图书馆的书目信息的功能. 二.软件运行 我们只做了安卓版本,需要在安卓环境下运行. 三.软件结构 本软件主要包括客户端 ...