1、更改不合理走位
在上一篇的末尾,完成了贪吃蛇小游戏中四方走位,但是,同样当小蛇在向上或者向右走的时候,此时在摁与之想反的反方向,就会立刻响应键盘的操作,这是不对的(当然也可以把这个当作特色,并不进行更改),在小蛇活动的时候,摁上与之相反的按键,要让小蛇不响应这个按键,那么此时引用abs()函数。
abs()是一个求绝对值的函数。在不同的编程语言中,abs()函数用于计算一个数的绝对值,即去掉该数的符号,无论是正数还是负数,都会返回其正值。
更改完成之后的小蛇走位的代码:
#include <stdlib.h>
#include <ncurses.h>
#include <pthread.h>
#define UP 1//定义成绝对值的形式,上下一对,左右一对
#define DOWN -1
#define LEFT 2
#define RIGHT -2
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head = NULL;
struct Snake *tail = NULL;
int key;
int dir;
void initNcurse(){
initscr();
keypad(stdscr,1);
noecho();//不要把无关的功能键的信息显示在界面上,避免地图出现乱码情况
}
int hasSnakeNode(int i,int j){
struct Snake *p;
p = head;
while(p != NULL){
if(p->hang == i && p->lie == j){
return 1;
}
p = p->next;
}
return 0;
}
void gamePic(){
int hang;
int lie;
move(0,0);
for(hang=0;hang<20;hang++){
if(hang == 0){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
}
if(hang >=0 && hang<=19)
{
for(lie=0;lie<=20;lie++){
if(lie == 0 || lie == 20){
printw("|");
}else if(hasSnakeNode(hang,lie)){
printw("[]");
}
else{
printw(" ");
}
}
printw("\n");
}
if (hang == 19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By ljs,key = %d\n",key);
}
}
}
void addNode(){
struct Snake *new = (struct Snake *)malloc(sizeof(struct Snake));
new->next = NULL;
switch(dir){
case UP:
new->hang = tail->hang-1;
new->lie = tail->lie;
break;
case DOWN:
new->hang = tail->hang+1;
new->lie = tail->lie;
break;
case LEFT:
new->hang = tail->hang;
new->lie = tail->lie-1;
break;
case RIGHT:
new->hang = tail->hang;
new->lie = tail->lie+1;
break;
}
tail->next = new;
tail = new;
}
void initSnake(){
struct Snake *p;
dir = RIGHT;
while(head != NULL){
p =head;
head = head->next;
free(p);
}
head = (struct Snake *)malloc(sizeof(struct Snake));
head->hang = 2;
head->lie = 1;
head->next = NULL;
tail = head;
addNode();
addNode();
}
void deleNode(){
struct Snake *p;
p=head;
head = head->next;
free(p);
}
void moveSnake(){
addNode();
deleNode();
if(tail->hang == 0||tail->lie == 0||tail->hang == 20 || tail->lie == 20){
initSnake();
}
}
void* refreshJieMian(){
while(1){
moveSnake();
gamePic();
refresh();
usleep(100000);
}
}
void turn(int direction){//来判断行走方向与键盘输入方法是否相反
if(abs(dir) != abs(direction)){//让用户输入的方向键与现在正在走的方向的绝对值不相等,不相等时才能转向
dir = direction;
}
}
void* changeDir(){
while(1){
key = getch();
switch(key){
case KEY_DOWN:
turn(DOWN);//调用转弯函数
break;
case KEY_UP:
turn(UP);
break;
case KEY_LEFT:
turn(LEFT);
break;
case KEY_RIGHT:
turn(RIGHT);
break;
}
}
}
int main()
{
pthread_t t1;
pthread_t t2;
initNcurse();
initSnake();
gamePic();
pthread_create(&t1,NULL,refreshJieMian,NULL);
pthread_create(&t2,NULL,changeDir,NULL);
while(1);
getch();
endwin();
return 0;
2、贪吃蛇的食物
关心的是,
1、食物的位置与符号
2、位置同样可以使用贪吃蛇的节点结构体
3、符号用“##”表示
#include <stdlib.h>
#include <ncurses.h>
#include <pthread.h>
#define UP 1
#define DOWN -1
#define LEFT 2
#define RIGHT -2
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head = NULL;
struct Snake *tail = NULL;
int key;
int dir;
struct Snake food;
void initFood(){//初始化食物
static int x = 4;
static int y = 5;//定义静态变量,不改变
food.hang = x;
food.lie = y;
x+=2;
y+=2;
noecho();
}
void initNcurse(){
initscr();
keypad(stdscr,1);
noecho();
}
int hasSnakeNode(int i,int j){
struct Snake *p;
p = head;
while(p != NULL){
if(p->hang == i && p->lie == j){
return 1;
}
p = p->next;
}
return 0;
}
int hasFood(int i,int j){//当蛇的尾巴结点等于食物结点的行列值时。返回1,否则返回0
if(food.hang == i && food.lie == j){
return 1;
}
return 0;
}
void gamePic(){
int hang;
int lie;
move(0,0);
for(hang=0;hang<20;hang++){
if(hang == 0){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
}
if(hang >=0 && hang<=19)
{
for(lie=0;lie<=20;lie++){
if(lie == 0 || lie == 20){
printw("|");
}else if(hasSnakeNode(hang,lie)){
printw("[]");
}else if(hasFood(hang,lie)){
printw("##");
}
else{
printw(" ");
}
}
printw("\n");
}
if (hang == 19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By ljs,key = %d\n",key);
}
}
}
void addNode(){
struct Snake *new = (struct Snake *)malloc(sizeof(struct Snake));
new->next = NULL;
switch(dir){
case UP:
new->hang = tail->hang-1;
new->lie = tail->lie;
break;
case DOWN:
new->hang = tail->hang+1;
new->lie = tail->lie;
break;
case LEFT:
new->hang = tail->hang;
new->lie = tail->lie-1;
break;
case RIGHT:
new->hang = tail->hang;
new->lie = tail->lie+1;
break;
}
tail->next = new;
tail = new;
}
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));//开辟空间
head->hang = 2;
head->lie = 1;
head->next = NULL;
tail = head;
addNode();
addNode();
}
void deleNode(){
struct Snake *p;
p=head;
head = head->next;
free(p);
}
void moveSnake(){
addNode();
if(hasFood(tail->hang,tail->lie)){//返回值是1时,重新初始化食物,否则删除节点
initFood();
}else{
deleNode();
}
if(tail->hang == 0||tail->lie == 0||tail->hang == 20 || tail->lie == 20){
initSnake();
}
}
void* refreshJieMian(){
while(1){
moveSnake();
gamePic();
refresh();
usleep(100000);
}
}
void turn(int direction){
if(abs(dir) != abs(direction)){
dir = direction;
}
}
void* changeDir(){
while(1){
key = getch();
switch(key){
case KEY_DOWN:
turn(DOWN);
break;
case KEY_UP:
turn(UP);
break;
case KEY_LEFT:
turn(LEFT);
break;
case KEY_RIGHT:
turn(RIGHT);
break;
}
}
}
int main()
{
pthread_t t1;
pthread_t t2;
initNcurse();
initSnake();
gamePic();
pthread_create(&t1,NULL,refreshJieMian,NULL);
pthread_create(&t2,NULL,changeDir,NULL);
while(1);
getch();
endwin();
return 0;
}
3、贪吃蛇的食物2
贪吃蛇的食物随机在框里出现
若食物的坐标时(x,y)
则要求0<=x<=19
0<=y<=19
引用rand()函数,生成随机数的函数
思路,对rand()%20取余运算
代码修改如下:
void initFood(){
int x = rand()%20;//对随机数除以20取余,这个取余的范围就时0-19
int y = rand()%20;
food.hang = x;
food.lie = y;
noecho();
}
4、优化代码并且贪吃蛇碰到自己死亡
问题一,蛇没到最顶端就死掉了
原因是tail.hang=0
修改代码如下:
void moveSnake(){
addNode();
if(hasFood(tail->hang,tail->lie)){
initFood();
}else{
deleNode();
}
if(tail->hang < 0||tail->lie == 0||tail->hang == 20 || tail->lie == 20){
initSnake();
}
}
问题二,蛇撞不死自己
代码实现如下:
#include <stdlib.h>
#include <ncurses.h>
#include <pthread.h>
#define UP 1
#define DOWN -1
#define LEFT 2
#define RIGHT -2
struct Snake{
int hang;
int lie;
struct Snake *next;
};
struct Snake *head = NULL;
struct Snake *tail = NULL;
int key;
int dir;
struct Snake food;
void initFood(){
int x = rand()%20;
int y = rand()%20;
food.hang = x;
food.lie = y;
noecho();
}
void initNcurse(){
initscr();
keypad(stdscr,1);
noecho();
}
int hasSnakeNode(int i,int j){
struct Snake *p;
p = head;
while(p != NULL){
if(p->hang == i && p->lie == j){
return 1;
}
p = p->next;
}
return 0;
}
int hasFood(int i,int j){
if(food.hang == i && food.lie == j){
return 1;
}
return 0;
}
void gamePic(){
int hang;
int lie;
move(0,0);
for(hang=0;hang<20;hang++){
if(hang == 0){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
}
if(hang >=0 && hang<=19)
{
for(lie=0;lie<=20;lie++){
if(lie == 0 || lie == 20){
printw("|");
}else if(hasSnakeNode(hang,lie)){
printw("[]");
}else if(hasFood(hang,lie)){
printw("##");
}
else{
printw(" ");
}
}
printw("\n");
}
if (hang == 19){
for(lie=0;lie<20;lie++){
printw("--");
}
printw("\n");
printw("By ljs,key = %d,food.hang = %d,food.lie = %d\n",key,food.hang,food.lie);
}
}
}
void addNode(){
struct Snake *new = (struct Snake *)malloc(sizeof(struct Snake));
new->next = NULL;
switch(dir){
case UP:
new->hang = tail->hang-1;
new->lie = tail->lie;
break;
case DOWN:
new->hang = tail->hang+1;
new->lie = tail->lie;
break;
case LEFT:
new->hang = tail->hang;
new->lie = tail->lie-1;
break;
case RIGHT:
new->hang = tail->hang;
new->lie = tail->lie+1;
break;
}
tail->next = new;
tail = new;
}
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));
head->hang = 2;
head->lie = 1;
head->next = NULL;
tail = head;
addNode();
addNode();
}
void deleNode(){
struct Snake *p;
p=head;
head = head->next;
free(p);
}
int ifSnakeDie(){
struct Snake *p;
p = head;
if(tail->hang < 0||tail->lie == 0||tail->hang == 20 || tail->lie == 20){//蛇碰到边界返回1,然后重新初始化,就是死亡了
return 1;
}
while(p->next != NULL){//当p的下一个不为空时,执行while循环
if(p->hang == tail->hang && p->lie == tail ->lie){//判断头结点的行列与尾巴结点的行列是否相等,如果相等证明贪吃蛇的头尾巴和身子相撞了,返回1,蛇死亡
return 1;
}
p = p->next;
}
return 0;
}
void moveSnake(){
addNode();
if(hasFood(tail->hang,tail->lie)){
initFood();
}else{
deleNode();
}
if(ifSnakeDie()){//判断函数的返回值是不是1,是否执行初始化蛇函数,也就是蛇是否死亡函数
initSnake();
}
}
void* refreshJieMian(){
while(1){
moveSnake();
gamePic();
refresh();
usleep(100000);
}
}
void turn(int direction){
if(abs(dir) != abs(direction)){
dir = direction;
}
}
void* changeDir(){
while(1){
key = getch();
switch(key){
case KEY_DOWN:
turn(DOWN);
break;
case KEY_UP:
turn(UP);
break;
case KEY_LEFT:
turn(LEFT);
break;
case KEY_RIGHT:
turn(RIGHT);
break;
}
}
}
int main()
{
pthread_t t1;
pthread_t t2;
initNcurse();
initSnake();
gamePic();
pthread_create(&t1,NULL,refreshJieMian,NULL);
pthread_create(&t2,NULL,changeDir,NULL);
while(1);
getch();
endwin();
return 0;
}
执行代码:
从
页面
退回
页面
按ctrl+C