C语言之贪吃蛇(ncurses)
Posted litran
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言之贪吃蛇(ncurses)相关的知识,希望对你有一定的参考价值。
声明: 以下内容可能会引起某些读者不适, 请小心阅读. 有些内容并没有详细介绍, 可能简单理解也是错误的, 但是这都是为了尽量简单。
前言: 代码是很久之前写的,属于边想边写的那种,很混乱。
推荐材料:
贪吃蛇应该是我们这代人都玩过的游戏。而如果我们要写一个贪吃蛇最需要考虑的就是贪吃蛇是如何移动的。其实贪吃蛇的移动就是尾部的减少和头部的增加。
这篇文章:
- 介绍一些ncurses库的基础内容
贪吃蛇游戏的代码解释
介绍一些ncurses库的基础内容
ncurses
curses是一个在命令行下面的图形函数库,而ncurses的意思是 new curses。
ncurses的一些函数的简单解释
#include <ncurses.h>
int main()
{ int ch;
initscr(); /* Start curses mode */
raw(); /* Line buffering disabled */
keypad(stdscr, TRUE); /* We get F1, F2 etc.. */
noecho(); /* Don't echo() while we do getch */
printw("Type any character to see it in bold\n");
ch = getch(); /* If raw() hadn't been called
* we have to press enter before it
* gets to the program */
if(ch == KEY_F(1)) /* Without keypad enabled this will */
printw("F1 Key pressed");/* not get to us either */
/* Without noecho() some ugly escape
* charachters might have been printed
* on screen */
else
{ printw("The pressed key is ");
attron(A_BOLD);
printw("%c", ch);
attroff(A_BOLD);
}
refresh(); /* Print it on to the real screen */
getch(); /* Wait for user input */
endwin(); /* End curses mode */
return 0;
}
这是我从这里拿到的一个例子。
我们应该注意到这个程序并没有导入标准输入输出库,而是导入了ncurses.h文件。在这个程序里面也没有使用printf(format printing),而是使用了printw这个函数(print window)就是打印到标准屏幕的意思
- initscr:初始化屏幕,启动curses模式
- raw:关闭行缓冲,一般的我们在命令行中输入数据的时候,只有当我们按下回车之后,才可以把数据提交给程序
- noecho: 负责按键事务,我不太懂
noecho: 关闭回显(按下一个字符之后,屏幕并不显示。比如说在普通的情况下按下a,a会被显示在屏幕上)
- getch: 获取一个字符
- attron: 在后面的打印中增加打印属性,这里是粗体的意思
- attroff: 移除属性
refresh:之前的printw只是打印到逻辑屏幕,而refresh函数会依据逻辑屏幕的内容,刷新到物理屏幕。
endwin:退出curses模式
其他的可以自己慢慢去学习
ncurses库的安装和使用
安装
如果你是使用debian系列的linux发行版,例如ubuntu,应该直接键入命令:
sudo apt-get install libncurses5-dev
就可以了。
如果是别的系列的版本,建议下载源码包,编译安装。或者百度搜索正确的答案。
使用
一般的,只需要在gcc编译命令的后面加上-lncurses就可以正确导入ncurses库了。
gcc -o demo demo.c -std=c99 -lncurses
-std=c99的意思是使用c99的标准来编译代码。
没有使用过命令行编译操作的同学需要自己去学习。
贪吃蛇的代码解释
从哪里得到
点击这里。这份代码是我写的,也确实写的不好。但也可以随便看看。
代码结构
|-- hungry_snake // 可执行文件,
|-- main.c
|-- snake.c
|-- snake.h
`-- wellcome.h
0 directories, 5 files
hungry_snake是一个可执行文件,在debian下编译的,在centos下面可能需要重新编译。
main.c是程序的主要逻辑部分。
wellcome.h包含了欢迎界面的代码实现。
snake.h
/*
* snake.h
*/
#ifndef SNAKE_H
#define SNAKE_H
#include <ncurses.h>
// 这个枚举类型我其实没有用
typedef enum state
{
goleft,
goright,
goup,
godown
}state;
// 这个是蛇的一节,也就是一个坐标
typedef struct body
{
int y;
int x;
struct body *prev;
struct body *next;
}Body ,*Pbody;
// 这个是蛇的结构定义,有一个虚蛇头,蛇头和蛇尾,还有蛇的长度啊,运动状态啊
typedef struct snake
{
Pbody vir_head;
Pbody head;
Pbody tail;
int length;
state movement; // 我没有用
char uping;
char downing;
char lefting;
char righting;
}Snake, *Psnake;
int FOOD[1000][1000]; // 食物坐标,标记哪个位置有食物
int food_num; // 食物数量
/*
** body part
*/
Pbody init_body(); // 初始化蛇身
void add_body(Pbody jack, Pbody bd); // 增加一节
Pbody bd(int lines,int cols); // 构造一个蛇节
void print_snake(Pbody jack); // 显示那条蛇
void print_bd(Pbody bd); // 显示蛇节
Pbody get_head(Pbody jack); // 得到蛇头部节点
Pbody add_head(Pbody oldhead,Pbody newhead); // 增加节点到头部
Pbody del_tail(Pbody jack); // 删除蛇尾
Pbody get_tail(Pbody jack); // 得到蛇尾节点指针
/*
** snake part
*/
Psnake init_snake(); //初始化蛇
int snake_go_right(Psnake snake); // 蛇的移动
int snake_go_left(Psnake jack);
void show_snake(Psnake jack); // 屏幕上显示蛇
void init_show_snake(Psnake jack); // 忘了
int snake_go_down(Psnake jack); // 蛇的移动
int snake_go_up(Psnake jack);
int snake_can_move(Psnake jack, char ch); // 判断蛇能否往目标方向移动
int body_in_snake(int row, int col, Psnake jack); // 判断蛇身是否覆盖坐标
/* food part */
void putfood(Psnake jack); // 随机投放食物
int count_food(); // 食物技术
/* game_over */
void game_over(Psnake jack); // 游戏结束
#endif // SNAKE_H
这里有一些结构定义和函数声明。
main.c
下面是程序主体逻辑部分:
#include <unistd.h>
#include <stdlib.h>
#include "snake.h"
#include <ncurses.h>
#include "wellcome.h"
#include <pthread.h>
int ch;
int GAMEOVER;
/*
void get_command(void *i)
{
ch = getch();
}
*/
int main()
{
initscr();
start_color();
keypad(stdscr,TRUE);
curs_set(0);
noecho();
halfdelay(4);
init_pair(1,COLOR_WHITE,COLOR_BLACK);
init_pair(2,COLOR_BLACK,COLOR_WHITE);
print_snake_logo(stdscr);
mvprintw(LINES-1,COLS-20,"Producted by Jack");
mvprintw(LINES-4,(COLS-21)/2,"|-> START");
printw(" (? for help)");
refresh();
int choice;
char goout = 0;
while (!goout){
switch (choice = getch() ){
case 'q':
endwin();
return 0;
case 'e':
goout = 1;
break;
}
}
/*
pthread_t id;
pthread_create(&id,NULL,get_command,NULL);
*/
Psnake jack = init_snake();
init_show_snake(jack);
ch = mvgetch(LINES-1,0);
srand((unsigned)time(0));
for (int i = 0; i<10; i++)
putfood(jack);
refresh();
int noout = 1;
int c = 0;
while(noout){
ch = getch();
switch (ch){
case KEY_RIGHT:
c = snake_go_right(jack);
if ( c == -1){
noout = 0;
GAMEOVER = 1;
break;
}
continue;
case KEY_DOWN :
c = snake_go_down(jack);
if ( c == -1){
noout = 0;
GAMEOVER = 1;
break;
}
continue;
case KEY_LEFT:
c = snake_go_left(jack);
if ( c == -1){
noout = 0;
GAMEOVER = 1;
break;
}
continue;
case KEY_UP:
c = snake_go_up(jack);
if ( c == -1){
noout = 0;
GAMEOVER = 1;
break;
}
continue;
case 'q':
game_over(jack);
endwin();
return 0;
}
if (jack->righting){
c = snake_go_right(jack);
if (c == -1){
GAMEOVER = 1;
break;
}
}
else if (jack->lefting){
c = snake_go_left(jack);
if (c == -1){
GAMEOVER = 1;
break;
}
}
else if(jack->uping){
c = snake_go_up(jack);
if (c == -1){
GAMEOVER = 1;
break;
}
}
else if(jack->downing){
c = snake_go_down(jack);
if (c == -1){
GAMEOVER = 1;
break;
}
}
if (food_num < 30)
putfood(jack);
mvprintw(LINES-1,2,"-- socre %d --",jack->length);
refresh();
}
if(GAMEOVER)
game_over(jack);
refresh();
endwin();
return 0;
}
编译
gcc -o snake.out snake.h snake.c main.c wellcome.h -lncurses -std=c99
小结
这份代码写的太差劲,所以我也没有也不想过多的去讲它。
以上是关于C语言之贪吃蛇(ncurses)的主要内容,如果未能解决你的问题,请参考以下文章