/* File Name : snake256.cpp
Date :2005-6-16~
Descripition :work in 800*600*256 */
//包含头文件
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <iostream.h>
#include <math.h>
#include <dos.h>
#include <bios.h>
#include <graphics.h>
#include <time.h>
//宏定义
#define ESC 0x011b //按键
#define ENTER 0x1c0d
#define UP 0x4800
#define RIGHT 0x4d00
#define DOWN 0x5000
#define LEFT 0x4b00
#define PALETTE_MASK 0x3c6//调色板寄存器号
#define PALETTE_RD 0x3c7
#define PALETTE_WD 0x3c8//设置调色板端口号
#define PALETTE_DATA 0x3c9
#define TextMode 0x03
#define VBE320X200X256 0x13 //显示模式宏定义
#define VBE640X400X256 0x100
#define VBE640X480X256 0x101
#define VBE800X600X256 0x103
#define VBE1024X768X256 0x105
#define VBE1280X1024X256 0x107
#define VBE320X200X64K 0x10E
#define VBE640X480X64K 0x111
#define VBE800X600X64K 0x114
#define VBE1024X768X64K 0x117
#define VBE1280X1024X64K 0x11A
typedef unsigned char uchar ;
typedef unsigned int uint ;
typedef unsigned long ulong ;
//结构/全局变量
uchar far *ImgEare=(uchar far *)0xa0000000l;//图象开始空间
uchar far *TextEare=(uchar far *)0xf000fa6el;
typedef struct BM_FILE {
uint ftype;//文件类型,"BM",BMP文件的标示
ulong fsize;//文件大小
uint nouse1;//保留字
uint nouse2;//保留字
ulong foffest;//数据区起始位置
} BmpFile;
typedef struct BM_INFO {
ulong isize;//图象描述信息快的大小
ulong iwidth;//图象宽度
ulong iheight;//图象高度
uint iplanes;//
uint ibitCount;//每个象素占的位数,确定是多少色图
ulong icomperssion;
ulong isizeimage;
ulong ixpolspermeter;
ulong iypolspermeter;
ulong iclrused;
ulong iclrimportant;
} BmpInfo;
int score=0 ;// //记录成绩
struct snakeN //小方块结构
{
int oldx,oldy;//记录老的坐标位置
int nx,ny; //记录新的坐标位置
int color; //防快的颜色
}snake[100],food;
struct time sys_time,tmp_time;//时间判断
int hund=0;
int movex=40,movey=40;
int way=0;//控制蛇走动方向
int speed=10;
//函数
void SetVideoMode(uint Mode);//设置显示模式
void SetPaletteColor(int index,char RED, char GREEN,char BLUE);//设置调色板
void GetPaletterColor(int index,char &RED, char &GREEN,char &BLUE);//获得调色板
void ChangePage(int Page); //改变显示页
void DrawDot(int x,int y,int color);//1024X768X256显示模式画点
void DrawLine(int x0,int y0,int x1,int y1,int color); //1024X768X256显示模式画线
void DrawLineH(int x0,int x1,int y0,int color); //1024X768X256显示模式画横线(主要做图形填充)
void DrawRec(int x0,int y0,int x1,int y1,int color); //1024X768X256显示模式画空心矩形
void DrawRecS(int x0,int y0,int x1,int y1,int color); //1024X768X256显示模式画实心矩形
void Windows(int x0,int y0,int x1,int y1,int c,int bc);//1024X768X256显示窗口
void DrawImg(FILE *fp,BmpFile &fpfile,BmpInfo &fpinfo,int x,int y); //绘制256色图形文件
void DrawChar(int x,int y,int color,char ch); //显示字符
void DrawChar2(int x,int y,int color,char ch);//2倍显示字符
void DrawStrH2(int x,int y,int color,char *ch);//2倍横向显示字符串
void DrawStrV2(int x,int y,int color,char *ch);//2倍纵向显示字符串
void ShowSnaT();//显示蛇头
void ShowSna(int i);//显示蛇身
void ShowKuai(snakeN *kuai);//显示方块
int KeyCtrl(int key); //按键控制
int GetFood(); //判断是否吃到食物
int OutWin(); //判断时候出边界
//主函数
int main(void)
{
int i,j,k;//循环变量
FILE *fp;//图形文件
BmpFile fpfile;//图形文件头文件信息
BmpInfo fpinfo;//图形文件图象信息
//time_t stime,etime;
if((fp=fopen("e:\\bc31\\gsnake.bmp","rb"))==NULL)//打开BMP显示图形文件
{
cout<<"Can't open the File";
getch();exit(1);
}
SetVideoMode(VBE1024X768X256);//设置显示模式为1024*768*256
DrawRec(1023,767,0,0,60);
DrawImg(fp,fpfile,fpinfo,200,134);
//time(&stime);
Windows(198,198,502,502,30,40);
DrawStrH2(250,610,60,"SCORES :");
//time(&etime);
//cout<<(etime-stime);//显示多长时间显示完
/////////////////////////////////////////////处理贪吃蛇
food.oldx=300;food.oldy=300;
food.nx=300;food.ny=300;
ShowKuai(&food);
snake[0].oldx=220;snake[0].oldy=220;
snake[0].nx=220;snake[0].ny=220;
ShowSnaT();
getch();
gettime(&sys_time);
gettime(&tmp_time);
randomize();//初始化随即数发生器
while(1)
{
if(bioskey(1)!=0)
{
int GetKey;//获得键值
GetKey=bioskey(0);//记住同时传送键值给函数,不然有问题!
if(KeyCtrl(GetKey))
break; //按键控制
}
gettime(&sys_time);
if(tmp_time.ti_hund!=sys_time.ti_hund)//用speed毫秒来判断
{
hund++;
tmp_time.ti_hund=sys_time.ti_hund;
}
if(hund==speed)
{
ShowSnaT();
for(i=1;i<=score;i++)
ShowSna(i);
GetFood();
hund=0;
}
}
SetVideoMode(TextMode);//恢复设置显示模式为文本模式
fclose(fp);
cout<<"END";
getch();
return 0;
}
////////////////////////////////////////////////////////////////////////////////////
//////////////////////////Function Definition///////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
void SetVideoMode(uint Mode)//设置显示模式
{
REGS inregs,outregs;
inregs.x.ax=0x4f02;
inregs.x.bx=Mode;
int86(0x10,&inregs,&outregs);
if(outregs.h.ah!=0)
{
closegraph();
cout<<"Can't Init the graphics !"<<endl;
getch();
exit(1);
}
}
void SetPaletteColor(int index,char RED, char GREEN,char BLUE)//设置调色板
{
outp(PALETTE_MASK,0xff); //允许改变调色板
outp(PALETTE_WD,index);
outp(PALETTE_DATA,RED>>2);
outp(PALETTE_DATA,GREEN>>2);
outp(PALETTE_DATA,BLUE>>2);
}
void GetPaletterColor(int index,char &RED, char &GREEN,char &BLUE)//获得调色板
{
outp(PALETTE_MASK,0xff); //允许改变调色板
outp(PALETTE_RD,index);
BLUE=inp(PALETTE_DATA)<<2;
GREEN=inp(PALETTE_DATA)<<2;
RED=inp(PALETTE_DATA)<<2;
}
void ChangePage(int Page) //改变显示页
{
REGS inregs,outregs;
inregs.x.ax=0x4f05;
inregs.x.bx=0x00;
inregs.x.dx=Page;
int86(0x10,&inregs,&outregs);
}
void DrawDot(int x,int y,int color)//1024X768X256显示模式画点
{
ChangePage(((long)((long)y<<10)+x)/65536l);//注意长整型的隐型转换
*(ImgEare+((long)((long)y<<10)+x)%65536l)=color;
}
void DrawLine(int x0,int y0,int x1,int y1,int color)//1024X768X256显示模式画线
{
//主要是确定每个点的坐标,从而确定要写的内存的位置
int i;//用来控制循环描点
int xn,yn;//写内存对应的坐标
if (x0>x1)
{
for(i=x1;i<=x0;i++)
{
xn=i;
yn=y0+(i-x1)*((y0-y1)/(x0-x1));
DrawDot(xn,yn,color);
}
}
else if(x0<x1)
{
for(i=x0;i<=x1;i++)
{
xn=i;
yn=y0+(i-x0)*((y1-y0)/(x1-x0));
DrawDot(xn,yn,color);
}
}
else
{
int temp;
if(y0<y1)
{
temp=y0;y0=y1;y1=temp;
}
for(i=y1;i<=y0;i++)
{
xn=x0;
yn=i;
DrawDot(xn,yn,color);
}
}
}
/*void DrawLineH(int x0,int x1,int y0,int color)//1024X768X256显示模式画横线(主要做图形填充)
{
char *buf;
buf=new char[abs(x0-x1)];
}*/
void DrawRec(int x0,int y0,int x1,int y1,int color)//1024X768X256显示模式画空心矩形
{
DrawLine(x0,y0,x1,y0,color);//画四条边
DrawLine(x0,y1,x1,y1,color);
DrawLine(x0,y0,x0,y1,color);
DrawLine(x1,y0,x1,y1,color);
}
void DrawRecS(int x0,int y0,int x1,int y1,int color)//1024X768X256显示模式画实心矩形
{
for(int i=y0;i<=y1;i++)
DrawLine(x0,i,x1,i,color);
}
void Windows(int x0,int y0,int x1,int y1,int c,int bc)//1024X768X256显示窗口
{
DrawRec(x0,y0,x1,y1,c);
DrawRec(x0+1,y0+1,x1-1,y1-1,c);
DrawRecS(x0+2,y0+2,x1-2,y1-2,bc);
}
void DrawImg(FILE *fp,BmpFile & fpfile,BmpInfo & fpinfo,int x,int y) //绘制256色图形文件
{
int i,j,k;//循环变量
uchar buffer[1000];//图象缓冲
ulong useB,lineB;//每一行图象在文件中占用的字节数~每一行需要的字节数
fseek(fp,0,SEEK_SET);
fread(&fpfile,14,1,fp);
fread(&fpinfo,40,1,fp);
for(i=0;i<256;i++)
{
char b,g,r;
b=fgetc(fp); g=fgetc(fp); r=fgetc(fp);
SetPaletteColor(i,r,g,b);
fgetc(fp);
}
useB=fpinfo.iwidth;
lineB=useB+(4-((useB%4)?useB%4:4));//关于(4-((useB%4)?useB%4:4))要注意
fseek(fp,0x36/*文件信息区+图象信息区大小*/+256*4,SEEK_SET);//到数据区起始位置
for(i=fpinfo.iheight-1;i>=0;i--) //高度循环
{
fread(buffer,lineB,1,fp);
for(j=0;j<useB;j++)
{
k=((long)((long)(i+y)<<10)+x+j)/65536l;
ChangePage(k);
*(ImgEare+(long)((long)((long)(i+y)<<10)+x+j)%65536l)=buffer[j];
}
}
}
void DrawChar(int x,int y,int color,char ch)//显示字符
{
int i,j;//循环变量
char chp[8];
int bit=0x80;
for(i=0;i<8;i++)
{
chp[i]=*(TextEare+ch*8+i);
for(j=0;j<8;j++)
{
if(chp[i]&(bit>>j))
{
DrawDot(x+j,y+i,color);
}
}
}
}
void DrawChar2(int x,int y,int color,char ch)//显示字符
{
int i,j;//循环变量
char chp[8];
int bit=0x80;
for(i=0;i<8;i++)
{
chp[i]=*(TextEare+ch*8+i);
for(j=0;j<8;j++)
{
DrawDot(x+j*2,y+2*i,(chp[i]&(bit>>j))?color:0);
DrawDot(x+j*2+1,y+2*i,(chp[i]&(bit>>j))?color:0);
DrawDot(x+j*2,y+2*i+1,(chp[i]&(bit>>j))?color:0);
DrawDot(x+j*2+1,y+2*i+1,(chp[i]&(bit>>j))?color:0);
}
}
}
void DrawStrH2(int x,int y,int color,char *ch)//2倍显示字符串
{
int i=0;
while(*ch!=NULL)
{
DrawChar2(x+i*16,y,color,*ch);
ch++;
i++;
}
}
void DrawStrV2(int x,int y,int color,char *ch)//2倍显示字符串
{
int i=0;
while(*ch!=NULL)
{
DrawChar2(x,y+i*16,color,*ch);
ch++;
i++;
}
}
int KeyCtrl(int key) //按键控制
{
if(key==ESC)
{
return 1;
}
else if(key==RIGHT)
{if(way!=2){way=0;DrawStrH2(610,610,60,"R");}}
else if(key==DOWN)
{if(way!=3){way=1;DrawStrH2(610,610,60,"D");}}
else if(key==LEFT)
{if(way!=0){way=2;DrawStrH2(610,610,60,"L");}}
else if(key==UP)
{if(way!=1){way=3;DrawStrH2(610,610,60,"U");}}
return 0;
}
void ShowSnaT()//显示蛇段
{
snake[0].oldx=snake[0].nx;
snake[0].oldy=snake[0].ny;
if(way==0) //右移
{
snake[0].oldx=snake[0].nx;
snake[0].nx=snake[0].nx+10;
}
else if(way==1) //下移
{
snake[0].oldy=snake[0].ny;
snake[0].ny=snake[0].ny+10;
}
else if(way==2) //左移
{
snake[0].oldx=snake[0].nx;
snake[0].nx=snake[0].nx-10;
}
else if(way==3) //上移
{
snake[0].oldy=snake[0].ny;
snake[0].ny=snake[0].ny-10;
}
OutWin();
ShowKuai(&snake[0]);
}
void ShowSna(int i)//显示方块
{
snake[i].oldx=snake[i].nx;
snake[i].oldy=snake[i].ny;
snake[i].nx=snake[i-1].oldx;
snake[i].ny=snake[i-1].oldy;
ShowKuai(&snake[i]);
}
void ShowKuai(snakeN *kuai)//显示方块
{
DrawRecS(kuai->oldx,kuai->oldy,kuai->oldx+10,kuai->oldy+10,40);
DrawRecS(kuai->nx,kuai->ny,kuai->nx+10,kuai->ny+10,140);
DrawRec(kuai->nx,kuai->ny,kuai->nx+10,kuai->ny+10,160);
}
int GetFood() //判断是否吃到食物
{
if((snake[0].nx==food.nx)&&(snake[0].ny==food.ny))
{
score++;
speed--;
char str[5];
snake[score].oldx=snake[score].nx=snake[score-1].oldx;
snake[score].oldy=snake[score].ny=snake[score-1].oldy;
food.oldx=food.nx=200+random(30)*10;
food.oldy=food.ny=200+random(30)*10;
ShowKuai(&food);
sprintf(str,"%d",score);
DrawStrH2(550,610,60,str);
return 1;
}
return 0;
}
int OutWin() //判断时候出边界
{
if((snake[0].nx<200)||(snake[0].nx>=500)||(snake[0].ny<200)||(snake[0].ny>=500))
{
DrawStrH2(150,110,60,"Game Again?(y(Y)/n(N)");
while(1)
{
int ch=getch();
if(ch=='y'||ch=='Y')
{
way=0;
score=0;
speed=10;
DrawStrH2(150,110,60,"---------------------");
Windows(198,198,502,502,30,40);
food.oldx=300;food.oldy=300;
food.nx=300;food.ny=300;
ShowKuai(&food);
snake[0].oldx=220;snake[0].oldy=220;//初始化
snake[0].nx=220;snake[0].ny=220;
ShowSnaT();
getch();
break;
}
else if(ch=='n'||ch=='N')
{
exit(0);
break;
}
}
}
return 0;
}
我做的贪吃蛇256色的!