首页 > 代码库 > 贪吃蛇

贪吃蛇

一月前写的贪吃蛇。不解释,注释很清楚了。主要处理那几个制表符弄了好长时间。还看不懂的话,可以一起交流。

由于不懂链表,就硬是用vector实现了。

和基友玩的时候可搞笑,"敢不敢比比" "来木‘" "恩,等下,叫我加个分数,完爆你。" ,然后添加分数的时候,加上了几个歪瓜。比如按键加分数,无障碍。哈

对了,贪吃蛇 有记分数功能,有障碍,有外挂,碰到障碍和墙壁会死,但是咬到自己不会死的。因为贪吃蛇贪吃蛇,不就贪吃了点嘛><咬到自己没事儿阿。

运行中....


暂停:  话说这个功能也花了有总时间的1/5.主要是一秒会刷新很多次,所以按一次键会识别好多次,所以run函数中

		if(wasd == ‘p‘){
			//shu = !shu;
			shu=true;
		}

没有使用注释的这句shu= !shu; 本来这句的功能是,可以暂时取消障碍,可以再按一次p就又有障碍。但是由于按一次识别好多次,就会出现失效的情况,索性要作弊就一直作弊下去。



end.




主程序

//2014-6-25 ~ 2014-6-26 13:44:00  Copyright 2014 onion  All rights reserved.  email:wsrfssx@yeah.net
/*
2014-6-26 19:08:11 添加障碍。

基本操作:
w a s d 控制方向
q 退出
l (L)暂停

歪瓜:
p 取消障碍的生成,由于run中按键可能会有多次按键的效果,所以多按几次,看分数前的空格成功与否。//已改,不是 shu = !shu; 直接不可逆 zhi=true;
/ 添加分数

*/
#include "tcs.h"
#include <conio.h>  //getch();  kbhit()检测输入。
#include <windows.h> //Sleep
#include <string>
#include <ctype.h>  //tolower转小写
#include <cstdlib>  //rand()
#include <ctime> //time()来初始化随机数srand
using namespace std;


int main(){

	Tcs tcs;
	tcs.show();
	tcs.run();
	cout<<"nice"<<endl;

return 0;
}


Tcs::Tcs(){
	S[0]=     "┌──────────────────────┐";
	S[sMax-1]="└──────────────────────┘";
	
	for(int j=1;j<sMax-1;++j){
		for(int i=0; i<kMax;++i){
			if(i==0) 
		  		S[j]+="│";
			else if(i==kMax-1)
		 	 	S[j]+="│";
			else S[j]+=' ';
		}
	}
	//S[8][8]='O';	
	cVec.push_back('+');
//	S[8][7]='*';
	cVec.push_back('*');

	//S[8][6]='*';	
	cVec.push_back('*');
	//S[8][5]='*';	
	cVec.push_back('*');
	//for(int i=0;i<sMax;++i) cout<<S[i]<<endl;
	
	cs = R;//初始化为右边前进,go go!

	x=8;
	y=8; //x,y先指定下一位置。 8,8 → 8,9


	xvec.push_back(8);  yvec.push_back(8);
	xvec.push_back(8);  yvec.push_back(7);
	xvec.push_back(8);  yvec.push_back(6);
	xvec.push_back(8);  yvec.push_back(5);
	score=0;
	
	bFood = false;
	shu=false;
	return ;
}

void Tcs::show(){
		for(int i=0;i<sMax;++i) cout<<S[i]<<endl;
		
		cout<<"w a s d 移动方向\nq 退出"<<endl;
		if(shu) cout<<"   ";
		cout<<"分数: "<<score<<endl;
}
void Tcs::run(char wasd){  //由于按了一次键盘会出现重复按键 //要防止按一次键很多次的效果。
	while(!kbhit() || (wasd = tolower(getch()) ) != 'q' ){
		
		if(wasd == 'p'){//和基友耍赖
			//shu = !shu;
			shu=true;
		}
		else if (wasd =='/') 
			score+=10;
		else if(wasd == 'l')
			break;
		else ;


		if( wasd == 'w') {
			if(cs==L || cs==R){ 
				cs = U;
				//x[0]--;
			}
		}
		else if(wasd == 's'){
			if(cs==L || cs==R){
				cs = D;
				//x[0]++;
			}
		}
		else if(wasd == 'a'){
			if(cs==U || cs==D){
				cs = L; 
				//y[0]--;
			}
		}
		else if(wasd == 'd'){
			if(cs==U || cs==D){
				cs = R;
				//y[0]++;
			}
		}
		else ;

		
		 
		if(cs==U) x--;
		else if(cs==D) x++;
		else if(cs==L) y--;
		else if(cs==R) y++;
		else ;
		
		food();
		bigbang();
		
		for(vector<int>::size_type c =( cVec.size()-1); c <=  1000; c--) {  //专用来移动坐标 . 看到条件不要疑惑,本来条件是c>=0,因为size_type 减0后不会取到负数,所以故此
			
			
			if(c==0){
					xvec[0]=x; yvec[0]=y;
			}
			else{ 
				if(c == cVec.size()-1) S[xvec[c]][ yvec[c]]=' ';
				xvec[c]=xvec[c-1];	yvec[c]=yvec[c-1];
			}
		
		}
		
		for(vector<int>::size_type c=0; c < cVec.size(); ++c) {  
			S[xvec[c]][yvec[c]] = cVec[c];
			
		}
	/*  四角边界
		S[1][2]='u'; 
		S[1][kMax-1]='l'; 
		S[sMax-2][2]='u'; 
		S[sMax-2][kMax-1]='r';
	*/		
		
	//if(S[sMax-2][1]!=' ' && S[sMax-2][2]==' ' )cout<<'\a';
		
		
		show();
		Sleep(40);
		system("cls");
		//score+=100; //同耍赖
			
		
	}//while


	
   if(wasd == 'q') gameOver();
   else if(wasd == 'l') stop();  //打算保存退出前最后的方向。
   else ;
		
}//run

void Tcs::food(){
	while(!bFood){
		srand(time(0));
		int i=rand()%20;  //0-19
		int j=rand()%45; 
		if(S[i][j]==' '){
			S[i][j]='@';//食物
			bFood = true;
		}
		if(!shu){
		//障碍添加。每次出现新食物的时候都会新增一个障碍且不会消失。以后得添加食物可食用性的问题。
		i=rand()%20;  
		j=rand()%45; 
		if(S[i][j]==' '){
			S[i][j]='^';//食物
			//bFood = true;
		}
		}
		

	}
	
}

void Tcs::bigbang(){
	//先检测墙壁,碰到便game over;
	if(xvec[0]<1 || xvec[0]>19 || yvec[0]<2  || yvec[0] >45)  //碰壁
		gameOver();
	if(S[x][y]=='@') {  //食物
		score+=10;
		cout<<'\a';
		cVec.push_back('!');  //末尾添加元素.坐标也要添加
		xvec.push_back(xvec[xvec.size()-1]);//x坐标和前一个蛇身坐标一样,y加一或减一
		if(S[xvec[xvec.size()-1]] [yvec[yvec.size()-1]+1] == ' '){
			
			yvec.push_back(yvec[yvec.size()-1]+1);
		}
		else yvec.push_back(yvec[yvec.size()-1]-1);
	//	S[xvec[xvec.size()-1]][yvec.size()-1]='*';
		//cout<<cVec.size();
		bFood=false;
	}
	if(S[x][y]=='^')
		gameOver();
}

void Tcs::gameOver(){
	system("cls");
	cout<<"game over!"<<endl;
	system("pause");
	exit(0);
}

void Tcs::stop(){
		cout<<"已暂停。"<<endl;
		system("pause");
		run('X'); //添加无功能字符,否则会调用默认,会改变原有方向。A cs会保存方向的。所以参数添加废弃字符便可

}
头文件:tcs.h
#ifndef TCS_H
#define TCS_H


#include <iostream>
#include <vector>
using namespace std;
class Tcs{
public:  
	Tcs();
	void show();//只输出当前的图案
	void run(char ='d'); //运行时刻  默认参数 d
	void turn();//转向
	void food();//生成食物,本来参数是bFood,后来去掉了//2014-6-26 18:44:36加障碍
	void bigbang();//碰撞检测,两种情况,一种和障碍、墙壁(false),另一种是食物(true)。已去掉参数。
	void gameOver();
	void stop( );//暂停。参数为退出run前的方向。

	/*struct xy{
		int x;
		int y;
	};*/
	
private:
	 unsigned  x,y; //坐标,保存下一个位置
	 unsigned score;
	 bool shu;
	 vector<unsigned> xvec,yvec;  //保存蛇身的坐标

	 /*
	 sMax为string高度。kMax为每行长度,主要用蛇身长短控制每个string长度 .
	 由于坑爹的制表符不是char。所以。边界测验为  x[1~ sMax-2],y[2~kMax-1]  . ||-- x[1~19] y[2~45]  
	 即四角边界为 
		S[1][2]='u'; 
		S[1][kMax-1]='l'; 
		S[sMax-2][2]='u'; 
		S[sMax-2][kMax-1]='r';
		打算用边界控制食物的生成和碰撞检测。不过
		if(S[sMax-2][1]!=' ' && S[sMax-2][2]==' ' )cout<<'\a';
		已经测试出来了。边界都不为空格的。所以这就好办了。

		制表符大概占用两个char的。
	 */
	static const int sMax=21,kMax=46;
	string  S[sMax];
	vector<char> cVec;//保存蛇身,比较容易增长,size计算长度。
	//char wasd;//方向
	enum A{U,D,L,R} cs;//前进方向ing
	bool bFood;//此刻食物是否存在
	
};
#endif

下载地址     //貌似没有必要,代码已经给了

p.s.没有积分的可以直接找我要。

欢迎交流。


贪吃蛇