你所在的位置:微信群>公众号运营>正文

源代码的开发(以新浪SAE为例),小游戏编写规则

原创
发布时间: 2023-05-31 10:22:06 热度: 426 作者: 李斯特 来源: 微信加 本文共 14558 字 阅读需要 49 分钟
要编写一个小游戏,需要先将该游戏的规则写得清楚明白,要找到游戏进行的流程、奖励等。以一个小游戏——贪吃蛇为例。规则这个游戏很简单。

要编写一个小游戏,需要先将该游戏的规则写得清楚明白,要找到游戏进行的流程、奖励等。以一个小游戏——贪吃蛇为例。

规则

这个游戏很简单,通过玩家的操作来控制蛇移动的方向,使贪吃蛇迟到果实,并且不让蛇的身体碰到墙壁。

程序启动后,载入游戏并初始化,同时定时器启动。按下 4 个方向键中的任意一个后,蛇身开始运动,界面内随机出现果实。根据键盘控制蛇的移动。判断是否吃到果实,如果没吃到果实,就继续随键盘控制而移动;如果吃到一个果实,蛇身增加一节,随机生成下一个果实,并继续随键盘控制而移动。判断蛇头坐标和自身或者墙坐标是否重合,如果不重合,就继续随键盘控制而移动;如果重合,游戏结束。

编写游戏中需要注意的是:

(1)要实现贪吃蛇自动向前移动,根据时间间隔,每一次将贪吃蛇的每节身体分别向前移动一格。移动方向为贪吃蛇当前行走方向。

(2)要使玩家能够通过键盘的上下左右 4 个方向控制贪吃蛇当前行走方向,吃掉屏幕上出现的果实。

(3)在游戏中,果实的出现,采用随机方式。当前一个果实被吃掉时,屏幕上随机出现另一个果实,且果实不与蛇身重合。

编写代码

撰写游戏的相关规则后,就可以着手游戏代码了。“贪吃蛇”的构成可大致分为“蛇”“食物”“墙壁”3 个部分,因此首先就要将这 3 个要素编写出来。蛇身初始化编码,如下所示。

void init() {

initscr(); //屏幕控制初始化,如果成功,返回一个只想 stdscr 结构的指针

raw(); //关闭特殊字符的处理

noecho();//关闭输入字符的回显功能

keypad(stdscr,TRUE);

curs_set(0);

nodelay(stdscr,TRUE);

}

蛇身的初始化编码

“蛇”与“食物”,它们用结构体表示出来,如下所示。

struct Snack {

int x[100];

int y[100];

int node;

int life;

int direction;

} snack;

struct Food {

int X,Y;

int set;

} food;

结构体

接着打印出蛇身和食物,如下所示。这里的“打印”就是 C 语言中的 printf()函数,是一种最常用的格式化输出函数,其原型为: int printf(char * format,...) ;printf()会根据参数 format 字符串来转换并格式化数据,然后将结果输出到标准输出设备(显示器),直到出现字符串结束('\0')为止。

void draw() {

snack.x[0]=6;

snack.y[0]=3;

snack.x[1]=5;

snack.y[1]=3;

snack.x[2]=4;

snack.y[2]=3;

snack.life= 0;

snack.node= 3;

snack.direction= 4;

food.set=0;

color();

d_e();

for(i=0; i < snack.node; i ++)

mvprintw(snack.y [i],snack.x[i],"*");

refresh();

timer=time(NULL);

}

打印出蛇身和食物

mvprintw() 函数为 int myprintw(int y,int x,char * format,...)

然后在指定的位置打印(x,y)字符串 format。随机生成食物,如下所示。

if(food.set== 0){

food.X=rand() % 50;

while(food.X== 0 || food.X==49)

food.X=rand() % 50;

food.Y=rand() % 20;

while(food.Y== 0 || food.Y==19)

food.Y=rand() % 20;

food.set=1;

}

食物生成

打印四面墙的模板如下所示。其中 start_color()函数对 curses 的颜色例程进行初始化;init_pair()函数对准备使用的颜色组合进行初始化;attron()函数在不影响其他属性的前提下启用制定的属性。

void color() {

start_color();

init_pair(1,COLOR_ GREEN,COLOR _RED);

attron(COLOR _PAIR(1));

for(i=0; i < 50; i++)

mvaddch(0,i,'*');

for(i=0; i < 20; i++)

mvaddch(i, 0,'*');

for(i=49; i >=0; i--)

mvaddch(19,i,'*');

for(i=19; i >=0; i--)

mvaddch(i, 49,'*'); // box(stdscr,' *','*');

attroff(COLOR _PAIR(1));

}

打印四面墙

在贪吃蛇游戏中,蛇身的移动也是游戏的重要组成部分。只有蛇身能够移动转向,才能将游戏推动下去。在游戏中玩家能够控制蛇身的移动方向,所以编程中需要能够判断前进方向,这一项编码如下所示。

void judge() {

if(snack.direction== 1)//up

snack.y[0]--;

else if(snack.direction== 2)//down

snack.y[0]++;

else if(snack.direction== 3)//left

snack.x[0]--;

else //right

snack.x[0]++;

}

ch=getch();

switch(ch) {

case(KEY_UP):

if(snack.direction== 3 || snack.direction== 4){

判断前进方向

snack.y[0]--;

snack.direction= 1;

} else if(snack.direction== 1)

snack.y[0]--;

else

snack.y[0]++;

break;

case(KEY_DOWN):

if(snack.direction== 3 || snack.direction== 4){

snack.y[0]++;

snack.direction= 2;

} else if(snack.direction== 1)

snack.y[0]--;

else

snack.y[0]++;

break;

case(KEY_LEFT):

if(snack.direction== 1 || snack.direction== 2){

snack.x[0]--;

snack.direction= 3;

} else if(snack.direction== 3)

snack.x[0]--;

else

snack.x[0]++;

break;

case(KEY_RIGHT):

if(snack.direction== 1 || snack.direction== 2){

snack.x[0]++;

snack.direction= 4;

} else if(snack.direction== 3)

snack.x[0]--;

else

snack.x[0]++;

break;

判断前进方向(续)

当贪吃蛇吃到食物后,需要进行加分奖励,因此在编程中也需要注意判断蛇是否吃到食物,吃到食物的个数以及奖励分数等,如下所示。

if(snack.x [0] ==food.X && snack.y [0]==food.Y){

food.set=0;

snack.node ++;

score +=10;

for(i=snack.node - 1; i > 0; i--){

snack.x[i]=snack.x[i - 1];

snack.y[i]=snack.y[i - 1];

}

judge();

}

蛇吃到食物

游戏开始之后,蛇身碰到墙壁即游戏失败,因此也需要在代码中编写判断游戏结束的程序,如下所示。

if((snack.x [0]==snack.x[i] && snack.y [0]==snack.y[i])

|| snack.x[0]==0 || snack.y[0]==0 || snack.x[0]==49

|| snack.y[0]==19){

for(i=1; i < snack.node; i ++){

snack.x[i - 1]=snack.x[i];

snack.y[i - 1]=snack.y[i];

}

snack.y[ snack.node - 1]=tem[0];

snack.x[ snack.node - 1]=tem[1];

for(i=0; i < snack.node; i ++)

mvprintw(snack.y [i],snack.x[i],"*");

mvaddch(food.Y,food.X,' *');

start_attr();

mvprintw(10,10 ,"You lose!");

mvprintw(11,10 ,"Do you want again?(y /n)");

output();

snack.life= 1;

//sleep(1);

break;

}

游戏结束

贪吃蛇的完整程序如下所示。

#include<curses.h>

#include<stdlib.h>

#include<unistd.h>

#include<time.h>

struct Snack {

int x[100],y[100];

int node;

int life;

int direction;

} snack;

struct Food {

int X,Y;

int set;

} food;

struct timespec delay;

struct timespec dummy;

time_t timer;

int TIME=0;

long Time,Time 1=0,Time2=0;

int ptime[100];

int score= 0;

int i,tem[2],k=0;

void color();

void init();

void draw();

void start _attr();

void output();

void play();

void judge();

int pause_ time(int,int *);

void d_e();

int main(int argc,char **argv){

init();

draw();

完整程序

play();

return 0;

}

void d_e(){

int location= 18;

int ch2=KEY_ LEFT,which= 0;

char str[2][5]={ "Easy","Hard" };

while(ch2 !='\n')

switch(ch2){

case(KEY_LEFT):

if(location != 18){

location -= 10;

which=0;

}

break;

case(KEY_RIGHT):

if(location== 18){

location +=10;

which=1;

}

break;

}

mvprintw(8,10 ,"Please choose the difficulty!");

mvprintw(10,23,"^_^");

mvprintw(12,18,"Easy");

mvprintw(12,28,"Hard");

attron(A_REVERSE);

mvprintw(12 ,location," %s",str[which]);

attroff(A_REVERSE);

refresh();

ch2=getch();

}

/*Time2 =time(NULL);

ptime[k]=Time2-Time1;

k++; */

if(location== 28)

完整程序(续)

delay.tv_nsec=100000000;

else

delay.tv_nsec=200000000;

}

int pause_ time(int k,int *PTIME){

int j;

int sum=0;

for(j=0; j < k; j++)

sum=sum + ptime[j];

return sum;

}

void judge() {

if(snack.direction== 1)

snack.y[0]--;

else if(snack.direction== 2)

snack.y[0]++;

else if(snack.direction== 3)

snack.x[0]--;

else

snack.x[0]++;

}

void color() {

start_color();

init_pair(1,COLOR_ GREEN,COLOR _RED);

attron(COLOR _PAIR(1));

for(i=0; i < 50; i++)

mvaddch(0,i,'*');

for(i=0; i < 20; i++)

mvaddch(i, 0,'*');

for(i=49; i >=0; i--)

mvaddch(19,i,'*');

for(i=19; i >=0; i--)

mvaddch(i, 49,'*'); // box(stdscr,' *','*');

attroff(COLOR _PAIR(1));

}

完整程序(续)

void init() {

initscr();

raw();

noecho();

keypad(stdscr,TRUE);

curs_set(0);

nodelay(stdscr,TRUE);

}

void draw() {

snack.x[0]=6;

snack.y[0]=3;

snack.x[1]=5;

snack.y[1]=3;

snack.x[2]=4;

snack.y[2]=3;

snack.life= 0;

snack.node= 3;

snack.direction= 4;

food.set=0;

color();

d_e();

for(i=0; i < snack.node; i ++)

mvprintw(snack.y [i],snack.x[i],"*");

refresh();

timer=time(NULL);

}

void output() {

color();

mvprintw(20,0,"Score=% d",score);

mvprintw(20,43,"Node=% d",snack.node);

mvprintw(21,0,"Time=% ds",TIME);

attroff(A_REVERSE);

refresh();

}

void start _attr(){

attron(A_REVERSE);

}

完整程序(续)

void play() {

while(1){

Time=time(NULL);

TIME=Time - timer - pause _ time(k,ptime);

clear();

if(food.set== 0){

food.X=rand() % 50;

while(food.X== 0 || food.X==49)

food.X=rand() % 50;

food.Y=rand() % 20;

while(food.Y== 0 || food.Y==19)

food.Y=rand() % 20;

food.set=1;

}

tem[0]=snack.y[ snack.node - 1];

tem[1]=snack.x[ snack.node - 1];

for(i=snack.node - 1; i > 0; i--){

snack.x[i]=snack.x[i - 1];

snack.y[i]=snack.y[i - 1];

}

int ch=0;

ch=getch();

switch(ch) {

case(KEY_UP):

if(snack.direction== 3 || snack.direction== 4){

snack.y[0]--;

snack.direction= 1;

} else if(snack.direction== 1)

snack.y[0]--;

else

snack.y[0]++;

break;

case(KEY_DOWN):

if(snack.direction== 3 || snack.direction== 4){

snack.y[0]++;

snack.direction= 2;

} else if(snack.direction== 1)

完整程序(续)

snack.y[0]--;

else

snack.y[0]++;

break;

case(KEY_LEFT):

if(snack.direction== 1 || snack.direction== 2){

snack.x[0]--;

snack.direction= 3;

} else if(snack.direction== 3)

snack.x[0]--;

else

snack.x[0]++;

break;

case(KEY_RIGHT):

if(snack.direction== 1 || snack.direction== 2){

snack.x[0]++;

snack.direction= 4;

} else if(snack.direction== 3)

snack.x[0]--;

else

snack.x[0]++;

break;

case 'p':

case 'P':

Time1 =time(NULL);

judge();

for(i=0; i < snack.node; i ++)

mvprintw(snack.y [i],snack.x[i],"*");

mvaddch(food.Y,food.X,' *');

start_attr();

mvprintw(9,10 ,"Pause!Press 'p' to continue!");

output();

while(getch()!='p')

;

Time2 =time(NULL);

ptime[k]=Time2 - Time1;

k++;

完整程序(续)

break;

case 'q':

case 'Q':

Time1 =time(NULL);

judge();

for(i=0; i < snack.node; i ++)

mvprintw(snack.y [i],snack.x[i],"*");

mvaddch(food.Y,food.X,' *');

start_attr();

mvprintw(10,22 ,"Quit!");

output();

int location= 18;

int ch2=KEY_ LEFT,which= 0;

char str[2][5]={ "No","Yes" };

while(ch2 !=‘\n’){

switch(ch2){

case(KEY_LEFT):

if(location != 18){

location -= 10;

which=0;

}

break;

case(KEY_RIGHT):

if(location== 18){

location +=10;

which=1;

}

break;

}

mvprintw(12,18,"No");

mvprintw(12,28,"Yes");

attron(A_REVERSE);

mvprintw(12 ,location," %s",str[which]);

attroff(A_REVERSE);

refresh();

ch2=getch();

完整程序(续)

}

Time2 =time(NULL);

ptime[k]=Time2 - Time1;k++;

if(location== 18)

break;

else {

clear();

endwin();

exit(1);

}

default:

judge();

break;

}

for(i=1; i < snack.node; i ++)

if((snack.x [0]==snack.x[i] && snack.y [0]==snack.y[i])

|| snack.x[0]==0 || snack.y[0]==0 || snack.x[0]==49

|| snack.y[0]==19){

for(i=1; i < snack.node; i ++){

snack.x[i - 1]=snack.x[i];

snack.y[i - 1]=snack.y[i];

}

snack.y[ snack.node - 1]=tem[0];

snack.x[ snack.node - 1]=tem[1];

for(i=0; i < snack.node; i ++)

mvprintw(snack.y [i],snack.x[i],"*");

mvaddch(food.Y,food.X,' *');

start_attr();

mvprintw(10,10 ,"You lose!");

mvprintw(11,10 ,"Do you want again?(y /n)");

output();

snack.life= 1;

//sleep(1);

break;

}

if(snack.x [0] ==food.X && snack.y [0]==food.Y){

food.set=0;

完整程序(续)

snack.node ++;

score +=10;

for(i=snack.node - 1; i > 0; i--){

snack.x[i]=snack.x[i - 1];

snack.y[i]=snack.y[i - 1];

}

judge();

}

if(snack.life== 0){

;

for(i=0; i < snack.node; i ++)

mvprintw(snack.y [i],snack.x[i],"*");

//attron(A_INVIS);

mvaddch(food.Y,food.X,' *');

//sleep(1);

//attroff(A_INVIS);

start_attr();

output();

nanosleep(&delay,&dummy); //sleep(2);

}

else {

char ch1;

while(ch1=getch())

if(ch1=='y' || ch1=='Y'){

clear();

for(i=0; i < snack.node; i ++)

snack.x[i]=snack.y[i]=-1;

TIME=Time1=Time2=k=0;

score=0;

draw();

snack.life= 0;

break;

} else if(ch 1=='n' || ch1=='N'){

完整程序(续)

endwin();

exit(1);

} else

continue;

}

}

}

完整程序(续)

版权保护: 本文由 李斯特 原创,转载请保留链接: https://www.wechatadd.com/artdet/8399