马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
这几天看了下linux程序设计,昨天没事干,突发奇想写个贪吃蛇怎么样,因为想想这个游戏也简单!代码全是自己写!
要是有win下的童鞋,注意,这个是linux 版的,用到curses库和pthread库(多线程库)
前提都要安装相关的库
curses库 sudo apt-get install libncurses5-dev
pthread 库sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev
编译的时候带上两库 gcc greedsnake.c -o greedsnake -lcurses -lpthread
注:代码全是自己想和写的,没有参照网上代码,故代码质量较差,高人勿喷!而且这个是刚刚完工的版本,存在bug,但是对于刚入门linuxC的来说
已经满意啦!
游戏实现:
0,因为终端贪吃蛇,所以用字符表示它的身体了,哈
1,首先是用键盘几个方向键控制贪吃蛇的方向,我这里用全局变量way表示,0 向左,1 向上,2 向右,3 向下
2,当头部触及到食物的时候,向前走一步,把食物纳为自己身体,同时最后一节身体不丢失,实现身长+1
3,触及到墙壁或者自己身体的时候,那么蛇死
游戏重点分析:
一 运行分析
因为我没有接触到多线程那些,昨天刚开始写的时候只用了curses库,发现贪吃蛇既要向已定的方向移动,又要监视键盘的输入,刚开始我都没有想到要用多线程,后面写完主体实现后发现,运行点击键盘就崩溃程序,百思不得妻姐,后来脑子一闪,想到了java中的多线程,因为接触C都从来没有用过多线程,所以就仓促百度了下实现过程:
这里,监视键盘输入做为主线程,而游戏运动作为游戏开始后再创立的线程,这样就能实现键盘输入和游戏运行互不影响
二 如何让终端描绘贪吃蛇
错误观点:因为使用curses库终端就是一个24×80的屏幕(默认大小),我这里首先想到用一个二维数组,刚开始全部赋值0,表示终端对应x,y坐标不显示任何东西,而要是array[x][y] = 1 那么对应就是贪吃蛇的身体一个点,我首先用这种思想试了,贪吃蛇成功走起,但是bug非常多,每前进一步,头部向前移,尾部点消失,就是这个关键,尾部点的坐标,一开始我是用rear_x 和rear_y保存尾部点,但是,当蛇向前移的时候,下一个尾部点的对应坐标是什么呢?是它的四个方向的哪一个?刚开始想的是哪个方向点不为空就是谁,但是为题来了,当蛇身体有一部分在身边如何判断?(就是它尾部点周围方向又有其他身体点,如蛇的缠绕在一起,尾部周围可能都是点,——) 所以二维行不通,
正确:那就使用三维数组把,假设那个点存在,那么就保留当前点的时候蛇的前进方向,这样,有了rear_x rear_y就能通过当前点的方向找到下一个尾部节点,比如array[x][y][0] = 1 array[x][y][1] = 2表示当前点为蛇的身体一节点,该节点的前进方向是2(向右)那么这个节点的后一个节点就是
array[x][y+1][0],以此类推,那么找到尾节点就不是问题、
至此,游戏大概思路就这样,主线程处理按键输入,另一线程让贪吃蛇按照既定方向前进
不说,直接上代码#include <curses.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#define Q_line 22
#define width 78
#define height 22
int array[22][78][2]={0};
int head_x = 10;
int head_y = 10;
int rear_x = 10;
int rear_y = 10;
int fool_x;
int fool_y;
int way = 3;
pthread_t id;
//0 left 1 up 2 right 3down
int getchoice();//获取键盘输入
void strat_game();//开始游戏
void creat_fool();//产生一个食物节点
void go();//贪吃蛇的运行前进
void refresh_win();//刷新界面
void creat_fool();//
int check_fool();//检测当前方向的前一个节点是不是食物
void go_catch();//吃掉食物
void find_rear();//找到后一个尾节点
void all_check();//检测是不是墙壁或者吃到自身
void snake_die();//死亡方法
int main()
{
int choice;
int first =0,key;
initscr();
noecho();
cbreak();
keypad(stdscr,1);
mvprintw(5,5,"My Greedy Snake Game V1.0");
mvprintw(6,10,"Power by HeLe");
mvprintw(Q_line,5,"Press space to start");
refresh();
while((key = getchoice()) != 'q'){
switch(key){
case ' ':if(!first){strat_game();first=1;}
break;
case KEY_UP:if(way != 3){way = 1;array[head_x][head_y][1] = 1;}
break;
case KEY_DOWN:if(way != 1){way = 3;array[head_x][head_y][1] = 3;}
break;
case KEY_LEFT:if(way !=2){ way = 0;array[head_x][head_y][1] = 0;}
break;
case KEY_RIGHT:if(way != 0) {way = 2;array[head_x][head_y][1] = 2;}
break;
}
}
endwin();
exit(EXIT_SUCCESS);
}
void snake_die()
{
mvprintw(Q_line-1,5,"Snake has die,Press Q to quti");
refresh();
pthread_exit("Ok");
}
void all_check(int tway) //check die
{
if(head_x > Q_line || head_x < 1 || head_y > 77 || head_y < 1)snake_die();
switch(tway){
case 0:if(array[head_x][head_y-1][0] == 1)snake_die();
break;
case 1:if(array[head_x-1][head_y][0] == 1)snake_die();
break;
case 2:if(array[head_x][head_y+1][0] == 1)snake_die();
break;
case 3:if(array[head_x+1][head_y][0] == 1) snake_die();
break;
}
}
void refresh_win()
{
int x,y;
clear();
for(x = 1; x <= height;x++ )
{
for(y = 1; y <= width; y++)
{
if(array[x][y][0] == 1)
{
mvprintw(x,y,"%s","*");
}
if(x == rear_x && y==rear_y){
mvprintw(x,y,"%s","$");
}
if(x==head_x && y == head_y){
mvprintw(x,y,"%s","@");
}
}
}
for(x = 0 ,y =0;y < 78;y++)
{
mvprintw(x,y,"-");
mvprintw(y,x,"|");
mvprintw(Q_line+1,y,"-");
mvprintw(y,width,"|");
}
move(height,width);
refresh();
usleep(200000);
go();
}
int getchoice(){
int key;
key = getch();
return key;
}
void creat_fool()
{
srand((unsigned)time(NULL));
fool_x = rand() %21+1;
fool_y = rand()%77+1;
while(array[fool_x][fool_y][0] == 1)
{
fool_x = rand()%22+1;
fool_y = rand()%78+1;
}
array[fool_x][fool_y][0] = 1;
}
void strat_game()
{
clear();
//box(stdscr,'|','-');
array[10][10][0] = 1;
array[10][10][1] = 3;
creat_fool();
if((pthread_create(&id,NULL,(void*)refresh_win,NULL)) !=0){
endwin();
exit(1);
}
}
int check_fool()
{
switch(way)
{
case 0:if(head_x == fool_x && (head_y-1) == fool_y)return 1;
else return 0;
break;
case 1:if((head_x-1) == fool_x && head_y == fool_y)return 1;
else return 0;
break;
case 2:if(head_x == fool_x && (head_y+1) == fool_y)return 1;
else return 0;
break;
case 3:if((head_x+1) == fool_x && head_y == fool_y)return 1;
else return 0;
break;
}
}
void go_catch(int tway)
{
array[fool_x][fool_y][0] = 1;
array[fool_x][fool_y][1] = tway;
head_x = fool_x;
head_y = fool_y;
creat_fool();
}
void find_rear()
{
array[rear_x][rear_y][0] = 0;
switch(array[rear_x][rear_y][1]){
case 0:rear_y--;
break;
case 1:rear_x--;
break;
case 2:rear_y++;
break;
case 3:rear_x++;
break;
}
}
void go()
{
switch(way)
{
case 0:if(check_fool()){
go_catch(0);
}
else {
all_check(0);
array[head_x][--head_y][0] = 1;
array[head_x][head_y][1] = 0;
array[rear_x][rear_y][0] = 0;
find_rear();
}
break;
case 1:if(check_fool()){
go_catch(1);
}
else {
all_check(1);
array[--head_x][head_y][0] = 1;
array[head_x][head_y][1] = 1;
array[rear_x][rear_y][0] = 0;
find_rear();
}
break;
case 2:if(check_fool()){
go_catch(2);
}
else {
all_check(2);
array[head_x][++head_y][0] = 1;
array[head_x][head_y][1] = 2;
array[rear_x][rear_y][0] = 0;
find_rear();
}
break;
case 3:if(check_fool()){
go_catch(3);
}
else {
all_check(3);
array[++head_x][head_y][0] = 1;
array[head_x][head_y][1] = 3;
array[rear_x][rear_y][0] = 0;
find_rear();
}
break;
}
refresh_win();
}
如果有童鞋有更好的实现方法,可以说说我实现下,哈! 毕竟这个贪吃蛇完全出于我的手!! |