采用了双向链表结点来模拟蛇身结点;

  通过C语言光标控制函数来打印地图、蛇身和食物;

/**************************
***************************
贪吃蛇游戏
C语言数据结构
作者:Dew
时间:2019年3月23日
版本:1.0
***************************
**************************/ #include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <conio.h> #define N 30
#define TRUE 1
#define FALSE 0
#define TIME 300 #define LEFT 37
#define UP 38
#define RIGHT 39
#define DOWN 40 void initMap();
void showGame();
void initSnake();
void control(int key);
void updateSnake(int next_head_x, int next_head_y);
void gotoxy(int x, int y); //光标控制
void gameRun();
void moveUp();
void moveDown();
void moveLeft();
void moveRight();
void createFood();
void addSnakeNode(int cur_tail_x, int cur_tail_y);
void crashTest(int head_x, int head_y); struct snakeNode {
int pos_x;
int pos_y;
snakeNode* pre;
snakeNode* next;
}; struct foodNode {
int pos_x;
int pos_y;
}; int map[N][N];
int keyPress;
int key; int next_head_x, next_head_y;
int cur_tail_x, cur_tail_y; snakeNode* snake_head = (snakeNode *)malloc(sizeof(snakeNode));
snakeNode* snake_tail = (snakeNode *)malloc(sizeof(snakeNode)); foodNode* food = (foodNode *)malloc(sizeof(foodNode)); int main()
{
initSnake(); initMap(); gameRun(); return 0;
} void initMap()
{
int i, j;
for(i = 0; i < N; i++)
for (j = 0; j < N; j++)
{
if (i == 0 || i == N - 1)
map[i][j] = 1;
else if (j == 0 || j == N - 1)
map[i][j] = 1;
else
map[i][j] = 0;
}
} void showGame()
{
int i, j;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
if (map[i][j] == 1) {
gotoxy(j*2, i);
printf("□");
}
else if (map[i][j] == 0) {
gotoxy(j*2, i);
printf(" ");
}
}
printf("\n");
}
gotoxy(snake_head->pos_y * 2, snake_head->pos_x);
printf("●");
gotoxy(snake_tail->pos_y * 2, snake_tail->pos_x);
printf("●");
gotoxy(food->pos_y * 2, food->pos_x);
printf("◇");
} void initSnake()
{
snake_head->pos_x = 15;
snake_head->pos_y = 15;
snake_head->pre = NULL;
snake_head->next = snake_tail; snake_tail->pre = snake_head;
snake_tail->pos_x = snake_tail->pre->pos_x + 1;
snake_tail->pos_y = snake_tail->pre->pos_y;
snake_tail->next = NULL; food->pos_x = rand() % 28 + 1;
food->pos_y = rand() % 28 + 1;
} void control(int direction)
{
if (direction == UP)
{
moveUp();
}
else if (direction == DOWN)
{
moveDown();
}
else if (direction == LEFT)
{
moveLeft();
}
else if (direction == RIGHT)
{
moveRight();
} } void updateSnake(int next_head_x, int next_head_y)
{
snakeNode* p = snake_tail;
while (p != snake_head)
{
p->pos_x = p->pre->pos_x;
p->pos_y = p->pre->pos_y;
p = p->pre;
}
p->pos_x = next_head_x;
p->pos_y = next_head_y;
} void gotoxy(int x, int y)
{
COORD pos;
HANDLE hOutput;
pos.X = x;
pos.Y = y;
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOutput, pos);
} void gameRun()
{
showGame(); control(UP); while (TRUE)
{
if (GetAsyncKeyState(VK_RIGHT))
{
control(RIGHT);
Sleep(TIME);
}
else if (GetAsyncKeyState(VK_LEFT))
{
control(LEFT);
Sleep(TIME);
}
else if (GetAsyncKeyState(VK_UP))
{
control(UP);
Sleep(TIME);
}
else if (GetAsyncKeyState(VK_DOWN))
{
control(DOWN);
Sleep(TIME);
}
}
} void moveUp()
{
while (TRUE)
{
next_head_x = snake_head->pos_x - 1;
next_head_y = snake_head->pos_y;
cur_tail_x = snake_tail->pos_x;
cur_tail_y = snake_tail->pos_y;
updateSnake(next_head_x, next_head_y);
gotoxy(next_head_y * 2, next_head_x);
printf("●");
crashTest(next_head_x, next_head_y);
if (next_head_x == food->pos_x && next_head_y == food->pos_y)
{
addSnakeNode(cur_tail_x, cur_tail_y);
createFood();
}
else
{
gotoxy(cur_tail_y * 2, cur_tail_x);
printf(" ");
} Sleep(TIME); if (GetAsyncKeyState(VK_RIGHT))
{
control(RIGHT);
Sleep(TIME);
}
else if (GetAsyncKeyState(VK_LEFT))
{
control(LEFT);
Sleep(TIME);
}
else if (GetAsyncKeyState(VK_UP))
{
control(UP);
Sleep(TIME);
}
else if (GetAsyncKeyState(VK_DOWN))
{
continue;
} }
} void moveDown()
{
while (TRUE)
{
next_head_x = snake_head->pos_x + 1;
next_head_y = snake_head->pos_y;
cur_tail_x = snake_tail->pos_x;
cur_tail_y = snake_tail->pos_y;
updateSnake(next_head_x, next_head_y);
gotoxy(next_head_y * 2, next_head_x);
printf("●");
crashTest(next_head_x, next_head_y);
if (next_head_x == food->pos_x && next_head_y == food->pos_y)
{
addSnakeNode(cur_tail_x, cur_tail_y);
createFood();
}
else
{
gotoxy(cur_tail_y * 2, cur_tail_x);
printf(" ");
} Sleep(TIME);
if (GetAsyncKeyState(VK_RIGHT))
{
control(RIGHT);
Sleep(TIME);
}
else if (GetAsyncKeyState(VK_LEFT))
{
control(LEFT);
Sleep(TIME);
}
else if (GetAsyncKeyState(VK_UP))
{
continue;
}
else if (GetAsyncKeyState(VK_DOWN))
{
control(DOWN);
Sleep(TIME);
} }
} void moveLeft()
{
while (TRUE)
{
next_head_x = snake_head->pos_x;
next_head_y = snake_head->pos_y - 1;
cur_tail_x = snake_tail->pos_x;
cur_tail_y = snake_tail->pos_y;
updateSnake(next_head_x, next_head_y);
gotoxy(next_head_y * 2, next_head_x);
printf("●");
crashTest(next_head_x, next_head_y);
if (next_head_x == food->pos_x && next_head_y == food->pos_y)
{
addSnakeNode(cur_tail_x, cur_tail_y);
createFood();
}
else
{
gotoxy(cur_tail_y * 2, cur_tail_x);
printf(" ");
} Sleep(TIME);
if (GetAsyncKeyState(VK_RIGHT))
{
continue;
}
else if (GetAsyncKeyState(VK_LEFT))
{
control(LEFT);
Sleep(TIME);
}
else if (GetAsyncKeyState(VK_UP))
{
control(UP);
Sleep(TIME);
}
else if (GetAsyncKeyState(VK_DOWN))
{
control(DOWN);
Sleep(TIME);
} }
} void moveRight()
{
while (TRUE)
{
next_head_x = snake_head->pos_x;
next_head_y = snake_head->pos_y + 1;
cur_tail_x = snake_tail->pos_x;
cur_tail_y = snake_tail->pos_y;
updateSnake(next_head_x, next_head_y);
gotoxy(next_head_y * 2, next_head_x);
printf("●");
crashTest(next_head_x, next_head_y);
if (next_head_x == food->pos_x && next_head_y == food->pos_y)
{
addSnakeNode(cur_tail_x, cur_tail_y);
createFood();
}
else
{
gotoxy(cur_tail_y * 2, cur_tail_x);
printf(" ");
} Sleep(TIME);
if (GetAsyncKeyState(VK_RIGHT))
{
control(RIGHT);
Sleep(TIME);
}
else if (GetAsyncKeyState(VK_LEFT))
{
continue;
}
else if (GetAsyncKeyState(VK_UP))
{
control(UP);
Sleep(TIME);
}
else if (GetAsyncKeyState(VK_DOWN))
{
control(DOWN);
Sleep(TIME);
} }
} void createFood()
{
food->pos_x = rand() % 28 + 1;
food->pos_y = rand() % 28 + 1;
gotoxy(food->pos_y * 2, food->pos_x);
printf("◇");
} void addSnakeNode(int cur_tail_x, int cur_tail_y)
{
snakeNode* tempNode = (snakeNode *)malloc(sizeof(snakeNode));
tempNode->pos_x = cur_tail_x;
tempNode->pos_y = cur_tail_y;
tempNode->next = NULL;
snake_tail->next = tempNode;
tempNode->pre = snake_tail;
snake_tail = tempNode;
} void crashTest(int head_x, int head_y)
{
snakeNode* p = snake_head->next;
while (p != NULL)
{
if (p->pos_x == head_x && p->pos_y == head_y)
{
gotoxy(32 * 2, 15);
printf("...发生撞击!......游戏结束...");
getchar();
}
if (p->pos_x == 1 || p->pos_x == N - 2 || p->pos_y == 1 || p->pos_y == N - 2)
{
gotoxy(32 * 2, 15);
printf("...发生撞击!......游戏结束...");
getchar();
}
p = p->next;
}
}

贪吃蛇游戏——C语言双向链表实现的更多相关文章

  1. 基于EasyX库的贪吃蛇游戏——C语言实现

    接触编程有段时间了,一直想学习怎么去写个游戏来练练手.在看了B站上的教学终于可以自己试试怎么实现贪吃蛇这个游戏了.好了,废话不多说,我们来看看如何用EasyX库来实现贪吃蛇. 一.准备 工具vc++6 ...

  2. 贪吃蛇游戏C语言源代码学习

    源代码下载地址为:www.clang.cc 阅读学习了源代码,并做了简单的注释和修改,里面只用了链表数据结构,非常适合C语言入门者学习阅读. 程序可在VS2013下编译运行. #include< ...

  3. 【C语言项目】贪吃蛇游戏(上)

    目录 00. 目录 01. 开发背景 02. 功能介绍 03. 欢迎界面设计 3.1 常用终端控制函数 3.2 设置文本颜色函数 3.3 设置光标位置函数 3.4 绘制字符画(蛇) 3.5 欢迎界面函 ...

  4. 贪吃蛇游戏(printf输出C语言版本)

    这一次我们应用printf输出实现一个经典的小游戏—贪吃蛇,主要难点是小蛇数据如何存储.如何实现转弯的效果.吃到食物后如何增加长度. 1 构造小蛇 首先,在画面中显示一条静止的小蛇.二维数组canva ...

  5. 使用Love2D引擎开发贪吃蛇游戏

    今天来介绍博主近期捣腾的一个小游戏[贪吃蛇],贪吃蛇这个游戏相信大家都不会感到陌生吧.今天博主将通过Love2D这款游戏引擎来为大家实现一个简单的贪吃蛇游戏,在本篇文章其中我们将会涉及到贪吃蛇的基本算 ...

  6. Android快乐贪吃蛇游戏实战项目开发教程-01项目概述与目录

    一.项目简介 贪吃蛇是一个很经典的游戏,也很适合用来学习.本教程将和大家一起做一个Android版的贪吃蛇游戏. 我已经将做好的案例上传到了应用宝,无病毒.无广告,大家可以放心下载下来把玩一下.应用宝 ...

  7. 用C++实现的贪吃蛇游戏

    我是一个C++初学者,控制台实现了一个贪吃蛇游戏. 代码如下: //"贪吃蛇游戏"V1.0 //李国良于2016年12月29日编写完成 #include <iostream& ...

  8. WebGL实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

  9. 100行JS实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

随机推荐

  1. 作业2:分布式版本控制系统Git的安装与使用

    1.下载安装配置用户名和邮箱. 2. 创建工作目录并通过git init命令把这个目录变成Git可以管理的仓库. 3. 在工作目录下准备文本文件,建议下载Notepad++代替记事本. 4. 组合用g ...

  2. flask wtforms组件详解

    一.简介 在flask内部并没有提供全面的表单验证,所以当我们不借助第三方插件来处理时候代码会显得混乱,而官方推荐的一个表单验证插件就是wtforms.wtfroms是一个支持多种web框架的form ...

  3. .NET Core 图片操作在 Linux/Docker 下的坑

    一.前言 .NET Core 目前更新到2.2了,但是直到现在在 .NET Core 本身依然不包括和图片有关的 Image.Bitmap 等类型.对于图片的操作在我们开发中很常见,比如:生成验证码. ...

  4. 【故障公告】10:30-10:45 左右 docker swarm 集群节点问题引发故障

    非常抱歉,今天 10:30-10:45 左右由于 docker swarm 集群节点出现问题,造成除博客之外的站点出现访问异常,由此给您带来很大的麻烦,请您谅解. 故障开始时出现有时访问正常有时访问出 ...

  5. Django(八)下:Model操作和Form操作、序列化操作

    二.Form操作 一般会创建forms.py文件,单独存放form模块. Form 专门做数据验证,而且非常强大.有以下两个插件: fields :验证(肯定会用的) widgets:生成HTML(有 ...

  6. centos7之openvpn搭建

    一.环境介绍 操作系统centos7.4 openvpn版本:openvpn-2.1 lzo版本:lzo-2.03 二.搭建 关闭firewalld防火墙,并设置开机不启动.关闭selinux sys ...

  7. DS博客作业01--日期抽象数据类型设计与实现

    1.思维导图及学习体会 1.1第一章绪论知识点思维导图 1.2 学习体会 这次博客园和大作业是我在编程学习中的有意义的进步,第一次尝试使用vs,并且通过同学的一些网站的推荐,和热心同学的帮忙,简单学会 ...

  8. Go语言里的slice

    1.切片是基于数组做的一层封装,灵活能够自动扩容. 2.切片的初始化方法 ①直接创建 ②基于已有的数组或切片 ③使用make来创建一个切片 第一个5是切片的大小 第二个5是切片的容量 3.基本操作 ① ...

  9. Windows Subsystem for Linux 环境变量

    WSL(Windows Subsystem for Linux )的环境变量是包含Linux子系统和Windows系统的,测试如下: wy@WY-PC:/mnt/c/Windows/System32$ ...

  10. tcpdump常用参数说明及常见操作

    tcpdump常用参数说明及常见操作 -a 将网络地址和广播地址转变成名字 -c 指定抓包的数量 -d 将匹配信息包的代码以人们能够理解的汇编格式给出 -dd 将匹配信息包的代码以c语言程序段的格式给 ...