必经之路,写个乞丐版的贪食蛇

来源:互联网 发布:七天网络查分登录app 编辑:程序博客网 时间:2024/04/28 09:45

//无聊写了个简化版的贪食蛇,基本测试通过,编译加上  -lncurses

//移动和接受键盘信号同时进行的问题,采用非阻塞的getch()模式就可以解决


#include<curses.h>
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<map>
#include<set>
#include<cstdlib>
#include<string>
#include<unistd.h>
#include<math.h>
#include<signal.h>
#include<fcntl.h>
#include<time.h>




using namespace::std;
struct dir_pos
{
int yPos;
int xPos;
int direction;
}head_dir_pos;


struct ele_pos
{
int ele_ypos;
int ele_xpos;
bool operator<(const ele_pos&) const;
bool operator==(const ele_pos &) const;


};
bool ele_pos::operator<(const ele_pos& aa) const
{
return aa.ele_ypos*1000+aa.ele_xpos<ele_ypos*1000+ele_xpos;
}
bool ele_pos::operator==(const ele_pos& aa) const
{
return ele_ypos*1000+ele_xpos==aa.ele_ypos*1000+aa.ele_xpos;
}


int status=0;
int move_status=1;
int speed=30;
char sk_ele='*';
int init_sk_len=2;
int init_dir=4;
bool no_food=TRUE;
bool eat_food=FALSE;
//string user="null";
ele_pos food_pos;


vector<struct ele_pos> snake;
vector<int> whole_scr;


ofstream score_record_file("record.txt",ios::app);


void init_sk(int,int);
void move_snake(int);
void draw_snake(vector<ele_pos>);
void int2string(int &,string &);
int check_alive(vector<ele_pos>);
struct ele_pos create_food();
void game_over();
map<int,int> trans_key_value;


int main(){
// map<int,int> trans_key_value;

trans_key_value[258]=3;
trans_key_value[259]=1;
trans_key_value[260]=2;
trans_key_value[261]=4;
srand((int)time(0));
INIT:
initscr();
box(stdscr,ACS_VLINE,ACS_HLINE);


keypad(stdscr,true);
noecho();
nodelay(stdscr,1);
curs_set(0);
for(int i=2;i<LINES-1;i++){
for(int j=2;j<COLS-1;j++){
int a=i*1000+j;
whole_scr.push_back(a);
}
}
// create_food(LINES,COLS);
// down:258  up:259   left:260    right:261

//mvprintw(LINES/3,COLS/2,"dir_pos=%s",dir_pos.c_str());


mvprintw(2,COLS/2,"p|P:\tpause game");
mvprintw(1,COLS/2,"press any key to start");
nodelay(stdscr,0);
int tmp_a=getch();
clear();
refresh();
init_sk(LINES,COLS);
nodelay(stdscr,1);
move_snake(100);
if(status==1){


clear();
snake.clear();
whole_scr.clear();
status=0;
speed=30;
init_sk_len=2;
init_dir=4;
no_food=TRUE;
eat_food=FALSE;
// mvprintw(LINES/4,COLS/2,"press a");
refresh();
// endwin();
goto INIT;
}
// mvprintw(LINES/3,COLS/2,"cols=%d",COLS);
// END:
// sleep(1);
endwin();
return 0;
}
void game_over(){
clear();
mvprintw(LINES/2,COLS/2,"GAME OVER!");
ifstream infile("record.txt");
string a,b;
while(getline(infile,a)!=NULL){
if(a.size()>b.size()){
b=a;
}else if(a.size()==b.size()){
if(a>b){
b=a;
}
}else{


}
}
int bb=atoi(b.c_str());
string aa;
int2string(init_sk_len,aa);
b=init_sk_len>bb?aa:b;
mvprintw(LINES/2+1,COLS/2,"score:\t%d,\tbest record:\t%s",init_sk_len,b.c_str());
mvprintw(LINES/2+2,COLS/2,"option:");
mvprintw(LINES/2+3,COLS/2,"A/a:\trestart game");
mvprintw(LINES/2+4,COLS/2,"Q/q:\tquit game");
score_record_file<<init_sk_len<<"\n";
refresh();
}
void move_snake(int){
while(1){


usleep(1000000/speed);
int tmp;
tmp=getch();
if(tmp=='Q' || tmp=='q'){
break;
}
if(tmp=='p' || tmp=='P'){
move_status=0;
while(!move_status){
int a=getch();
if(a!='p' && a!='P'){
usleep(1000000/speed);
}else{
move_status=1;
// break;
}
}


}
if(tmp>=258 && tmp<=261){
if((head_dir_pos.direction-trans_key_value[tmp])!=2 && (head_dir_pos.direction-trans_key_value[tmp])!=-2){
head_dir_pos.direction=trans_key_value[tmp];
}
}else{
if(tmp==-1){
goto NORMAL_MOVE;
}
}
NORMAL_MOVE:
ele_pos new_ele,last_ele;
switch(head_dir_pos.direction){
case 4:{
new_ele.ele_xpos=head_dir_pos.xPos+1;
new_ele.ele_ypos=head_dir_pos.yPos; 
break;
}
case 3:{
new_ele.ele_ypos=head_dir_pos.yPos+1;
new_ele.ele_xpos=head_dir_pos.xPos;
break;
}
case 2:{
new_ele.ele_xpos=head_dir_pos.xPos-1;
new_ele.ele_ypos=head_dir_pos.yPos;
break;
}
case 1:{
new_ele.ele_ypos=head_dir_pos.yPos-1;
new_ele.ele_xpos=head_dir_pos.xPos;
break;
}
default:break;
}
for(vector<ele_pos>::iterator ix=snake.begin();ix!=snake.end();ix++){
if(*ix==new_ele){
game_over();
nodelay(stdscr,0);
WAIT:
int tmp2=getch();
switch(tmp2){
case 'q':case 'Q':status=0;break;
case 'a':case 'A':status=1 ;break;
default:status=0;break;
}
break;
}
}
snake.insert(snake.begin(),new_ele);
head_dir_pos.xPos=new_ele.ele_xpos;
head_dir_pos.yPos=new_ele.ele_ypos;
last_ele=*(snake.end()-1);
int tmp_p=last_ele.ele_ypos*1000+last_ele.ele_xpos;


if(head_dir_pos.yPos==food_pos.ele_ypos && head_dir_pos.xPos==food_pos.ele_xpos){
no_food=TRUE;
eat_food=TRUE;
init_sk_len++;
}else{
snake.erase(snake.end()-1);
whole_scr.push_back(tmp_p);
mvaddch(last_ele.ele_ypos,last_ele.ele_xpos,' ');
}
if(no_food){
food_pos=create_food();
mvaddch(food_pos.ele_ypos,food_pos.ele_xpos,'O');
}
if(check_alive(snake)<0){
game_over();
nodelay(stdscr,0);
int tmp2=getch();
switch(tmp2){
case 'q':case 'Q':status=0;endwin();break;
case 'a':case 'A':status=1 ;break;
default:status=0;break;
}
break;
}
draw_snake(snake);
refresh();
usleep(1000000/speed);
}
}
struct ele_pos create_food(){
vector<int>::size_type s_size=whole_scr.size();
srand(int(time(0)));
int a=(int)((rand())%s_size);
ele_pos food;
food.ele_ypos=(int)(whole_scr.at(a)/1000);
food.ele_xpos=whole_scr.at(a)%1000;
no_food=FALSE;
return food;

int check_alive(vector<ele_pos> a){
set<struct ele_pos> exist_eles;
for(vector<ele_pos>::iterator ix=a.begin();ix!=a.end();ix++){
if((*ix).ele_ypos<=0 || (*ix).ele_ypos>=LINES-1 || (*ix).ele_xpos<=0 || (*ix).ele_xpos>=COLS-1 || exist_eles.find(*ix)!=exist_eles.end()){
return -1;
}else{
exist_eles.insert(*ix);
}
}
exist_eles.clear();
return 1;
}
void init_sk(int box_high,int box_width){
int start_pos_y=(int)(rand()%(box_high-30))+15;
int start_pos_x=(int)(rand()%(box_width/2-30))+15;
ele_pos snake_ele;
for(int x_pos=start_pos_x;x_pos!=start_pos_x-2;x_pos--){
snake_ele.ele_xpos=x_pos;
snake_ele.ele_ypos=start_pos_y;
snake.push_back(snake_ele);
}
draw_snake(snake);
int dir=4;
head_dir_pos.direction=dir;
head_dir_pos.yPos=snake[0].ele_ypos;
head_dir_pos.xPos=snake[0].ele_xpos;
}
void draw_snake(vector<ele_pos> a){


for(vector<ele_pos>::iterator ix=a.begin();ix!=a.end();ix++){
int y_tmp=(*ix).ele_ypos;
int x_tmp=(*ix).ele_xpos;
mvaddch(y_tmp,x_tmp,sk_ele);
int tmp=y_tmp*1000+x_tmp;
for(vector<int>::iterator ix2=whole_scr.begin();ix2!=whole_scr.end();ix2++){
if(*ix2==tmp){
whole_scr.erase(ix2);
}
}
}
}
void int2string(int &a,string &b){
stringstream ss;
ss<<a;
b=ss.str();
}
0 0