前天看了下链表,由于平时对链表的使用不多,所以对链表的应用也没什么了解,所以想来想去,就想用链表实现一下贪吃蛇。

下面言归正传,先看效果图,再看代码,其他没有了!

图1:

图2:

代码:

#include<iostream.h>
//turbo c++ conio.h==控制控制台相关函数的头文件
#include<conio.h>
#include<time.h>
#include<stdlib.h> typedef char bool; //点
struct Point
{
int x;
int y;
}; //链表的一个节点
//蛇的一个身体
//每个节点包含位置信息,pos:当前位置,lastpos:上一个位置
struct Node
{
Point lastpos;
Point pos;
Node* next;
}; //围墙
struct Wall
{
int UP_BOND;
int RIGHT_BOND;
int DOWN_BOND;
int LEFT_BOND;
int length;
short offset;
}; //蛇
struct Snake
{
Node* head;//蛇的头
Node* tail;//蛇的尾
Node* atefood;//蛇吃下的食物信息
Node* lastfood;//食物中最先被吃下的一个
int length;//蛇的长度
short direction;//蛇移动的方向
int timeperstep;//蛇的移动速度
Wall wall;//围墙
}; //获取当前蛇的尾巴节点
Node* getSnakeTail(Snake* snake)
{
Node* node;
Node* lastnode; lastnode = snake->head;
node = snake->head; while(NULL != node)
{
lastnode = node;
node = node->next;
} return lastnode;
}; //初始化时添加蛇身
void addNode(Snake* snake,Node* node)
{
node->next = snake->head;
snake->head = node;
}; //随机产生食物时,检测食物是否在蛇的身上,即不合法
bool generateCheck(Point* pos,Snake* snake)
{
Node* node;
node = snake->head;
while(node!=NULL)
{
if(pos->x == node->pos.x&&pos->y == node->pos.y)
{
return 1;
}
node = node->next;
}
node = snake->atefood;
while(NULL!=node)
{
if(pos->x == node->pos.x&&pos->y == node->pos.y)
{
return 1;
}
node = node->next;
}
return 0;
}; //产生食物,位置随机
Point* generateFood(Snake* snake)
{
Point* pos;
pos = new Point; srand(time(NULL)); pos->x = rand()%snake->wall.length+snake->wall.offset+2;
pos->y = rand()%snake->wall.length+snake->wall.offset+2; while(generateCheck(pos,snake))
{
pos->x = rand()%50+2;
pos->y = rand()%50+2;
} return pos;
}; //检测蛇是否吃到食物
bool eateFood(Snake* snake,Point* food)
{
if(snake->head->pos.x == food->x && snake->head->pos.y == food->y)
{
return 1;
} return 0;
} //检测蛇是否撞到围墙或自己的身体
bool attackCheck(Snake* snake)
{
switch(snake->direction)
{
case 0://up
if(snake->head->pos.y == snake->wall.UP_BOND)
{
return 1;
}
break;
case 1://right
if(snake->head->pos.x == snake->wall.RIGHT_BOND)
{
return 1;
}
break;
case 2://down
if(snake->head->pos.y == snake->wall.DOWN_BOND)
{
return 1;
}
break;
case 3://left
if(snake->head->pos.x == snake->wall.LEFT_BOND)
{
return 1;
}
break;
} Node* node;
node = snake->head->next;
while(NULL != node)
{
if(snake->head->pos.x == node->pos.x &&
snake->head->pos.y == node->pos.y)
return 1;
node = node->next;
} return 0;
}; //向当前方向移动蛇
bool move(Snake* snake)
{
snake->head->lastpos.x = snake->head->pos.x;
snake->head->lastpos.y = snake->head->pos.y; switch(snake->direction)
{
case 0://up
snake->head->pos.y--;
break;
case 1://right
snake->head->pos.x++;
break;
case 2://down
snake->head->pos.y++;
break;
case 3://left
snake->head->pos.x--;
break;
} Node* nodelast;
Node* node;
node = snake->head; //headmove
gotoxy(node->pos.x,node->pos.y);
cout<<'#'; nodelast = node;
node = node->next; while(node!=NULL)
{
node->lastpos.x = node->pos.x;
node->lastpos.y = node->pos.y; node->pos.x = nodelast->lastpos.x;
node->pos.y = nodelast->lastpos.y; //move
gotoxy(node->pos.x,node->pos.y);
cout<<'*';
nodelast = node;
node = node->next;
} //lastpos
//gotoxy(nodelast->lastpos.x,nodelast->lastpos.y);
gotoxy(snake->tail->lastpos.x,snake->tail->lastpos.y);
cout<<' '; if(1 == attackCheck(snake))
return 0; return 1;
}; //初始化
Snake* init()
{ Snake* snake;
snake = new Snake;
snake->length = 0;
snake->head = NULL; Node* node;
int head_x;
int head_y; head_x = 5;
head_y = 5; for(int i=0;i<3;i++)
{
node = new Node;
node->pos.x = head_x;
node->pos.y = head_y;
node->next = NULL;
head_x++;
snake->length++;
addNode(snake,node);
} snake->tail = getSnakeTail(snake);
snake->lastfood = NULL;
snake->atefood = NULL; snake->direction = 1; snake->timeperstep = 5; snake->wall.length = 20;
snake->wall.offset = 0;
snake->wall.UP_BOND = snake->wall.offset+1;
snake->wall.RIGHT_BOND = snake->wall.length+snake->wall.offset+2;
snake->wall.DOWN_BOND = snake->wall.length+snake->wall.offset+2;
snake->wall.LEFT_BOND = snake->wall.offset+1; //draw wall
int temp = snake->wall.length+2;
for(i = 0;i < temp;i++)
{
//left wall
gotoxy(1,i+1);
cout<<'|';
//right wall
gotoxy(temp,i+1);
cout<<'|';
//up wall
gotoxy(i+1,1);
cout<<'-';
//down wall
gotoxy(i+1,temp);
cout<<'-';
} //draw snake
//head
gotoxy(snake->head->pos.x,snake->head->pos.y);
cout<<'#';
//body
node = snake->head->next;
while(node!=NULL)
{
gotoxy(node->pos.x,node->pos.y);
cout<<'*';
node = node->next;
} //state
gotoxy(snake->wall.RIGHT_BOND+10,snake->wall.UP_BOND+6);
cout<<"SCORES:0"; return snake;
}; //获取蛇吃下的倒数第二个食物
Node* getLastSecFood(Snake* snake)
{
Node* node;
Node* lastnode; lastnode = NULL;
node = snake->atefood; while(NULL != node->next)
{
lastnode = node;
node = node->next;
} return lastnode;
} //吃到一个食物
void addFood(Snake* snake,Node* node)
{
if(NULL == snake->atefood)
snake->lastfood =node; node->next = snake->atefood;
snake->atefood = node; }; //检测食物是否消化,以增长蛇的长度
//当蛇吃下一个食物或多个食物时,食物的位置信息会被存储
//当蛇的尾部移动到相对最先被吃下的食物的位置时,将食物转换为蛇的体长,及食物被消化。
void growSnake(Snake* snake)
{
if(NULL == snake->lastfood)
return; Node* temp = getLastSecFood(snake);
if(NULL == temp)
{
snake->lastfood = snake->atefood;
}
else
{
snake->lastfood = temp->next;
} if(snake->lastfood ->pos.x == snake->tail->lastpos.x &&
snake->lastfood->pos.y == snake->tail->lastpos.y)
{
snake->tail->next = snake->lastfood;
snake->tail = snake->lastfood; if(NULL == snake->atefood->next)
{
snake->lastfood = NULL;
snake->atefood = NULL;
}
else
{
snake->lastfood = getLastSecFood(snake);
snake->lastfood->next = NULL;
}
snake->length++;
} } //清除链表的内存
void clean(Snake* snake)
{
Node* node;
Node* temp;
node = snake->head;
while(NULL != node)
{
temp = node;
node = node->next;
delete temp;
} node = snake->atefood;
while(NULL!=node)
{
temp = node;
node = node->next;
delete temp;
} delete snake;
} //主函数
int main()
{
Snake* snake;
clock_t start;
bool flag;
Point* food;
Node* node;
int score;
short state; while(1)//外层:重新开始游戏
{
clrscr();//清屏 snake = init();
state = 0;
score = 0; //产生第一个食物
food = generateFood(snake);
gotoxy(food->x,food->y);
cout<<'@'; while(1)//第二层:刷新,移动蛇
{
flag = 1;
start = clock();
//while((flag = (clock()-start<=snake->timeperstep))&&!kbhit());
while(1)
{
//如果是时间间隔到达
if(clock() - start >= snake->timeperstep)
{
flag = 0;
break;
}
//如果是有按键按下
if(kbhit())
break;
};
//有按键按下时,根据按下的键改变方向
if(1==flag)
{
char temp = getch();
//cin.ignore(80);
switch(temp)
{
case 'w':
if(2!=snake->direction)
snake->direction = 0;
break;
case 'd':
if(3!=snake->direction)
snake->direction = 1;
break;
case 's':
if(0!=snake->direction)
snake->direction = 2;
break;
case 'a':
if(1!=snake->direction)
snake->direction = 3;
break;
}
}
//如果移动失败,碰到围墙或自身
if(0==move(snake))
{
gotoxy(snake->wall.RIGHT_BOND+10,snake->wall.UP_BOND+7);
cout<<"game over!";
gotoxy(snake->wall.RIGHT_BOND+10,snake->wall.UP_BOND+8);
cout<<"press 'q' to quit and others to continue!";
char temp;
temp = getch(); if('q' == temp)
{
state = 1;
}
else
{
state = 2;
}
break;
} //如果吃到了食物
if(1 == eateFood(snake,food))
{
node = new Node;
node->pos.x = food->x;
node->pos.y = food->y;
node->next = NULL;
addFood(snake,node);
food = generateFood(snake);
gotoxy(food->x,food->y);
cout<<'@';
score+=10;
}
//时刻检测是否增长身体
growSnake(snake);
gotoxy(snake->wall.RIGHT_BOND+10,snake->wall.UP_BOND+6);
cout<<"SCORES:"<<score;
}
if(state == 1)
break;
clean(snake);
} return 1;
};

不能运行主要是clrscr和goto函数,参考:

#include <windows.h>
#include <stdio.h> void ConPrint(char *CharBuffer, int len);
void ConPrintAt(int x, int y, char *CharBuffer, int len);
void gotoXY(int x, int y);
void ClearConsole(void);
void ClearConsoleToColors(int ForgC, int BackC);
void SetColorAndBackground(int ForgC, int BackC);
void SetColor(int ForgC);
void HideTheCursor(void);
void ShowTheCursor(void); int main(int argc, char* argv[])
{
HideTheCursor();
ClearConsoleToColors(15, 1);
ClearConsole();
gotoXY(1, 1);
SetColor(14);
printf("This is a test...\n");
Sleep(5000);
ShowTheCursor();
SetColorAndBackground(15, 12);
ConPrint("This is also a test...\n", 23);
SetColorAndBackground(1, 7);
ConPrintAt(22, 15, "This is also a test...\n", 23);
gotoXY(0, 24);
SetColorAndBackground(7, 1);
return 0;
} //This will clear the console while setting the forground and
//background colors.
void ClearConsoleToColors(int ForgC, int BackC)
{
WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);
//Get the handle to the current output buffer...
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
//This is used to reset the carat/cursor to the top left.
COORD coord = {0, 0};
//A return value... indicating how many chars were written
//not used but we need to capture this since it will be
//written anyway (passing NULL causes an access violation).
DWORD count; //This is a structure containing all of the console info
// it is used here to find the size of the console.
CONSOLE_SCREEN_BUFFER_INFO csbi;
//Here we will set the current color
SetConsoleTextAttribute(hStdOut, wColor);
if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
{
//This fills the buffer with a given character (in this case 32=space).
FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count); FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
//This will set our cursor position for the next print statement.
SetConsoleCursorPosition(hStdOut, coord);
}
} //This will clear the console.
void ClearConsole()
{
//Get the handle to the current output buffer...
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
//This is used to reset the carat/cursor to the top left.
COORD coord = {0, 0};
//A return value... indicating how many chars were written
// not used but we need to capture this since it will be
// written anyway (passing NULL causes an access violation).
DWORD count;
//This is a structure containing all of the console info
// it is used here to find the size of the console.
CONSOLE_SCREEN_BUFFER_INFO csbi;
//Here we will set the current color
if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
{
//This fills the buffer with a given character (in this case 32=space).
FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
//This will set our cursor position for the next print statement.
SetConsoleCursorPosition(hStdOut, coord);
}
} //This will set the position of the cursor
void gotoXY(int x, int y)
{
//Initialize the coordinates
COORD coord = {x, y};
//Set the position
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
} //This will set the forground color for printing in a console window.
void SetColor(int ForgC)
{
WORD wColor;
//We will need this handle to get the current background attribute
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi; //We use csbi for the wAttributes word.
if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
{
//Mask out all but the background attribute, and add in the forgournd color
wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);
SetConsoleTextAttribute(hStdOut, wColor);
}
} //This will set the forground and background color for printing in a console window.
void SetColorAndBackground(int ForgC, int BackC)
{
WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), wColor);
} //Direct console output
void ConPrint(char *CharBuffer, int len)
{
DWORD count;
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), CharBuffer, len, &count, NULL);
} //Direct Console output at a particular coordinate.
void ConPrintAt(int x, int y, char *CharBuffer, int len)
{
DWORD count;
COORD coord = {x, y};
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hStdOut, coord);
WriteConsole(hStdOut, CharBuffer, len, &count, NULL);
} //Hides the console cursor
void HideTheCursor()
{
CONSOLE_CURSOR_INFO cciCursor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); if(GetConsoleCursorInfo(hStdOut, &cciCursor))
{
cciCursor.bVisible = FALSE;
SetConsoleCursorInfo(hStdOut, &cciCursor);
}
} //Shows the console cursor
void ShowTheCursor()
{
CONSOLE_CURSOR_INFO cciCursor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); if(GetConsoleCursorInfo(hStdOut, &cciCursor))
{
cciCursor.bVisible = TRUE;
SetConsoleCursorInfo(hStdOut, &cciCursor);
}
}

字符界面的贪吃蛇--链表--C++的更多相关文章

  1. console下纯字符实现的贪吃蛇

    最近简直超级无聊-- code blocks win7 64编译运行无问题,应该其他编译器也不会有问题. w:上 s:下 a:左 d:右 CS标准方向控制,AK47和M4这种高级货是没有滴-- 废话不 ...

  2. C项目实践--贪吃蛇(1)

    1.功能需求分析 1.1主要功能 i.游戏欢迎界面 ii.游戏执行功能,包括计算得分 iii.游戏结束界面 1.2游戏基本规则 游戏开始时蛇的长度是4个单位,并且按照当前方向不停地移动.移动范围是CO ...

  3. 使用TypeScript实现简单的HTML5贪吃蛇游戏

    TypeScript是一种由微软开发的自由和开源的编程语言.它是JavaScript的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程.安德斯·海尔斯伯格,C#的首席架构师,已 ...

  4. easyx图形库做贪吃蛇游戏

    编程总是对着一个黑窗口,可以说是非常乏味了,于是喵喵就翻出来了以前用easyx图形库做图形界面的贪吃蛇游戏. 不过大家只是当做提高编程的乐趣来学习吧,想进一步做的话可以学习QT,还有其他的框架. 这是 ...

  5. 用Python实现童年小游戏贪吃蛇

    贪吃蛇作为一款经典小游戏,早在 1976 年就面世了,我最早接触它还是在家长的诺基亚手机中.

  6. [C语言]链表实现贪吃蛇及部分模块优化

    在继上篇[C语言]贪吃蛇_结构数组实现大半年后,链表实现的版本也终于出炉了.两篇隔了这么久除了是懒癌晚期的原因外,对整个游戏流程的改进,模块的精简也花了一些时间(都是借口). 优化模块的前沿链接: · ...

  7. Perl字符贪吃蛇

    一时兴起,想试试能不能用perl实现字符贪吃蛇,算法如下: 定义2个数组@bg.@snake,@bg用来显示整个界面,@snake从蛇头开始保存蛇的坐标点. 蛇每移动一次,新的坐标点放到@snake头 ...

  8. 以小时候玩的贪吃蛇为例,对于Java图像界面的学习感悟

    简介 正文 01.JFrame是啥? 02.JPanel 03. KeyListener 04.Runnable 05.游戏Running 06.游戏初始类编写 07.main 简介: 一直以来用代码 ...

  9. C字符贪吃蛇

    算法参照Perl字符贪吃蛇,源码: #include <stdio.h> #include <windows.h> #define WIDTH 12 // 宽 #define ...

随机推荐

  1. vue,vux判断字符串是否是undefined

    if (typeof thisObj.city === 'undefined') { return}

  2. 第一章:IPsecVPN

    第一章 一.VPN(virtual private Network,虚拟专用网)的基本概念 VPN连接模式分为两种,分别是传输模式和隧道模式 传输模式:在整个VPN传输中,ip包头并没有被封装进去 隧 ...

  3. 【洛谷p1932】A+B A-B A*B A/B A%B Problem

    (emmmm) 这道题成功让我见识到了Dev撤回的高端大气上档(dàng)次. A+B A-B A*B A/B A%B Problem[传送门](真是个优秀的高精) 算法:::::::(模板题弄这么费 ...

  4. 解决audio 在部分移动端浏览器不能自动播放(目前包括ios、微博)

    问题描述:项目需要在页面加载完成后自动播放音乐,但在ios中却无法自动播放,需要用户主动触发 解决办法: $('html').one('touchstart',function(){ document ...

  5. python中生成器

    1.简介 通过列表生成式,我们可以直接创建一个列表,但是受到内存的限制,列表容量肯定是有限的. 如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢? 在Pytho ...

  6. 【LeetCode】大数相乘

    1. 模拟手工计算 原理: 将 string 反转存储在 int 数组中,如 A = 17 = (7, 1),B = 25 = (5, 2),亦即幂表示法,幂次是从低位到高位. 作逐位相乘,即 ai ...

  7. vue-router 按需加载

    vue的单页面(SPA)项目,必然涉及路由按需的问题.以前我们是这么做的 //require.ensure是webpack里面的,这样做会将单独拉出来作为一个chunk文件 const Login = ...

  8. 巧用call,appl有 根据对象某一属性求最大值

    查找对象数组中某属性的最大最小值的快捷方法 例如要查找array数组中对象的value属性的最大值 var array=[ { "index_id": 119, "are ...

  9. linux 添加php gd扩展 (linux添加PHP扩展)

    首先最基本的 第一:先安装库 yum -y install libjpeglibjpeg-devel libpng libpng-devel freetype freetype-devel 第二:进入 ...

  10. where的顺序对运行的影响--无影响

    2.表连接的时候,大表与小表的顺序是哪个在前.3.在多表连接时,是表与表先连接起来,再执行对单表的限制条件where条件:还是先执行单表的限制where条件,再进行表连接?4.多表连接时,如4个表,我 ...