上大学学习编程的初始目的就是冲着游戏来的~不过在刚学习C语言的时候,完全无法利用所学知识弄出一个可玩的游戏╮(╯_╰)╭,学了1年后仍然对最简单的贪吃蛇没有思路(当然不是说没有打代码的思路,而是没有办法弄出动态的东西,而且当时往算法那走了~),直到如今大二,利用寒假的一点时间入门Linux的时候,发现了curses库函数!当我看明白它的作用时,拍案而起,TM这玩意不就是我梦寐以求的可实现界面的东东么!当我学了一点点就觉悟到,用一个move()和printw()函数就完全可以把贪吃蛇这种级别的写出来。。。

既然要写就要写自己喜欢玩的~一条蛇太单调没有可玩价值,弄两条刚好有点挑战性!

游戏规则:

初始时两条蛇会在中间,[email protected],食物是‘$’;另一条蛇头是‘+‘,食物是‘*‘,蛇身都是‘#‘。WASD控制‘+‘蛇方向,[email protected],每条蛇只能吃自己的食物。撞墙,碰到自己或另一条蛇的身体,吃到另一条蛇的食物都会结束游戏。

运行环境:Linux操作系统,请确认已安装curses库,没有的请在终端输入sudo apt-get libncurses5-dev 安装(移植性不好~可惜了)

编译指令:例如保存为snake.c    就在终端键入:g++ -o snake snake.c -lcurses

执行指令:在终端键入:./snake

思路:

怎样弄出一条蛇呢?我觉得用双链表还是比较方便的,每个结点记录的是当前蛇身的坐标跟前驱后继指针。这样在蛇移动时在头结点前添加一个结点,用move()移动到蛇头坐标,打印蛇头;接着如果没有吃到食物的话,把尾结点删掉,用move()移动到蛇尾,打印空值。之后~完了(高中语文都是及格低分飘过,再加上懒,只能写这么一点。。。)

感慨:

唉~想归想,实际动起手来还是有点麻烦的。主要是键盘响应上的问题,由于是刚刚接触curses库,学得还是很浅的。还是那句话,语文太差,连问题都不知道如何形容。。。反正就是按下任一方向键不松手,一段时间后松开,然后再按别的方向,它会先朝之前的方向移动,直到移动完后在去别的方向。移动一步的时间调得越慢,这种现象越明显。意思就是我不懂怎样在移动一步的时间内把多余的输入getch()忽略掉。还有一个蛋疼的就是让我在无数次尝试中发现了一个客观性的东西:C语言不支持函数的引用参数。我个蛋!害我无数次在终端中输入gcc开头的可爱句子找问题,结果可想而知。本来想加上计分的,后来发现,两条蛇的话,不知道怎样计才公平,唉~还需要一点点数学。。。最后想说一点就是:在编程的很多时候,我们并不是缺少能力,而是缺少工具。(像这个例子:我懂点C语言,但我不懂curses库,我就做不出东西),所以不敢说精通,但至少要熟练运用一门语言,之后再去找合适的工具,编程就不是什么难事情。写到这里,突然提醒了我,也提醒了大家,学编程,基础与实践很重要,反正切不可急!相信别人能做的,自己也可以!

PS:这只是刚写完版本的,bug众多~我觉得在继续学习curses的过程中为程序添加生机,这样才不那么枯燥。虽然curses库是基于文本的图形编程,但一样可以把游戏做得很好看。为QT打下基础先。。。

最后一点,CSND博客里的字符显示是不是出现了点问题。。。

#include

#include

#include

#include

#include

int dir_y[] = {-1, 1, 0, 0};

int dir_x[] = {0, 0, -1, 1};

int vis[100][100];

int scord;

typedef struct body

{

int y, x;

struct body *pre, *sub;

} Body;

typedef struct

{

Body *head, *tail;

int DIRECTION;

int HEAD_X;

int HEAD_Y;

int FOOD_X;

int FOOD_Y;

char food;

char H;

} Snake;

//随机函数

int Get_Rand_Number(int k)

{

static int first_time = 0;

if(!first_time){

first_time = 1;

srand((unsigned int)(time(NULL)));

}

return rand()%k + 1;

}

void Add(Snake &snake)

{

Body *s;

s = (Body *)malloc(sizeof(Body));

s->y = snake.HEAD_Y;

s->x = snake.HEAD_X;

s->pre = NULL;

s->sub = snake.head;

snake.head->pre = s;

snake.head = s;

}

void Free(Body *head)

{

if(NULL == head) return;

Free(head->sub);

free(head);

}

int Judge_Kill(int y, int x)

{

if(y == LINES - 1 || x == COLS - 1 || y == 0 || x == 0) return 1;

if(1 == vis[y][x]) return 1;

return 0;

}

void Initialization(Snake &snake, int y, int x)

{

snake.DIRECTION = 0;

int &FOOD_Y = snake.FOOD_Y;

int &FOOD_X = snake.FOOD_X;

snake.HEAD_Y = y;

snake.HEAD_X = x;

while(1)

{

FOOD_Y = Get_Rand_Number(LINES - 3);

FOOD_X = Get_Rand_Number(COLS - 3);

if(!vis[FOOD_Y][FOOD_X]){

vis[FOOD_Y][FOOD_X] = 2;

break;

}

}

move(FOOD_Y, FOOD_X);

printw("%c", snake.food);

snake.head = (Body *)malloc(sizeof(Body));

snake.head->y = y;

snake.head->x = x;

snake.head->pre = snake.head->sub = NULL;

snake.tail = snake.head;

move(y, x);

printw("%c", snake.H);

refresh();

}

void New_Food(Snake &snake)

{

scord++;

int &FOOD_Y = snake.FOOD_Y;

int &FOOD_X = snake.FOOD_X;

while(1){

FOOD_Y = Get_Rand_Number(LINES - 3);

FOOD_X = Get_Rand_Number(COLS - 3);

if(!vis[FOOD_Y][FOOD_X]){

vis[FOOD_Y][FOOD_X] = 2;

break;

}

}

move(FOOD_Y, FOOD_X);

printw("%c", snake.food);

}

void Reverse_Direction(Snake &snake)

{

int &HEAD_Y = snake.HEAD_Y;

int &HEAD_X = snake.HEAD_X;

Body *&head = snake.head;

HEAD_Y += dir_y[snake.DIRECTION];

HEAD_X += dir_x[snake.DIRECTION];

//在蛇长不为1时,下一个移动跟蛇运动方向相反

if(head->sub && HEAD_Y == head->sub->y && HEAD_X == head->sub->x){

if(HEAD_Y == head->y){

if(HEAD_X > head->x) HEAD_X = head->x - 1;

else HEAD_X = head->x + 1;

}

else{

if(HEAD_Y > head->y) HEAD_Y = head->y - 1;

else HEAD_Y = head->y + 1;

}

}

}

int Move(Snake &snake, int fy, int fx)

{

int &FOOD_Y = snake.FOOD_Y;

int &FOOD_X = snake.FOOD_X;

int &HEAD_Y = snake.HEAD_Y;

int &HEAD_X = snake.HEAD_X;

Body *&head = snake.head;

Body *&tail = snake.tail;

//输出蛇头

move(HEAD_Y, HEAD_X);

printw("%c", snake.H);

vis[HEAD_Y][HEAD_X] = 1;

//如果有蛇身,输出之

if(head->sub){

move(head->sub->y, head->sub->x);

printw("#");

}

if(HEAD_Y == FOOD_Y && HEAD_X == FOOD_X) New_Food(snake);//吃到食物

else if(HEAD_Y == fy && HEAD_X == fx) return 1;//吃到另一条蛇的食物

else{//什么都没有吃到

move(tail->y, tail->x);

printw(" ");

vis[tail->y][tail->x] = 0;

free(tail);

if(tail->pre){

tail = tail->pre;

tail->sub = NULL;

}

}

return 0;

}

int main()

{

initscr();

curs_set(0);//隐藏物理指针

noecho();//不回显输入

box(stdscr, '|', '-');//画框

Snake snake1, snake2;

snake1.food = '$';

snake2.food = '*';

snake1.H = '@';

snake2.H = '+';

//两条蛇的初始化位置(小蛇放中间比较舒服)

int init1_y = LINES / 2;

int init1_x = COLS / 2 - 1;

int init2_y = LINES / 2;

int init2_x = COLS / 2 + 1;

vis[init1_y][init1_x] = vis[init2_y][init2_x] = 1;

//初始化两条蛇位置跟食物位置

Initialization(snake1, init1_y, init1_x);

Initialization(snake2, init2_y, init2_x);

keypad(stdscr, true);//开启键盘功能键

int key = 0;

key = getch();

while(1)

{

if(KEY_UP == key) snake1.DIRECTION = 0;

else if(KEY_DOWN == key) snake1.DIRECTION = 1;

else if(KEY_LEFT == key) snake1.DIRECTION = 2;

else if(KEY_RIGHT == key) snake1.DIRECTION = 3;

else if('w' == key) snake2.DIRECTION = 0;

else if('s'== key) snake2.DIRECTION = 1;

else if('a' == key) snake2.DIRECTION = 2;

else if('d' == key) snake2.DIRECTION = 3;

//获取向前移动的坐标及判断是否跟蛇运动方向相反(一条长度不为1的运动着的蛇

//是有一个方向是不能走的)

Reverse_Direction(snake1);

Reverse_Direction(snake2);

//判断游戏是否结束

if(Judge_Kill(snake1.HEAD_Y, snake1.HEAD_X) || Judge_Kill(snake2.HEAD_Y, snake2.HEAD_X)){

//释放内存,很重要

Free(snake1.head);

Free(snake2.head);

break;

}

//往各自的链表添加蛇身

Add(snake1);

Add(snake2);

//移动蛇及判断是否吃到另一条蛇的食物

int over1 = 0, over2 = 0;

over1 = Move(snake1, snake2.FOOD_Y, snake2.FOOD_X);

over2 = Move(snake2, snake1.FOOD_Y, snake1.FOOD_X);

if(over1 || over2) break;

refresh();

usleep(150*1000);//停留150毫秒

if(ERR != halfdelay(1)) key = getch();//在100毫秒内等待输入,如无输入,往下执行

}

sleep(3);

endwin();

exit(0);

}

原文:http://blog.csdn.net/u013351484/article/details/43940803

c语言贪吃蛇积分用什么函数,C语言之贪吃蛇(curses库函数)相关推荐

  1. C语言 va_start / va_end / va_arg 自定义 printf 函数 - C语言零基础入门教程

    目录 一.前言 二.函数不定长参数简介 1.va_start 2.va_arg 3.va_end 三.win32 控制台版本 四.MFC 对话框版本 五.猜你喜欢 零基础 C/C++ 学习路线推荐 : ...

  2. C语言 用传统流程图表示分段函数,C语言程序设计习题答案

    C语言程序设计习题答案 习题一 C语言程序设计概述 一.名词解释 (1)程序P1 (2)程序设计P1 (3)机器语言P1 (4)汇编程序P2 (5)高级语言P2 (6)编译程序P3 (7)解释程序P3 ...

  3. c语言里的fun是什么函数,c语言fun函数有什么作用

    c语言fun函数的作用是被主函数所调用,来定义一个函数或方法,这样在引用时可以用fun表示,比如[int fun(int x,int y)]. c语言fun函数的作用是: C语言中,fun函数通常被主 ...

  4. c语言中如何定义一个pos函数,c语言中函数 Pos(40, 12);是什么意思?

    2019-11-26 回答 有两种理解.(1)库函数是c语言的内部函数或自带函数,外部函数即程序员自定函数. (2)凡加写了extern 的函数是外部函数. 第一种理解好懂: c语言的内部函数指的是c ...

  5. C语言规定 在一个源程序中 main函数,C语言规定:在一个源程序中,main函数的位置()A.必须在程序的最开始B.必须在系统调用的库函数的_搜题易...

    完全数,又称完美数或完数(Perfect Number),它是指这样的一些特殊的自然数,它所有的真因子(即除了自身以外的约数)的和,恰好等于它本身.例如,6就是一个完全数,是因为6 = 1 + 2 + ...

  6. c语言中用于格式化输出的函数,C语言中格式化输入输出函数(转)

    1.1.1 格式化输入输出函数 一.printf()函数 printf()函数是格式化输出函数, 一般用于向标准输出设备按规定格式输出 信息.在编写程序时经常会用到此函数.printf()函数的调用格 ...

  7. C/C++ atol函数- C语言零基础入门教程

    目录 一.ltoa 函数简介 二.int/long/unsigned long 区别 1.无符号整形(16 位系统) 2.有符号整形(16 位系统) 3.int 和 long 区别 三.atol 函数 ...

  8. C/C++ strtol 函数 - C语言零基础入门教程

    目录 一.strtol 函数简介 二.strtol 函数函数实战 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 一.strtol 函数简 ...

  9. C/C++ strtod函数 - C语言零基础入门教程

    目录 一.strtod 函数简介 二.strtod 函数函数实战 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 一.strtod 函数简 ...

  10. C/C++ ultoa函数 - C语言零基础入门教程

    目录 一.ltoa 函数简介 二.int/long/unsigned long 区别 1.无符号整形(16 位系统) 2.有符号整形(16 位系统) 3.int 和 long 区别 三.ultoa 函 ...

最新文章

  1. mysql中pi是什么意思,MySql delimiter的作用是什么
  2. 免sudo使用docker
  3. flutter图标按钮_Flutter开发第一个项目android studio 开发工具的使用说明
  4. WCF 第四章 绑定 msmqIntegrationBinding
  5. 《超越想象——Windows_8应用设计与开发》
  6. boost::phoenix::function相关的测试程序
  7. raid5 合适 多少块硬盘_raid1 raid2 raid5 raid6 raid10如何选择使用?各需要几块硬盘?...
  8. 学习笔记:CentOS7学习之二十二: 结构化命令case和for、while循环
  9. 没有到主机的路由_网络基础知识:TCP协议之跟踪路由
  10. HttpWatch工具简介及使用技巧(二)
  11. java字符串加密解密
  12. 论文阅读笔记(一)——DESCENDING THROUGH A CROWDED VALLEY—BENCHMARKING DEEP LEARNING OPTIMIZERS
  13. html5 拖放游戏,HTML5拖放API实现拖放排序的实例代码
  14. 代码 点胶gcode_3D打印☞Gcode代码详解(含详解PDF附件)
  15. Windows XP无线零配置服务
  16. Crosses and Crosses POJ - 3537 (博弈)
  17. 从鼠标点击位置发射射线检测是否点击到3D世界中的物体
  18. html的u标签去掉文字下划线代码
  19. 自习室的泡利不相容定律(C语言实现)
  20. 【Vue】 Vue生命周期详解

热门文章

  1. 极简jmeter使用教程
  2. 把svg图标制作成字体图标_SVG图标FTW
  3. 0x68111002_黑苹果10.12.2驱动R9 270显卡成功一例
  4. vb.net 功能f8键事件_UG软件F8快捷键和笔记本电脑F8快捷键冲突的解决方法
  5. 小程序和H5 之间的通信
  6. REST服务和RESTful API是什么
  7. java jsp中文乱码怎么解决_如何解决JSP中文乱码问题
  8. DataGrip连接不上本地localhost数据库解决办法
  9. Ubuntu与stm32串口通信及Windows与stm32串口通信
  10. 小米笔记本计算机在哪里,小米笔记本电脑配置在哪里查看