贪吃蛇小游戏

这篇博客介绍了在Linux环境下使用Vim编辑器时遇到的.swap交换文件及其作用,以及如何利用ncurses库编写一个简单的贪吃蛇游戏。游戏包含了上下左右移动、碰撞检测和多线程实现。代码示例展示了游戏的基本逻辑和结构,包括地图绘制、移动、碰撞判断等关键功能。
摘要由CSDN通过智能技术生成

Linux下修改文件崩溃的时候产生了一个.swap 交换文件

在用vim打开一个文件时,其会产生一个 .filename.swap文件,用于保存数据,当文件非正常关闭时,可用此文件来恢复。
文件正常关闭—>此文件会被删除

文件非正常关闭—>不会被删除,所以提示存在.swap文件—>此时你可以恢复文件:恢复以后把.swap文件删掉,在打开时就不会有提示了
swap文件是个隐藏文件:用ls -al查看

通过swp恢复原来文件

  1. vi -r .demo.c.swp打开缓存文件
  2. 将里面的内容复制后到对应的文件

获取用户键盘输入(上下左右异常)

#include <stdio.h>
#include <curses.h>//包含ncurses头文件

int main()
{
        char c;
        initscr();//初始化ncurses

        while(1)
        {
                c = getch();
                printw("input:%c\n",c);
        }
        endwin();//关闭ncurses

        return 0;
}

获取用户输入(包括上下左右)

#include <stdio.h>
#include <curses.h>

int main()
{
        int key;
        initscr();
        keypad(stdscr,1);

        while(1)
        {
                key = getch();
                switch(key)
                {
                        case KEY_UP:
                                printw("UP\n");
                                break;
                        case KEY_DOWN:
                                printw("DOWN\n");
                                break;
                        case KEY_LEFT:
                                printw("LEFT\n");
                                break;
                        case KEY_RIGHT:
                                printw("RIGHT\n");
                                break;
                }
        }
        endwin();
        return 0;
}

完整版地图

#include <curses.h>

void gamePic(),initNcurse();

int main()
{
        initNcurse();//初始化ncursese
        gamePic();

        getch();
        endwin();//关闭ncursese
        return 0;
}

void gamePic()
{
        int row;
        int column;
        for(row = 0;row < 20;row++)
        {   
                if(row == 0)
                {   
                        for(column=0;column<20;column++)
                        {   
                                printw("--");
                        }   
                        printw("\n");
                }   
  }   

                if(row>=0 && row<=19)
                {   
                        for(column=0;column<=20;column++)
                        {
                                if(column==0 || column ==20)
                                {
                                        printw("|");
                                }
                                else
                                {
                                        printw("  ");
                                }
                        }
                        printw("\n");
                }

                if(row == 19)
                {
                        for(column=0;column<20;column++)
                        {
                                printw("--");
                        }
                        printw("\n");
                printw("created by qqx\n");
                }

        }
void initNcurse()
{
        initscr();
        keypad(stdscr,1);
}

实现向右移动

#include <curses.h>
#include <stdlib.h>

void gamePic(),initNcurse(),initSnake(),addNode(),delNode(),moveToRight();
int hasSnakeNode(int row,int column);

struct Snake
{
	int row;
	int column;
	struct Snake *next;
};

struct Snake *head;
struct Snake *tail;

int main()
{
	int con;
	initNcurse();//初始化ncursese
	initSnake();
	gamePic();

	while(1)
	{
		con = getch();
		if(con == KEY_RIGHT)
		{
			moveToRight();
			gamePic();
		}
	}
	getch();
	endwin();//关闭ncursese
	return 0;
}

void delNode()
{
	struct Snake *p;
	p = head;
	head = head->next;
	free(p);
}

void moveToRight()//向右移动的本质,就是右边添加一个,左边删除一个
{
	addNode();
	delNode();
}

void initSnake()
{
	head = (struct Snake *)malloc(sizeof(struct Snake));//初始化头结点的位置为(2,3),并把下一个指向空
	head->row = 2;
	head->column = 2;
	head->next=NULL;

	tail = head;//初始化包含头节点共有3个
	addNode();
	addNode();
}

void addNode()
{
	struct Snake *new = (struct Snake *)malloc(sizeof(struct Snake));//开辟一个新的空间
	
	new->row = tail->row;//新的相较于旧的尾节点,行不变,列加1个
	new->column = tail->column+1;
	new->next = NULL;//新结点下一个给指向为空
	tail->next = new;//将新的节点链接起来
	tail = new;//将新的节点变为尾节点
	
}

void gamePic()
{
	int row;
	int column;
	
	move(0,0);
	for(row = 0;row < 20;row++)
	{
		if(row == 0)
		{
			for(column=0;column<20;column++)
			{
				printw("--");
			}
			printw("\n");
		}

		if(row>=0 && row<=19)
		{
			for(column=0;column<=20;column++)
			{	
				if(column==0 || column ==20)
				{
					printw("|");
				}
				else if(hasSnakeNode(row,column))
				{
					printw("[]");
				}
				else
				{
					printw("  ");
				}
			}
			printw("\n");
		}

		if(row == 19)
		{
			for(column=0;column<20;column++)
			{
				printw("--");
			}
			printw("\n");
			printw("created by qqx\n");
		}
	}
}

int hasSnakeNode(int row,int column)
{
	struct Snake *p = head;
	while(p != NULL)
	{
		if(p->row == row && p->column == column)
		{
			return 1;
		}
		p = p->next;
	}
	return 0;
}

void initNcurse()
{
	initscr();
	keypad(stdscr,1);
}

Linux多线程

#include <stdio.h>
#include <pthread.h>

void *func1(),*func2();

int main()
{
        pthread_t th1;
        pthread_t th2;

        pthread_create(&th1,NULL,func1,NULL);
        pthread_create(&th2,NULL,func2,NULL);

        while(1);

        return 0;
}

void *func1()//返回值必须是void *
{
        while(1)
        {
                printf("1\n");
                sleep(1);
        }
}

void *func2()
{
        while(1)
        {
                printf("2\n");
                sleep(2);
        }
}

实现蛇的上下左右移动

#include <curses.h>
#include <stdlib.h>
#include <pthread.h>

#define UP      1
#define DOWN    2
#define LEFT    3
#define RIGHT   4

void gamePic(),initNcurse(),initSnake(),addNode(),delNode(),moveToRight(),*getDir(),*refreshJieMian();
int hasSnakeNode(int row,int column);

struct Snake
{
        int row;
        int column;
        struct Snake *next;
};

struct Snake *head = NULL;
struct Snake *tail = NULL;
int key;
int dir;

int main()
{
        pthread_t t1;
        pthread_t t2;

        initNcurse();//初始化ncursese
        initSnake();
        gamePic();

        pthread_create(&t1,NULL,getDir,NULL);
        pthread_create(&t2,NULL,refreshJieMian,NULL);
        while(1);

        getch();
        endwin();//关闭ncursese
        return 0;
}

void *refreshJieMian()
{
        while(1)
        {
                moveToRight();
                gamePic();
                refresh();
                usleep(100000);//1000微秒=1毫秒  1000毫秒=1秒
        }
}

void *getDir()
{
        while(1)
        {
                key = getch();
                switch(key)
                {
                        case KEY_UP:
                                dir = UP;
                                break;
                        case KEY_DOWN:
                                dir = DOWN;
                                break;
                        case KEY_LEFT:
                                dir = LEFT;
                                break;
                        case KEY_RIGHT:
                                dir =RIGHT;
                                break;
                }
        }
}

void delNode()
{
        struct Snake *p;
        p = head;
        head = head->next;
        free(p);
}

void moveToRight()//向右移动的本质,就是右边添加一个,左边删除一个
{
        addNode();
        delNode();
        if(tail->column == 20 || tail->column==0 || tail->row == 0 || tail->row ==20)//实现贪吃蛇撞墙就死
        {
                initSnake();
        }
}

void initSnake()
{
        struct Snake *p;

        dir = RIGHT;
        while(head != NULL)//死了之后不为空,释放掉每个节点,防止内存被撑爆
        {
                p = head;
                head = head->next;
                free(p);
        }

        head = (struct Snake *)malloc(sizeof(struct Snake));//初始化头结点的位置为(2,3),并把下一个指向空
        head->row = 2;
        head->column = 2;
        head->next=NULL;

        tail = head;//初始化包含头节点共有3个
        addNode();
        addNode();
}

void addNode()
{
        struct Snake *new = (struct Snake *)malloc(sizeof(struct Snake));//开辟一个新的空间
        new->next = NULL;//新结点下一个给指向为空

        switch(dir)
        {
                case UP:
                        new->row = tail->row-1;
                        new->column = tail->column;
                        break;
                case DOWN:
                        new->row = tail->row+1;
                        new->column = tail->column;
                        break;
                case LEFT:
                        new->row = tail->row;
                        new->column = tail->column-1;
                        break;
                case RIGHT:
                        new->row = tail->row;//新的相较于旧的尾节点,行不变,列加1个
                        new->column = tail->column+1;
                        break;
        }

        tail->next = new;//将新的节点链接起来
        tail = new;//将新的节点变为尾节点

}

void gamePic()
{
        int row;
        int column;

        move(0,0);
        for(row = 0;row < 20;row++)
        {
                if(row == 0)
                {
                        for(column=0;column<20;column++)
                        {
                                printw("--");
                        }
                        printw("\n");
                }

                if(row>=0 && row<=19)
                {
                        for(column=0;column<=20;column++)
                        {
                                if(column==0 || column ==20)
                                {
                                        printw("|");
                                }
                                else if(hasSnakeNode(row,column))
                                {
                                        printw("[]");
                                }
                                else
                                {
                                        printw("  ");
                                }
                        }
                        printw("\n");
                }

                if(row == 19)
                {
                        for(column=0;column<20;column++)
                        {
                                printw("--");
                        }
                        printw("\n");
                        printw("%d\n",key);
                }
        }
}

int hasSnakeNode(int row,int column)
{
        struct Snake *p = head;
        while(p != NULL)
        {
                if(p->row == row && p->column == column)
                {
                        return 1;
                }
                p = p->next;
        }
        return 0;
}

void initNcurse()
{
        initscr();
        keypad(stdscr,1);
}

贪吃蛇最终版本

#include <curses.h>
#include <stdlib.h>
#include <pthread.h>

#define UP 	1
#define DOWN 	-1
#define LEFT 	2
#define RIGHT 	-2

void gamePic(),initNcurse(),initSnake(),addNode(),delNode(),moveToRight(),*getDir(),*refreshJieMian(),turn(),initFood();
int hasSnakeNode(int row,int column),hasFood(int row,int column),ifSnakeDie();

struct Snake
{
	int row;
	int column;
	struct Snake *next;
};

struct Snake *head = NULL;
struct Snake *tail = NULL;
struct Snake food;

int key;
int dir;

int main()
{
	pthread_t t1;
	pthread_t t2;

	initNcurse();//初始化ncursese
	initSnake();
	gamePic();

	pthread_create(&t1,NULL,getDir,NULL);
	pthread_create(&t2,NULL,refreshJieMian,NULL);	
	while(1);

	getch();
	endwin();//关闭ncursese
	return 0;
}

void initFood()
{
	int x = rand()%20;
	int y = rand()%20;

	food.row = x;
	food.column = y;

	x = x+2;
	y = y+2;
}

void *refreshJieMian()
{
	while(1)
	{
		moveToRight();
		gamePic();
		refresh();
		usleep(100000);//1000微秒=1毫秒  1000毫秒=1秒
	}
}

void *getDir()
{
	while(1)
	{
		key = getch();
		switch(key)
		{
			case KEY_UP:
				turn(UP);;
				break;
			case KEY_DOWN:
				turn(DOWN);
				break;
			case KEY_LEFT:
				turn(LEFT);
				break;
			case KEY_RIGHT:
				turn(RIGHT);
				break;
		}
	}
}

void turn(int srcDir)
{
	if(abs(srcDir) != abs(dir))
	{
		dir = srcDir;
	}
}

void delNode()
{
	struct Snake *p;
	p = head;
	head = head->next;
	free(p);
}

void moveToRight()//向右移动的本质,就是右边添加一个,左边删除一个
{
	addNode();
	if(hasFood(tail->row,tail->column))
	{
		initFood();
	}
	else
	{
		delNode();
	}
	if(ifSnakeDie())
	{
		initSnake();	
	}
}

int ifSnakeDie()//蛇撞墙或者蛇自己咬到自己蛇就死了
{
	struct Snake *p;
	p = head;
	if(tail->column == 20 || tail->column==0 || tail->row < 0 || tail->row ==20)//实现贪吃蛇撞墙就死
	{
		return 1;
	}
	while(p->next != NULL)
	{
		if(p->row == tail->row && p->column == tail->column)
		{
			return 1;	
		}
		p=p->next;
	
	}
	return 0;
}

void initSnake()
{
	struct Snake *p;

	dir = RIGHT;
	while(head != NULL)//死了之后不为空,释放掉每个节点,防止内存被撑爆
	{
		p = head;
		head = head->next;
		free(p);
	}	

	initFood();

	head = (struct Snake *)malloc(sizeof(struct Snake));//初始化头结点的位置为(2,3),并把下一个指向空
	head->row = 2;
	head->column = 2;
	head->next=NULL;

	tail = head;//初始化包含头节点共有3个
	addNode();
	addNode();
}

int  hasFood(int row,int column)
{
	if(food.row == row && food.column == column)
	{
		return 1;
	}
	else 
	{
		return 0;
	}
}

void addNode()
{
	struct Snake *new = (struct Snake *)malloc(sizeof(struct Snake));//开辟一个新的空间
	new->next = NULL;//新结点下一个给指向为空

	switch(dir)
	{
		case UP:
			new->row = tail->row-1;
			new->column = tail->column;
			break;
		case DOWN:
			new->row = tail->row+1;
			new->column = tail->column;
			break;
		case LEFT:
			new->row = tail->row;
			new->column = tail->column-1;
			break;
		case RIGHT:
			new->row = tail->row;//新的相较于旧的尾节点,行不变,列加1个
			new->column = tail->column+1;
			break;
	}	

	tail->next = new;//将新的节点链接起来
	tail = new;//将新的节点变为尾节点

}

void gamePic()
{
	int row;
	int column;

	move(0,0);
	for(row = 0;row < 20;row++)
	{
		if(row == 0)
		{
			for(column=0;column<20;column++)
			{
				printw("--");
			}
			printw("\n");
		}

		if(row>=0 && row<=19)
		{
			for(column=0;column<=20;column++)
			{	
				if(column==0 || column ==20)
				{
					printw("|");
				}
				else if(hasSnakeNode(row,column))
				{
					printw("[]");
				}
				else if(hasFood(row,column))//判断是否该显示食物,如果该显示就显示##
				{
					printw("##");
				}
				else
				{
					printw("  ");
				}
			}
			printw("\n");
		}

		if(row == 19)
		{
			for(column=0;column<20;column++)
			{
				printw("--");
			}
			printw("\n");
			//	printw("%d\n",key);
			printw("Snake created by qqx\n");
		}
	}
}

int hasSnakeNode(int row,int column)
{
	struct Snake *p = head;
	while(p != NULL)
	{
		if(p->row == row && p->column == column)
		{
			return 1;
		}
		p = p->next;
	}
	return 0;
}

void initNcurse()
{
	initscr();
	keypad(stdscr,1);
	noecho();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值