嗯,这是终结版,虽然还有一些地方不完善,但我感觉也没必要完善。只是纠结于AI的自动寻物还是有问题,桑心。GCC编译命令 gcc -Wall -D_REENTRANT -o "%e" "%f" -lncurses -lpthread
snakeGame.c
1 #include "snakeAI.c" 2 #define CTRL_TIMES 1000 // AI每秒显示的最大步数 3 #define WINDOW_W 40 4 #define WINDOW_H 10 5 int threadtype=-1,threadbool=0; 6 void *threadctrl(void *arg) 7 { 8 noecho(); 9 while(1) 10 { 11 if(threadbool) 12 { 13 switch(getch()) 14 { 15 case 'a': 16 threadtype=0; 17 break; 18 case 'd': 19 threadtype=1; 20 break; 21 case 'w': 22 threadtype=2; 23 break; 24 case 's': 25 threadtype=3; 26 break; 27 case 'q': 28 threadbool=0; 29 threadtype=4; 30 break; 31 default: 32 break; 33 } 34 } 35 } 36 } 37 38 39 int main() 40 { 41 srand((int)time(0)); 42 initscr(); 43 int exitbool = 0; 44 //create_queue(100); 45 /*检查屏幕是否支持彩色功能*/ 46 if(has_colors()) 47 { 48 start_color(); 49 init_pair(10,COLOR_BLACK,COLOR_WHITE);//菜单背景 50 init_pair(11,COLOR_WHITE,COLOR_BLACK);//菜单选中文字 51 init_pair(12,COLOR_WHITE,COLOR_BLACK);//弹出菜单 52 init_pair(20,COLOR_YELLOW,COLOR_BLACK);//食物 53 init_pair(30,COLOR_GREEN,COLOR_BLACK);//蛇通常 54 init_pair(31,COLOR_CYAN,COLOR_BLACK);//蛇变色 55 init_pair(40,COLOR_RED,COLOR_BLACK);//游戏碰撞 56 init_pair(41,COLOR_BLACK,COLOR_BLACK);//游戏背景 57 init_pair(50,COLOR_WHITE,COLOR_RED);//程序出错 58 } 59 60 /*用户控制线程*/ 61 pthread_t a_thread; 62 pthread_create(&a_thread,NULL,threadctrl,(void *)0); 63 charModel cmTEMP[SCR_WIDTH*SCR_HEIGHT]; 64 ctrlModel snakeModel[SCR_WIDTH*SCR_HEIGHT]; 65 ctrlModel foodModel[FOOD_AMOUNT_MAX]; 66 /*菜单选项*/ 67 while(1) 68 { 69 threadbool = 0;//键盘控制游戏-禁止 70 int i = 0,usrctrl[2] = {0,0}; 71 while(1) 72 { 73 attrset(COLOR_PAIR(10)); 74 for(i=0;i<SCR_WIDTH*SCR_HEIGHT;i++) 75 { 76 if( i%SCR_WIDTH == 0|| i%SCR_WIDTH == SCR_WIDTH-1) 77 { 78 cmTEMP[i].chartype='|'; 79 } 80 else if(i/SCR_WIDTH == 0 || i/SCR_WIDTH == SCR_HEIGHT-1) 81 { 82 cmTEMP[i].chartype='-'; 83 } 84 else 85 { 86 cmTEMP[i].type=air; 87 cmTEMP[i].chartype=i%26+65; 88 } 89 } 90 for(i=0;i<WINDOW_W*WINDOW_H;i++) 91 { 92 int sum; 93 sum=(i/WINDOW_W+(SCR_HEIGHT-WINDOW_H)/2)*SCR_WIDTH+(i%WINDOW_W+(SCR_WIDTH-WINDOW_W)/2); 94 if(i%WINDOW_W == 0|| i%WINDOW_W == WINDOW_W-1 || i/WINDOW_W == 0 || i/WINDOW_W == WINDOW_H-1) 95 { 96 cmTEMP[sum].chartype='.'; 97 } 98 else 99 { 100 cmTEMP[sum].chartype='='; 101 } 102 } 103 attrset(COLOR_PAIR(10)); 104 writeLineQ (cmTEMP,0); 105 move((SCR_HEIGHT-WINDOW_H)/2+1,(SCR_WIDTH-WINDOW_W)/2+1); 106 printw(" SnakeGame "); 107 move((SCR_HEIGHT-WINDOW_H)/2+2,(SCR_WIDTH-WINDOW_W)/2+1); 108 printw(" Start SnakeGame "); 109 move((SCR_HEIGHT-WINDOW_H)/2+3,(SCR_WIDTH-WINDOW_W)/2+1); 110 printw(" Watch snakeAI "); 111 move((SCR_HEIGHT-WINDOW_H)/2+4,(SCR_WIDTH-WINDOW_W)/2+1); 112 printw(" About "); 113 move((SCR_HEIGHT-WINDOW_H)/2+5,(SCR_WIDTH-WINDOW_W)/2+1); 114 printw(" EXIT "); 115 move((SCR_HEIGHT-WINDOW_H)/2+7,(SCR_WIDTH-WINDOW_W)/2+1); 116 printw(" Ctrl UP:W DOWN:S Enter:D Quit:Q "); 117 move((SCR_HEIGHT-WINDOW_H)/2+2,(SCR_WIDTH-WINDOW_W)/2+40); 118 attrset(COLOR_PAIR(11)); 119 switch(usrctrl[0]) 120 { 121 case 1: 122 move((SCR_HEIGHT-WINDOW_H)/2+3,(SCR_WIDTH-WINDOW_W)/2+1); 123 printw(" >----Watch snakeAI----< "); 124 break; 125 case 2: 126 move((SCR_HEIGHT-WINDOW_H)/2+4,(SCR_WIDTH-WINDOW_W)/2+1); 127 printw(" >----About----< "); 128 break; 129 case 3: 130 move((SCR_HEIGHT-WINDOW_H)/2+5,(SCR_WIDTH-WINDOW_W)/2+1); 131 printw(" >----EXIT----< "); 132 break; 133 default: 134 move((SCR_HEIGHT-WINDOW_H)/2+2,(SCR_WIDTH-WINDOW_W)/2+1); 135 printw(" >----Start SnakeGame----< "); 136 break; 137 } 138 refresh(); 139 noecho(); 140 switch(getch()) 141 { 142 case 'w': 143 if(usrctrl[0]==0) 144 { 145 usrctrl[0]=3; 146 } 147 else 148 { 149 usrctrl[0]-=1; 150 } 151 break; 152 case 's': 153 if(usrctrl[0]==3) 154 { 155 usrctrl[0]=0; 156 } 157 else 158 { 159 usrctrl[0]+=1; 160 } 161 break; 162 case 'd': 163 if(usrctrl[0]==3) 164 { 165 clear(); 166 exit(1); 167 } 168 else if(usrctrl[0]==1) 169 { 170 usrctrl[1]=1; 171 snakeModel[0].type=right; 172 } 173 else if(usrctrl[0]==2) 174 { 175 /*about*/ 176 } 177 else 178 { 179 usrctrl[1]=2; 180 snakeModel[0].type=stop; 181 } 182 break; 183 } 184 if(usrctrl[1]==1||usrctrl[1]==2) 185 { 186 break; 187 } 188 } 189 190 /*游戏初始化*/ 191 for(i=0;i<SCR_WIDTH*SCR_HEIGHT;i++)//初始化蛇模型 192 { 193 if(i<SNAKE_LENGTH) 194 { 195 snakeModel[i].x= (SCR_WIDTH+SNAKE_LENGTH)/2-i; 196 snakeModel[i].y= SCR_HEIGHT/2-1; 197 if(i!=0) 198 { 199 snakeModel[i].type=stop; 200 } 201 } 202 else 203 { 204 snakeModel[i].type=null; 205 } 206 } 207 for(i=0;i<FOOD_AMOUNT_MAX;i++)//初始化食物 208 { 209 foodModel[i].type=null; 210 } 211 addfood(snakeModel,foodModel,FOOD_AMOUNT_MAX); 212 threadbool=1;//允许键盘控制 213 214 /*游戏主循环*/ 215 while(1) 216 { 217 int bctrlsnake=0; //变色模式控制 218 for(i=0;i<SCR_WIDTH*SCR_HEIGHT;i++) 219 { 220 if( i%SCR_WIDTH == 0|| i%SCR_WIDTH == SCR_WIDTH-1) 221 { 222 cmTEMP[i].type =wall; 223 cmTEMP[i].chartype='|'; 224 } 225 else if(i/SCR_WIDTH == 0 || i/SCR_WIDTH == SCR_HEIGHT-1) 226 { 227 cmTEMP[i].type =wall; 228 cmTEMP[i].chartype='-'; 229 } 230 else 231 { 232 cmTEMP[i].type=air; 233 cmTEMP[i].chartype=' '; 234 } 235 } 236 removSnake(snakeModel); //移动蛇 237 /*添加食物图形*/ 238 for(i=0;i<FOOD_AMOUNT_MAX;i++) 239 { 240 if(foodModel[i].type==null) 241 continue; 242 int sum; 243 sum=foodModel[i].x+foodModel[i].y*SCR_WIDTH; 244 cmTEMP[sum].type = food; 245 cmTEMP[sum].chartype=FOOD_CHAR; 246 } 247 /*碰撞处理*/ 248 int retdeal=collidedeal(cmTEMP,snakeModel); 249 if(retdeal==1) 250 { 251 addsnakemod(snakeModel,1); 252 for(i=0;i<FOOD_AMOUNT_MAX;i++) 253 { 254 if(foodModel[i].x==snakeModel[0].x && foodModel[i].y==snakeModel[0].y) 255 { 256 foodModel[i].type=null; 257 } 258 } 259 addfood(snakeModel,foodModel,FOOD_AMOUNT_MAX); 260 bctrlsnake=1; //变色 261 } 262 else if(retdeal==2) 263 { 264 for(i=0;i<5;i++) 265 { 266 move(SCR_HEIGHT/2-1,SCR_WIDTH/2-5); 267 attrset(COLOR_PAIR(40)); 268 printw("GAME OVER! %d...",5-i); 269 refresh(); 270 sleep(1); 271 } 272 for(i=0;i<SCR_WIDTH*SCR_HEIGHT;i++) 273 { 274 if(i<SNAKE_LENGTH) 275 { 276 snakeModel[i].x= (SCR_WIDTH+SNAKE_LENGTH)/2-i; 277 snakeModel[i].y= SCR_HEIGHT/2-1; 278 snakeModel[i].type=stop; 279 } 280 else 281 { 282 snakeModel[i].type=null; 283 } 284 } 285 for(i=0;i<FOOD_AMOUNT_MAX;i++) 286 { 287 foodModel[i].type=null; 288 } 289 addfood(snakeModel,foodModel,FOOD_AMOUNT_MAX); 290 if(usrctrl[1]==1) 291 { 292 snakeModel[0].type=right; 293 } 294 else 295 { 296 snakeModel[0].type=stop; 297 } 298 continue; 299 } 300 else if(retdeal==-1) 301 { 302 program_error("Collidedeal type NULL"); 303 } 304 /*关卡等级及游戏速度控制 并未实现*/ 305 for(i=0;i<SCR_WIDTH*SCR_HEIGHT;i++) //添加蛇模型 306 { 307 if(snakeModel[i].type==null) 308 { 309 break; 310 } 311 int sum; 312 sum=snakeModel[i].x+snakeModel[i].y*SCR_WIDTH; 313 cmTEMP[sum].type = wall; 314 cmTEMP[sum].chartype=SNAKE_CHAR; 315 if(i==0) 316 { 317 switch(snakeModel[0].type) 318 { 319 case left: 320 cmTEMP[sum].chartype='<'; 321 break; 322 case right: 323 cmTEMP[sum].chartype='>'; 324 break; 325 case up: 326 cmTEMP[sum].chartype='^'; 327 break; 328 case down: 329 cmTEMP[sum].chartype='+'; 330 break; 331 case stop: 332 cmTEMP[sum].chartype='@'; 333 break; 334 case null: 335 program_error("SnakeModel[0] type NULL"); 336 default: 337 program_error("SnakeModel[0] type =?"); 338 } 339 } 340 } 341 /*玩家控制或者自动AI 即菜单选项1和2 */ 342 if(usrctrl[1]==1) 343 { 344 if(bctrlsnake==1) 345 { 346 writeLineQ (cmTEMP,5); 347 } 348 else 349 { 350 writeLineQ (cmTEMP,1); 351 } 352 snakeModel[0].type=EatAI(cmTEMP,snakeModel,foodModel); 353 } 354 else 355 { 356 if(bctrlsnake==1) 357 { 358 writeLineQ (cmTEMP,4); 359 } 360 else 361 { 362 writeLineQ (cmTEMP,2); 363 } 364 switch(threadtype) 365 { 366 case stop: 367 case left: 368 case up: 369 case down: 370 case right: 371 snakeModel[0].type=threadtype; 372 break; 373 case 4: 374 exitbool = 1; 375 break; 376 default: 377 break; 378 } 379 } 380 if(exitbool == 1) 381 { 382 exitbool = 0; 383 break; 384 } 385 } 386 } 387 endwin(); 388 exit(EXIT_SUCCESS); 389 } 390 391 void ctrltimes() 392 { 393 static int a=0; 394 a+=1; 395 if(a==CTRL_TIMES) 396 { 397 sleep(1); 398 a=0; 399 } 400 } 401 402 void writeLineQ(charModel cmTEMP[],int bctrltime) 403 { 404 int i; 405 for(i=0;i<SCR_WIDTH*SCR_HEIGHT;i++) 406 { 407 move(i/SCR_WIDTH,i%SCR_WIDTH); 408 switch(cmTEMP[i].chartype) 409 { 410 case '+': 411 case '<': 412 case '>': 413 case '^': 414 case '@': 415 case SNAKE_CHAR: 416 if(bctrltime==4||bctrltime==5) 417 { 418 attrset(COLOR_PAIR(31)); 419 } 420 else 421 { 422 attrset(COLOR_PAIR(30)); 423 } 424 break; 425 case FOOD_CHAR: 426 attrset(COLOR_PAIR(20)); 427 break; 428 case '|': 429 case '-': 430 attrset(COLOR_PAIR(10)); 431 break; 432 case '.': 433 attrset(COLOR_PAIR(10)); 434 break; 435 case '=': 436 attrset(COLOR_PAIR(10)); 437 break; 438 default: 439 attrset(COLOR_PAIR(41)); 440 break; 441 442 } 443 addch((cmTEMP[i]).chartype); 444 } 445 refresh(); 446 switch(bctrltime) 447 { 448 case 1: 449 ctrltimes(); 450 break; 451 case 2: 452 case 5: 453 sleep(1); 454 break; 455 case 0: 456 case 4: 457 break; 458 default: 459 program_error("WriteLineQ bctrltime '=?'"); 460 } 461 } 462 void removSnake(ctrlModel snakeModel[]) 463 { 464 int i; 465 if( snakeModel[0].type==stop) 466 { 467 return; 468 } 469 for(i=0;i<SCR_WIDTH*SCR_HEIGHT;i++) 470 { 471 int nxtemp,nytemp,nttemp,xtemp,ytemp,ttemp; 472 if(snakeModel[i].type==null) 473 { 474 return; 475 } 476 nxtemp=snakeModel[i].x; 477 nytemp=snakeModel[i].y; 478 nttemp=snakeModel[i].type; 479 if(i==0) 480 { 481 xtemp=nxtemp; 482 ytemp=nytemp; 483 ttemp=nttemp; 484 switch(snakeModel[i].type) 485 { 486 case left: 487 snakeModel[i].x -=1; 488 break; 489 case right: 490 snakeModel[i].x +=1; 491 break; 492 case up: 493 snakeModel[i].y -=1; 494 break; 495 case down: 496 snakeModel[i].y +=1; 497 break; 498 default: 499 break; 500 } 501 } 502 else 503 { 504 snakeModel[i].x=xtemp; 505 snakeModel[i].y=ytemp; 506 snakeModel[i].type=ttemp; 507 xtemp=nxtemp; 508 ytemp=nytemp; 509 ttemp=nttemp; 510 } 511 } 512 } 513 514 void fallremovSnake(ctrlModel snakeModel[]) 515 { 516 int i,ctrls; 517 for(i=SCR_WIDTH*SCR_HEIGHT-1;i>=0;i--) 518 { 519 int nxtemp,nytemp,nttemp,xtemp,ytemp,ttemp; 520 if(snakeModel[i].type==null) 521 { 522 ctrls = 1; 523 continue; 524 } 525 nxtemp=snakeModel[i].x; 526 nytemp=snakeModel[i].y; 527 nttemp=snakeModel[i].type; 528 if(ctrls == 1) 529 { 530 xtemp=snakeModel[i].x; 531 ytemp=snakeModel[i].y; 532 ttemp=snakeModel[i].type; 533 switch(snakeModel[i].type) 534 { 535 case left: 536 snakeModel[i].x +=1; 537 break; 538 case right: 539 snakeModel[i].x -=1; 540 break; 541 case up: 542 snakeModel[i].y +=1; 543 break; 544 case down: 545 snakeModel[i].y -=1; 546 break; 547 default: 548 break; 549 } 550 ctrls = 0 ; 551 } 552 else 553 { 554 snakeModel[i].x=xtemp; 555 snakeModel[i].y=ytemp; 556 snakeModel[i].type=ttemp; 557 xtemp=nxtemp; 558 ytemp=nytemp; 559 ttemp=nttemp; 560 } 561 } 562 } 563 564 int collidedeal(charModel cmTEMP[],ctrlModel snakeModel[]) 565 { 566 int i; 567 for(i=1;i<=SCR_WIDTH*SCR_HEIGHT;i++) 568 { 569 if(snakeModel[i].type==null) 570 { 571 break; 572 } 573 if(snakeModel[0].x==snakeModel[i].x && snakeModel[0].y==snakeModel[i].y) 574 { 575 return 2; 576 } 577 } 578 int sum; 579 sum=snakeModel[0].x+snakeModel[0].y*SCR_WIDTH; 580 switch(cmTEMP[sum].type) 581 { 582 case air: 583 return 0; 584 case food: 585 return 1; 586 case wall: 587 return 2; 588 default: 589 return -1; 590 } 591 } 592 593 void addfood(ctrlModel snakeModel[],ctrlModel foodModel[],int amount) 594 { 595 596 int i; 597 for(i=0;i<amount;i++) 598 { 599 if(foodModel[i].type!=null) 600 { 601 return; 602 } 603 } 604 for(i=0;i<amount;i++) 605 { 606 int x,y,randx; 607 do 608 { 609 randx=rand(); 610 }while(randx>=SCR_WIDTH*SCR_HEIGHT); 611 x=randx%SCR_WIDTH;y=randx/SCR_WIDTH; 612 if(x!=0 && y!=0 && x!= SCR_WIDTH-1 && y!=SCR_HEIGHT-1) 613 { 614 int times,ctrlbool=0; 615 for(times=0;times<SCR_WIDTH*SCR_WIDTH;times++) 616 { 617 if(snakeModel[times].type==null) 618 { 619 break; 620 } 621 else if(snakeModel[times].x==x && snakeModel[times].y==y) 622 { 623 ctrlbool=-1; 624 break; 625 } 626 } 627 if(ctrlbool==-1) 628 { 629 i--; 630 } 631 else 632 { 633 foodModel[i].x=x; 634 foodModel[i].y=y; 635 foodModel[i].type=stop; 636 } 637 638 } 639 else 640 { 641 i--; 642 } 643 } 644 } 645 646 void addsnakemod(ctrlModel snakeModel[],int amount) 647 { 648 int i,times; 649 for(i=0;i<SCR_WIDTH*SCR_HEIGHT;i++) 650 { 651 if( snakeModel[i].type==null) 652 { 653 for(times=0;times<amount;times++) 654 { 655 snakeModel[i+times].type=stop; 656 switch(snakeModel[i+times-1].type) 657 { 658 659 case left: 660 snakeModel[i+times].x=snakeModel[i+times-1].x+1; 661 snakeModel[i+times].y=snakeModel[i+times-1].y; 662 break; 663 case right: 664 snakeModel[i+times].x=snakeModel[i+times-1].x-1; 665 snakeModel[i+times].y=snakeModel[i+times-1].y; 666 break; 667 case up: 668 snakeModel[i+times].x=snakeModel[i+times-1].x; 669 snakeModel[i+times].y=snakeModel[i+times-1].y+1; 670 break; 671 case down: 672 snakeModel[i+times].x=snakeModel[i+times-1].x; 673 snakeModel[i+times].y=snakeModel[i+times-1].y-1; 674 break; 675 default: 676 break; 677 } 678 } 679 return; 680 } 681 } 682 } 683 684 void program_error(char error_string[]) 685 { 686 attrset(COLOR_PAIR(50)); 687 int i; 688 for(i=0;i<SCR_WIDTH*SCR_HEIGHT;i++) 689 { 690 move(i/SCR_WIDTH,i%SCR_WIDTH); 691 addch(' '); 692 } 693 move(SCR_HEIGHT/2,0); 694 printw("*** (ERROR) \"%s\"",error_string); 695 refresh(); 696 sleep(5); 697 exit(0); 698 }
snakeAI.c
1 #include "snakeHead.h" 2 3 int calculate(charModel cmTEMP[],ctrlModel snakeModel[],int direction); 4 movtype DirectionAlt(movtype type,int direction) 5 { 6 int irand; 7 switch(direction) 8 { 9 case 1: 10 return type; 11 case 2: 12 switch(type) 13 { 14 case left: 15 return down; 16 case right: 17 return up; 18 case up: 19 return left; 20 case down: 21 return right; 22 default: 23 return stop; 24 } 25 case 4: 26 switch(type) 27 { 28 case left: 29 return up; 30 case right: 31 return down; 32 case up: 33 return right; 34 case down: 35 return left; 36 default: 37 return stop; 38 } 39 case 3://随即选定一个方向 40 case 5: 41 irand=rand(); 42 irand=irand%2; 43 if(irand==0) 44 { 45 return type; 46 } 47 else 48 { 49 return DirectionAlt(type,direction-1); 50 } 51 case 6://随即选定一个方向 52 irand=rand(); 53 irand=irand%2; 54 if(irand==0) 55 { 56 return DirectionAlt(type,2); 57 } 58 else 59 { 60 return DirectionAlt(type,4); 61 } 62 case 7://随即选定一个方向 63 irand=rand(); 64 irand=irand%3; 65 if(irand==0) 66 { 67 return type; 68 } 69 else if(irand==1) 70 { 71 return DirectionAlt(type,2); 72 } 73 else 74 { 75 return DirectionAlt(type,4); 76 } 77 default: 78 return stop; 79 } 80 } 81 82 movtype EatAI(charModel cmTEMP[],ctrlModel snakeModel[],ctrlModel foodModel[]) 83 { 84 int ix,iy,i,foodamount[FOOD_AMOUNT_MAX],distance=SCR_WIDTH*SCR_HEIGHT,numfood[2]; 85 86 /*寻找头部周围的身体*/ 87 int headbar[4]={0,0,0,0};//[0]左 [1]右 [2]上 [3]下 88 for(i=1;i<SCR_WIDTH*SCR_HEIGHT;i++) 89 { 90 if(snakeModel[i].type==null) 91 { 92 break; 93 } 94 else if(snakeModel[i].x==snakeModel[0].x) 95 { 96 if(snakeModel[i].y==snakeModel[0].y-1) 97 { 98 headbar[2]=1; 99 } 100 else if(snakeModel[i].y==snakeModel[0].y+1) 101 { 102 headbar[3]=1; 103 } 104 } 105 else if(snakeModel[i].y==snakeModel[0].y) 106 { 107 if(snakeModel[i].x==snakeModel[0].x-1) 108 { 109 headbar[0]=1; 110 } 111 else if(snakeModel[i].x==snakeModel[0].x+1) 112 { 113 headbar[1]=1; 114 } 115 } 116 } 117 int direction=7; //1为向前 2为向左 4为向右 ,1+2 1+4 2+4 1+2+4 方向组合 118 119 /*排除算法 排除墙体和身体碰撞*/ 120 switch(snakeModel[0].type) 121 { 122 case left: 123 if(cmTEMP[(snakeModel[0].x-1)+snakeModel[0].y*60].type==wall || headbar[0]==1) 124 { 125 direction-=1; 126 } 127 if(cmTEMP[(snakeModel[0].x)+(snakeModel[0].y+1)*60].type==wall || headbar[3]==1) 128 { 129 direction-=2; 130 } 131 if(cmTEMP[(snakeModel[0].x)+(snakeModel[0].y-1)*60].type==wall || headbar[2]==1) 132 { 133 direction-=4; 134 } 135 break; 136 case right: 137 if(cmTEMP[(snakeModel[0].x+1)+snakeModel[0].y*60].type==wall || headbar[1]==1) 138 { 139 direction-=1; 140 } 141 if(cmTEMP[(snakeModel[0].x)+(snakeModel[0].y-1)*60].type==wall || headbar[2]==1) 142 { 143 direction-=2; 144 } 145 if(cmTEMP[(snakeModel[0].x)+(snakeModel[0].y+1)*60].type==wall || headbar[3]==1) 146 { 147 direction-=4; 148 } 149 break; 150 case up: 151 if(cmTEMP[snakeModel[0].x+(snakeModel[0].y-1)*60].type==wall || headbar[2]==1) 152 { 153 direction-=1; 154 } 155 if(cmTEMP[(snakeModel[0].x-1)+snakeModel[0].y*60].type==wall || headbar[0]==1) 156 { 157 direction-=2; 158 } 159 if(cmTEMP[(snakeModel[0].x+1)+snakeModel[0].y*60].type==wall || headbar[1]==1) 160 { 161 direction-=4; 162 } 163 break; 164 case down: 165 if(cmTEMP[snakeModel[0].x+(snakeModel[0].y+1)*60].type==wall || headbar[3]==1) 166 { 167 direction-=1; 168 } 169 if(cmTEMP[(snakeModel[0].x+1)+snakeModel[0].y*60].type==wall || headbar[1]==1) 170 { 171 direction-=2; 172 } 173 if(cmTEMP[(snakeModel[0].x-1)+snakeModel[0].y*60].type==wall || headbar[0]==1) 174 { 175 direction-=4; 176 } 177 break; 178 case stop: 179 default: 180 return stop; 181 } 182 183 /*走投无路,自我毁灭*/ 184 if(direction==0){ 185 return snakeModel[0].type;} 186 187 /*带深度递归,检验方向可行性,防止自我封闭*/ 188 if(direction!=1 && direction!=2 && direction!=4) 189 { 190 direction=calculate(cmTEMP,snakeModel,direction); 191 } 192 193 /*自动寻物*/ 194 for(i=0;i<FOOD_AMOUNT_MAX;i++)//取相对距离,并选取最小值 195 { 196 if(foodModel[i].type==null) 197 { 198 continue; 199 } 200 ix=snakeModel[0].x-foodModel[i].x;iy=snakeModel[0].y-foodModel[i].y; 201 foodamount[i]=ix*ix+iy*iy;//平面两点坐标公式 x^2+y^2 202 if(distance>foodamount[i]) 203 { 204 numfood[0]=foodModel[i].x; 205 numfood[1]=foodModel[i].y; 206 distance=foodamount[i]; 207 } 208 } 209 /*创建寻物方向*/ 210 int fooddirection=0,subx=snakeModel[0].x-numfood[0],suby=snakeModel[0].y-numfood[1]; 211 if(subx == 0) 212 { 213 if(suby < 0) 214 { 215 switch(snakeModel[0].type) 216 { 217 case left: 218 fooddirection+=2; 219 break; 220 case right: 221 fooddirection+=4; 222 break; 223 case up: 224 fooddirection+=6; 225 break; 226 case down: 227 fooddirection+=1; 228 break; 229 default: 230 break; 231 } 232 } 233 else if(suby > 0) 234 { 235 switch(snakeModel[0].type) 236 { 237 case left: 238 fooddirection+=4; 239 break; 240 case right: 241 fooddirection+=2; 242 break; 243 case up: 244 fooddirection+=1; 245 break; 246 case down: 247 fooddirection+=6; 248 break; 249 default: 250 break; 251 } 252 } 253 } 254 else if(subx<0) 255 { 256 if(suby== 0) 257 { 258 switch(snakeModel[0].type) 259 { 260 case left: 261 fooddirection+=6; 262 break; 263 case right: 264 fooddirection+=1; 265 break; 266 case up: 267 fooddirection+=4; 268 break; 269 case down: 270 fooddirection+=2; 271 break; 272 default: 273 break; 274 } 275 } 276 else if(suby < 0) 277 { 278 switch(snakeModel[0].type) 279 { 280 case left: 281 fooddirection+=2; 282 break; 283 case right: 284 fooddirection+=5; 285 break; 286 case up: 287 fooddirection+=4; 288 break; 289 case down: 290 fooddirection+=3; 291 break; 292 default: 293 break; 294 } 295 } 296 else{ 297 switch(snakeModel[0].type) 298 { 299 case left: 300 fooddirection+=4; 301 break; 302 case right: 303 fooddirection+=3; 304 break; 305 case up: 306 fooddirection+=5; 307 break; 308 case down: 309 fooddirection+=2; 310 break; 311 default: 312 break; 313 } 314 } 315 } 316 else{ 317 if(suby== 0) 318 { 319 switch(snakeModel[0].type) 320 { 321 case left: 322 fooddirection+=1; 323 break; 324 case right: 325 fooddirection+=6; 326 break; 327 case up: 328 fooddirection+=2; 329 break; 330 case down: 331 fooddirection+=4; 332 break; 333 default: 334 break; 335 } 336 } 337 else if(suby < 0) 338 { 339 switch(snakeModel[0].type) 340 { 341 case left: 342 fooddirection+=3; 343 break; 344 case right: 345 fooddirection+=4; 346 break; 347 case up: 348 fooddirection+=2; 349 break; 350 case down: 351 fooddirection+=5; 352 break; 353 default: 354 break; 355 } 356 } 357 else{ 358 switch(snakeModel[0].type) 359 { 360 case left: 361 fooddirection+=5; 362 break; 363 case right: 364 fooddirection+=2; 365 break; 366 case up: 367 fooddirection+=3; 368 break; 369 case down: 370 fooddirection+=4; 371 break; 372 default: 373 break; 374 } 375 } 376 } 377 switch(direction) 378 { 379 case 1: 380 return snakeModel[0].type; 381 case 2: 382 case 4: 383 return DirectionAlt(snakeModel[0].type,direction); 384 case 7://前左右 385 return DirectionAlt(snakeModel[0].type,fooddirection); 386 case 6://左右 387 if(fooddirection>=direction || fooddirection==1) 388 { 389 return DirectionAlt(snakeModel[0].type,6); 390 } 391 else if(fooddirection==2 || fooddirection==4) 392 { 393 return DirectionAlt(snakeModel[0].type,fooddirection); 394 } 395 else if(fooddirection==3 || fooddirection==5) 396 { 397 return DirectionAlt(snakeModel[0].type,fooddirection-1); 398 } 399 case 3://前左 400 if(fooddirection<=3) 401 { 402 return DirectionAlt(snakeModel[0].type,fooddirection); 403 } 404 else if(fooddirection==5||fooddirection==6) 405 { 406 return DirectionAlt(snakeModel[0].type,fooddirection-4); 407 } 408 else if(fooddirection==4||fooddirection==7) 409 { 410 return DirectionAlt(snakeModel[0].type,3); 411 } 412 case 5://前右 413 if(fooddirection==5||fooddirection==7) 414 { 415 return DirectionAlt(snakeModel[0].type,5); 416 } 417 else if(fooddirection<=3) 418 { 419 return DirectionAlt(snakeModel[0].type,1); 420 } 421 else if(fooddirection==4||fooddirection==6) 422 { 423 return DirectionAlt(snakeModel[0].type,4); 424 } 425 default: 426 return stop; 427 } 428 } 429 430 /*自动寻物递归精简版本*/ 431 movtype ToWhy(charModel cmTEMP[],ctrlModel snakeModel[]) 432 { 433 int i; 434 int headbar[4]={0,0,0,0}; 435 for(i=1;i<SCR_WIDTH*SCR_HEIGHT;i++) 436 { 437 if(snakeModel[i].type==null) 438 { 439 break; 440 } 441 else if(snakeModel[i].x==snakeModel[0].x) 442 { 443 if(snakeModel[i].y==snakeModel[0].y-1) 444 { 445 headbar[2]=1; 446 } 447 else if(snakeModel[i].y==snakeModel[0].y+1) 448 { 449 headbar[3]=1; 450 } 451 } 452 else if(snakeModel[i].y==snakeModel[0].y) 453 { 454 if(snakeModel[i].x==snakeModel[0].x-1) 455 { 456 headbar[0]=1; 457 } 458 else if(snakeModel[i].x==snakeModel[0].x+1) 459 { 460 headbar[1]=1; 461 } 462 } 463 } 464 int direction=7; //1为向前 2为向左 4为向右 ,1+2 1+4 2+4 1+2+4 方向组合 465 switch(snakeModel[0].type) 466 { 467 case left: 468 if(cmTEMP[(snakeModel[0].x-1)+snakeModel[0].y*60].type==wall || headbar[0]==1) 469 { 470 direction-=1; 471 } 472 if(cmTEMP[(snakeModel[0].x)+(snakeModel[0].y+1)*60].type==wall || headbar[3]==1) 473 { 474 direction-=2; 475 } 476 if(cmTEMP[(snakeModel[0].x)+(snakeModel[0].y-1)*60].type==wall || headbar[2]==1) 477 { 478 direction-=4; 479 } 480 break; 481 case right: 482 if(cmTEMP[(snakeModel[0].x+1)+snakeModel[0].y*60].type==wall || headbar[1]==1) 483 { 484 direction-=1; 485 } 486 if(cmTEMP[(snakeModel[0].x)+(snakeModel[0].y-1)*60].type==wall || headbar[2]==1) 487 { 488 direction-=2; 489 } 490 if(cmTEMP[(snakeModel[0].x)+(snakeModel[0].y+1)*60].type==wall || headbar[3]==1) 491 { 492 direction-=4; 493 } 494 break; 495 case up: 496 if(cmTEMP[snakeModel[0].x+(snakeModel[0].y-1)*60].type==wall || headbar[2]==1) 497 { 498 direction-=1; 499 } 500 if(cmTEMP[(snakeModel[0].x-1)+snakeModel[0].y*60].type==wall || headbar[0]==1) 501 { 502 direction-=2; 503 } 504 if(cmTEMP[(snakeModel[0].x+1)+snakeModel[0].y*60].type==wall || headbar[1]==1) 505 { 506 direction-=4; 507 } 508 break; 509 case down: 510 if(cmTEMP[snakeModel[0].x+(snakeModel[0].y+1)*60].type==wall || headbar[3]==1) 511 { 512 direction-=1; 513 } 514 if(cmTEMP[(snakeModel[0].x+1)+snakeModel[0].y*60].type==wall || headbar[1]==1) 515 { 516 direction-=2; 517 } 518 if(cmTEMP[(snakeModel[0].x-1)+snakeModel[0].y*60].type==wall || headbar[0]==1) 519 { 520 direction-=4; 521 } 522 break; 523 case stop: 524 default: 525 return stop; 526 } 527 return direction; 528 } 529 530 int depthrecurrence(charModel charTEMP[],ctrlModel TEMP_snake[],int depth,int direction,int DIR[]) 531 { 532 if(depth <= 0) 533 { 534 return 0; 535 } 536 int x,y,z; 537 switch(direction) 538 { 539 case 0: 540 return 1; 541 case 1: 542 TEMP_snake[0].type = DirectionAlt(TEMP_snake[0].type,1); 543 removSnake(TEMP_snake); 544 DIR[1] = depthrecurrence(charTEMP,TEMP_snake,depth-1,ToWhy(charTEMP,TEMP_snake),DIR) + DIR[1]; 545 fallremovSnake(TEMP_snake); 546 return DIR[1]; 547 case 2: 548 TEMP_snake[0].type=DirectionAlt(TEMP_snake[0].type,2); 549 removSnake(TEMP_snake); 550 DIR[2] = depthrecurrence(charTEMP,TEMP_snake,depth-1,ToWhy(charTEMP,TEMP_snake),DIR) + DIR[2]; 551 fallremovSnake(TEMP_snake); 552 return DIR[2]; 553 case 3: 554 x = depthrecurrence(charTEMP,TEMP_snake,depth-1,1,DIR); 555 y = depthrecurrence(charTEMP,TEMP_snake,depth-1,2,DIR); 556 if(x>=y){DIR[3] = x + 1;}else{DIR[3] = y + 1;} 557 return DIR[3]; 558 case 4: 559 TEMP_snake[0].type=DirectionAlt(TEMP_snake[0].type,4); 560 removSnake(TEMP_snake); 561 DIR[4] = depthrecurrence(charTEMP,TEMP_snake,depth-1,ToWhy(charTEMP,TEMP_snake),DIR) + DIR[2]; 562 fallremovSnake(TEMP_snake); 563 return DIR[4]; 564 case 5: 565 x = depthrecurrence(charTEMP,TEMP_snake,depth-1,1,DIR); 566 y = depthrecurrence(charTEMP,TEMP_snake,depth-1,4,DIR); 567 if(x>=y){DIR[5] = x + 1;}else{DIR[5] = y + 1;} 568 return DIR[5]; 569 case 6: 570 DIR[6] += 1; 571 x = depthrecurrence(charTEMP,TEMP_snake,depth-1,2,DIR); 572 y = depthrecurrence(charTEMP,TEMP_snake,depth-1,4,DIR); 573 if(x>=y){DIR[6] = x + 1;}else{DIR[6] = y + 1;} 574 return DIR[6]; 575 case 7: 576 DIR[7] += 1; 577 x = depthrecurrence(charTEMP,TEMP_snake,depth-1,1,DIR); 578 y = depthrecurrence(charTEMP,TEMP_snake,depth-1,2,DIR); 579 z = depthrecurrence(charTEMP,TEMP_snake,depth-1,4,DIR); 580 if(x>=y) 581 { 582 if(x>=z){DIR[7] = x + 1;}else{DIR[7] = z + 1;} 583 } 584 else 585 { 586 if(y>=z){DIR[7] = y + 1;}else{DIR[7] = z + 1;} 587 } 588 return DIR[7]; 589 default: 590 program_error("Direction type =?"); 591 return -1; 592 593 } 594 } 595 596 int calculate(charModel cmTEMP[],ctrlModel snakeModel[],int direction) 597 { 598 int i,x; 599 int DIR[8]={0,0,0,0,0,0,0,0}; 600 DIR[8]=direction; 601 ctrlModel TEMP_snake[SCR_WIDTH*SCR_HEIGHT]; 602 for(i = 0; i<SCR_WIDTH*SCR_HEIGHT; i++) 603 { 604 if(snakeModel[i].type == null) 605 { 606 break; 607 } 608 TEMP_snake[i]=snakeModel[i]; 609 } 610 depthrecurrence(cmTEMP,TEMP_snake,SNAKEAI_DEPTH,direction,DIR); 611 x=DIR[0]; 612 for(i = 1;i<=6;i++) 613 { 614 if(x<=DIR[i+1]) 615 { 616 x=DIR[i+1]; 617 DIR[8] = i+1; 618 } 619 } 620 switch(direction) 621 { 622 case 7: 623 break; 624 case 3: 625 if(DIR[8] == 1 || DIR[8] == 2 || DIR[8] == 3){break;} 626 else{DIR[8] = direction;} 627 break; 628 case 5: 629 if(DIR[8] == 1 || DIR[8] == 4 || DIR[8] == 5){break;} 630 else{DIR[8] = direction;} 631 break; 632 case 6: 633 if(DIR[8] == 2 || DIR[8] == 4 || DIR[8] == 6){break;} 634 else{DIR[8] = direction;} 635 break; 636 case 1: 637 case 2: 638 case 4: 639 DIR[8] = direction; 640 break; 641 default: 642 DIR[8] = direction; 643 break; 644 } 645 646 647 return DIR[8]; 648 } 649 650 651 652 //~ int closegraph(charModel cmTEMP[],ctrlModel snakeModel[],int direction) 653 //~ { 654 //~ /*检测是否为闭合图形 1 蛇模型闭合 2 蛇模型+边界闭合 (沒有实现)*/ 655 //~ int i; 656 //~ for(i=SCR_WIDTH*SCR_HEIGHT-1;i>=0;i--)//从蛇尾到倒找 657 //~ { 658 //~ if(snakeModel[i].type==null) 659 //~ { 660 //~ continue; 661 //~ } 662 //~ if(i==2) 663 //~ { 664 //~ return direction; 665 //~ } 666 //~ if(snakeModel[i].x-1==snakeModel[0].x && snakeModel[i].y-1==snakeModel[0].y){break;} 667 //~ if(snakeModel[i].x-1==snakeModel[0].x && snakeModel[i].y==snakeModel[0].y){break;} 668 //~ if(snakeModel[i].x-1==snakeModel[0].x && snakeModel[i].y+1==snakeModel[0].y){break;} 669 //~ if(snakeModel[i].x==snakeModel[0].x && snakeModel[i].y-1==snakeModel[0].y){break;} 670 //~ if(snakeModel[i].x==snakeModel[0].x && snakeModel[i].y+1==snakeModel[0].y){break;} 671 //~ if(snakeModel[i].x+1==snakeModel[0].x && snakeModel[i].y-1==snakeModel[0].y){break;} 672 //~ if(snakeModel[i].x+1==snakeModel[0].x && snakeModel[i].y==snakeModel[0].y){break;} 673 //~ if(snakeModel[i].x+1==snakeModel[0].x && snakeModel[i].y+1==snakeModel[0].y){break;} 674 //~ } 675 //~ /*如果结点为末尾无视*/ 676 //~ if(snakeModel[i+1].type==null){return direction;} 677 //~ /*判断前结点方向*/ 678 //~ movtype direfalse[2]={null,null}; 679 //~ if(snakeModel[i-1].x==snakeModel[i].x) 680 //~ { 681 //~ if(snakeModel[i-1].y-snakeModel[i].y==1) 682 //~ { 683 //~ direfalse[0]=down; 684 //~ } 685 //~ else 686 //~ { 687 //~ direfalse[0]=up; 688 //~ } 689 //~ } 690 //~ else if(snakeModel[i-1].y==snakeModel[i].y) 691 //~ { 692 //~ if(snakeModel[i-1].x-snakeModel[i].x==-1) 693 //~ { 694 //~ direfalse[0]=left; 695 //~ } 696 //~ else 697 //~ { 698 //~ direfalse[0]=right; 699 //~ } 700 //~ } 701 //~ /*判断后结点方向*/ 702 //~ if(snakeModel[i].x==snakeModel[i+1].x) 703 //~ { 704 //~ if(snakeModel[i].y-snakeModel[i+1].y==1) 705 //~ { 706 //~ direfalse[1]=down; 707 //~ } 708 //~ else 709 //~ { 710 //~ direfalse[1]=up; 711 //~ } 712 //~ } 713 //~ else if(snakeModel[i].y==snakeModel[i+1].y) 714 //~ { 715 //~ if(snakeModel[i].x-snakeModel[i+1].x==-1) 716 //~ { 717 //~ direfalse[1]=left; 718 //~ } 719 //~ else 720 //~ { 721 //~ direfalse[1]=right; 722 //~ } 723 //~ } 724 //~ /*方向*/ 725 //~ for(i=0;i<2;i++) 726 //~ { 727 //~ if(snakeModel[0].type==direfalse[i]) 728 //~ { 729 //~ direction-=1; 730 //~ continue; 731 //~ } 732 //~ if(direfalse[0]==direfalse[1]) 733 //~ { 734 //~ break; 735 //~ } 736 //~ switch(snakeModel[0].type) 737 //~ { 738 //~ case 0: 739 //~ if(direfalse[i]==2) 740 //~ { 741 //~ direction-=4; 742 //~ } 743 //~ else if(direfalse[i]==3) 744 //~ { 745 //~ direction-=2; 746 //~ } 747 //~ break; 748 //~ case 1: 749 //~ if(direfalse[i]==2) 750 //~ { 751 //~ direction-=2; 752 //~ } 753 //~ else if(direfalse[i]==3) 754 //~ { 755 //~ direction-=4; 756 //~ } 757 //~ break; 758 //~ case 2: 759 //~ if(direfalse[i]==0) 760 //~ { 761 //~ direction-=2; 762 //~ } 763 //~ else if(direfalse[i]==1) 764 //~ { 765 //~ direction-=4; 766 //~ } 767 //~ break; 768 //~ case 3: 769 //~ if(direfalse[i]==0) 770 //~ { 771 //~ direction-=4; 772 //~ } 773 //~ else if(direfalse[i]==1) 774 //~ { 775 //~ direction-=2; 776 //~ } 777 //~ break; 778 //~ default: 779 //~ break; 780 //~ } 781 //~ } 782 //~ return direction; 783 //~ }
snakeHead.h
1 #include <unistd.h> 2 #include <stdlib.h> 3 #include <curses.h> 4 #include <time.h> 5 #include <pthread.h> 6 typedef enum {null=-2,stop=-1,left=0,right=1,up=2,down=3}movtype; 7 typedef enum {air,food,wall}coltype; 8 typedef struct { 9 coltype type; 10 int chartype; 11 }charModel; 12 typedef struct { 13 int x; 14 int y; 15 movtype type; 16 }ctrlModel; 17 void writeLineQ(charModel cmTemp[],int bctrltime); 18 void removSnake(ctrlModel snakeModel[]); 19 void fallremovSnake(ctrlModel snakeModel[]); 20 int collidedeal(charModel cmTEMP[],ctrlModel snakeModel[]); 21 void addfood(ctrlModel snakeModel[],ctrlModel foodModel[],int amount); 22 void addsnakemod(ctrlModel snakeModel[],int amount); 23 void program_error(char error_string[]); 24 25 #define SCR_WIDTH 60 26 #define SCR_HEIGHT 20 27 #define SNAKE_CHAR '*' 28 #define SNAKE_LENGTH 8 29 #define FOOD_AMOUNT_MAX 10 30 #define FOOD_CHAR '0' 31 #define SNAKEAI_DEPTH 15
截图: