#include
#include
#include
#include
#include
# define timer 10//毫秒单位,控制球的移速,与dx,dy也有关
char ch1[]={"Win"};
char ch2[]={"Game Over"};
//球的参数
int r=4;
int dx=1,dy=1;//球的步进,成45°角
//砖墙左上角第一块砖的红色区域的左上角坐标
int startx=250,starty=30;
//边界墙的参数
int boundaryx;
int boundaryy;
POINT positionboundary[5];
//每块砖的参数
int sizex1=20;
int sizey1=15;
int sizet1=3;
//砖墙的参数
int horizontal=15;
int vertical_1=6;
int vertical_2=9;
int gap_end=4;
//挡板的参数
int sizex2=60;
int sizey2=5;
int sizet2=3;
int mousedx=4;//挡板步进。控制挡板移速,与timer也有关
int mousex=0;
//用于鼠标定位
RECT rcClient;
RECT rect_mouse;
POINT positionmouse;
int status=0;
int positionmousestatus=0;
int positionmouseflag=0;
HWND hwnd;
HDC hdc;
HDC hdc_screen;
HBRUSH hbrushred,hbrushwhite,hbrushblack;
HPEN hpenyellow,hpenblack,hpenwhite;
//客户区尺寸
int sizeclientx=600;
int sizeclienty=600;
//菜单的参数
int id_menu=0;
int key_1_menu=0;
//屏幕尺寸
int width_screen;
int long_screen;
//储存砖墙中每块砖的红色区域左上角的坐标,不包括白色边界墙
struct wallarray
{
int x;
int y;
int flag;//用于标记砖是否被撞掉
}wall[50][50];
//初始化HDC
void creathdc()
{
hwnd=GetConsoleWindow();
hdc=GetDC(hwnd);
hdc_screen=GetDC(NULL);
hbrushred=CreateSolidBrush(RGB(255,0,0));
hbrushwhite=CreateSolidBrush(RGB(255,255,255));
hbrushblack=CreateSolidBrush(RGB(0,0,0));
hpenblack=CreatePen(PS_SOLID,1,RGB(0,0,0));
hpenyellow=CreatePen(PS_SOLID,1,RGB(255,255,0));
hpenwhite=CreatePen(PS_SOLID,1,RGB(255,255,255));
}
//置顶光标到客户区的指定位置,与printf函数配合使用
void cursor(int x,int y)//x,y是在客户区坐标系中的坐标
{
COORD position;
HANDLE handle;
handle=GetStdHandle(STD_OUTPUT_HANDLE);
position.X=x;
position.Y=y;
SetConsoleCursorPosition(handle,position);
}
//进行游戏中...,提示按键功能
void key_1()
{
cursor(1,1);
printf("按Enter暂停游戏");
cursor(1,2);
printf("按Space继续游戏");
cursor(1,3);
printf("按ESC返回主菜单");
}
//菜单界面...,提示按键功能
void key_2()
{
cursor(1,1);
printf("按上、下键选择");
cursor(1,2);
printf("按Enter确认选项");
}
//获取客户区尺寸
void clientsizeget()
{
GetClientRect(hwnd,&rcClient);
}
//获取屏幕尺寸(像素)
void screensizeget()
{
long_screen=GetDeviceCaps(hdc_screen,HORZRES);//屏幕水平尺寸
width_screen=GetDeviceCaps(hdc_screen,VERTRES);//屏幕垂直尺寸
}
//设置窗口位置;根据需要的客户区尺寸设置大约的窗口大小
void clientsizeset(int x,int y)
{
screensizeget();
MoveWindow(hwnd,long_screen/2-x/2,0,x,y,1);//移动窗口(并不是客户区)在显示器上的位置和设置窗口大小
}
//创建一块转
void stonedraw(int x,int y,int sizex,int
sizey,int sizet)//创建一块转
{
POINT positionred[4],positionwhite[6];
//红砖
positionred[0].x=x;
positionred[0].y=y;
positionred[1].x=x+sizex;
positionred[1].y=y;
positionred[2].x=x+sizex;
positionred[2].y=y+sizey;
positionred[3].x=x;
positionred[3].y=y+sizey;
SelectObject(hdc,hpenblack);
SelectObject(hdc,hbrushred);
Polygon(hdc,positionred,4);
//砖的白边
positionwhite[0].x=x-sizet;
positionwhite[0].y=y-sizet;
positionwhite[1].x=x-sizet;
positionwhite[1].y=y+sizey;
positionwhite[2].x=x;
positionwhite[2].y=y+sizey;
positionwhite[3].x=x;
positionwhite[3].y=y;
positionwhite[4].x=x+sizex;
positionwhite[4].y=y;
positionwhite[5].x=x+sizex;
positionwhite[5].y=y-sizet;
SelectObject(hdc,hbrushwhite);
Polygon(hdc,positionwhite,6);
}
//创建砖墙及边界墙
void picture(int h,int v,int gap)
{
int i,j;
boundaryx=h*(sizex1+sizet1+gap)+gap;//正好是砖墙水平x轴的长度
boundaryy=v*(sizey1+sizet1+gap)+gap+250;//正好是砖墙垂直y轴的长度+250
//砖墙
for(i=0;i
for(j=0;j
{
stonedraw(startx+j*(sizex1+sizet1+gap),starty+i*(sizey1+sizet1+gap),sizex1,sizey1,sizet1);//gap是相邻砖的缝隙;(startx,starty)是砖墙左上角第一块砖的红色区域的左上角坐标
//初始化wall结构体数组
wall[i][j].x=startx+j*(sizex1+sizet1+gap);
wall[i][j].y=starty+i*(sizey1+sizet1+gap);
wall[i][j].flag=0;
}
//边界墙
positionboundary[0].x=startx-sizet1-gap;
positionboundary[0].y=starty-sizet1-gap;
positionboundary[1].x=startx-sizet1-gap;
positionboundary[1].y=starty-sizet1-gap+boundaryy;
positionboundary[2].x=startx-sizet1-gap+boundaryx;
positionboundary[2].y=starty-sizet1-gap+boundaryy;
positionboundary[3].x=startx-sizet1-gap+boundaryx;
positionboundary[3].y=starty-sizet1-gap;
positionboundary[4].x=startx-sizet1-gap;
positionboundary[4].y=starty-sizet1-gap;
SelectObject(hdc,hpenwhite);
Polyline(hdc,positionboundary,5);
}
//画挡板
void stonedraw_mouse(int x)//x水平移动。x=0时是初始位置:靠左侧
{
//覆盖删除
SelectObject(hdc,hpenblack);
SelectObject(hdc,hbrushblack);
if(status>x)//左移
Rectangle(hdc,startx-sizet2+x+mousedx,starty+boundaryy-50-sizet2,startx+sizex2+x+mousedx,starty+boundaryy-50+sizey2);
if(status
Rectangle(hdc,startx-sizet2+x-mousedx,starty+boundaryy-50-sizet2,startx+sizex2+x-mousedx,starty+boundaryy-50+sizey2);
//移动后,重画
stonedraw(startx+x,starty+boundaryy-50,sizex2,sizey2,sizet2);
status=x;
}
//将鼠标限制到客户区外侧正下方
void mouselimitxy()
{
//限制在固定区域
rect_mouse.left=long_screen/2-sizeclientx/2+40;
rect_mouse.top=sizeclienty-40;
rect_mouse.right=long_screen/2+sizeclientx/2-40;
rect_mouse.bottom=sizeclienty-35;
ClipCursor(&rect_mouse);
}
//获取鼠标在客户区的当前位置,以客户区坐标系为参考坐标
void mousegetxy()
{
GetCursorPos(&positionmouse);
ScreenToClient(hwnd,&positionmouse);
}
//根据鼠标状态控制挡板移动
void mousestatus()
{
if(GetKeyState(VK_LBUTTON)<0)
{
mousegetxy();
//鼠标移动
if(positionmouse.x>positionmousestatus &&
startx+sizex2+mousex+gap_end
{
mousex+=mousedx;
stonedraw_mouse(mousex);
positionmouseflag=0;
}
if(positionmouse.xpositionboundary[0].x)//左移
{
mousex-=mousedx;
stonedraw_mouse(mousex);
positionmouseflag=1;
}
//鼠标没有移动,保持鼠标没有移动前的左右移动其一功能
if(positionmouse.x==positionmousestatus)
{
if(positionmouseflag==0 &&
startx+sizex2+mousex+gap_end
{
mousex+=mousedx;
stonedraw_mouse(mousex);
}
if(positionmouseflag==1&&
startx-sizet2+mousex-gap_end>positionboundary[0].x )//左移
{
mousex-=mousedx;
stonedraw_mouse(mousex);
}
}
positionmousestatus=positionmouse.x;
}
Sleep(timer);
}
//进行游戏
void play(int ho,int ve)
{
void menuinitialize();//声明
int i,j,t=0;
//球的中心坐标
int ballx;
int bally=starty+boundaryy-50-sizet2-r-1;//球中心的初始位置y
srand((unsigned) time(NULL));
do
{
ballx=rand()`0;//球中心的初始位置x,在挡板上任意位置
if(ballx%2==0)//球的初始x轴移动方向:dx为正代表向右,dx为负代表向左
dx=dx*(-1);
}
while(ballx<=startx-sizet2 ||
ballx>=startx+sizex2);
while(1)
{
if(GetKeyState(VK_SPACE)<0)//空格:暂停
while(1)
{
if(GetKeyState(VK_RETURN)<0)//回车:继续
break;
if(GetKeyState(VK_ESCAPE)<0)//ESC:返回主菜单
{
//回复初始状态,以备下次执行play()
dx=1;
dy=1;
mousex=0;
status=0;
positionmousestatus=0;
menuinitialize();
}
}
if(GetKeyState(VK_ESCAPE)<0)//ESC:返回主菜单
{
//回复初始状态,以备下次执行play()
dx=1;
dy=1;
mousex=0;
status=0;
positionmousestatus=0;
menuinitialize();
}
mousestatus();
//撞上边界墙,反弹
if(bally==positionboundary[0].y+r+1)
dy*=(-1);
//撞左右边界墙,反弹
if(ballx==positionboundary[0].x+r+1 ||
ballx==positionboundary[2].x-r-1)
dx*=(-1);
//覆盖删除球
SelectObject(hdc,hpenblack);
MoveToEx(hdc,ballx+r,bally,NULL);
AngleArc(hdc,ballx,bally,r,0,360);
//球移动,步进(dx,dy)
SelectObject(hdc,hpenyellow);
MoveToEx(hdc,ballx+dx+r,bally-dy,NULL);
AngleArc(hdc,ballx+=dx,bally-=dy,r,0,360);//球的移动方向:dx为正代表向右,dx为负代表向左;dy为正代表向上,dy为负代表向下
//撞砖墙(包括红色区域和白色区域),反弹
for(i=0;i
for(j=0;j
{
if( t
{
//撞砖墙上面和下面,反弹
if( ballx>wall[i][j].x-sizet1-r && ballx
{
t++;//用于计算已消除多少块砖
dy*=(-1);
wall[i][j].flag=1;//代表此块砖被撞后消除
//覆盖消除
SelectObject(hdc,hpenblack);
SelectObject(hdc,hbrushblack);
Rectangle(hdc,wall[i][j].x-sizet1,wall[i][j].y-sizet1,wall[i][j].x+sizex1,wall[i][j].y+sizey1);
}
//撞砖墙左面和右面,反弹
if(ballywall[i][j].y-sizet1-r &&
(ballx==wall[i][j].x-sizet1-r ||
ballx==wall[i][j].x+sizex1+r))
{
t++;//用于计算已消除多少块砖
dx*=(-1);
wall[i][j].flag=1;//代表此块砖被撞后消除
//覆盖消除
SelectObject(hdc,hpenblack);
SelectObject(hdc,hbrushblack);
Rectangle(hdc,wall[i][j].x-sizet1,wall[i][j].y-sizet1,wall[i][j].x+sizex1,wall[i][j].y+sizey1);
}
//撞砖墙四角,原路返回,前提是:dx=1,dy=1,成45°步进
if((ballx==wall[i][j].x-sizet1-r &&
(bally==wall[i][j].y+sizey1+r || bally==wall[i][j].y-sizet1-r)) ||
( ballx==wall[i][j].x+sizex1+r &&
(bally==wall[i][j].y+sizey1+r ||
bally==wall[i][j].y-sizet1-r)))
{
t++;//用于计算已消除多少块砖
dx*=(-1);
dy*=(-1);
wall[i][j].flag=1;//代表此块砖被撞后消除
//覆盖消除
SelectObject(hdc,hpenblack);
SelectObject(hdc,hbrushblack);
Rectangle(hdc,wall[i][j].x-sizet1,wall[i][j].y-sizet1,wall[i][j].x+sizex1,wall[i][j].y+sizey1);
}
}
}
//撞挡板左上角上部白色部分,原路返回
if(ballx>=startx+mousex-sizet2 &&
ballx<=startx+mousex &&
bally==starty+boundaryy-50-sizet2-r-1)
{
dx*=(-1);
dy*=(-1);
}
//撞挡板非左上角上部白色区域,反弹
if(ballx>startx+mousex &&
ballx<=startx+mousex+sizex2 &&
bally==starty+boundaryy-50-sizet2-r-1)
dy*=(-1);
//判断砖是否全部清除,游戏成功
if(t==ve*ho)
{
Sleep(500);
system("cls");
SetTextColor(hdc,RGB(0,255,0));
TextOut(hdc,rcClient.right/2,rcClient.bottom/2,ch1,strlen(ch1)+1);
Sleep(1000);
break;
}
//判断未接住球,游戏失败
if(bally>starty+boundaryy-50+r)
{
Sleep(500);
system("cls");
SetTextColor(hdc,RGB(255,0,0));
TextOut(hdc,rcClient.right/2,rcClient.bottom/2,ch2,strlen(ch2)+1);
Sleep(1000);
break;
}
}
//回复初始状态,以备下次执行play()
dx=1;
dy=1;
mousex=0;
status=0;
positionmousestatus=0;
}
//子菜单:游戏规则介绍
void rule()
{
int n;
int sizech_rule;
char *s_rule[4]={"移动并点击鼠标左、右键控制挡板移动、反弹小球"," 小球撞击红砖后消除红砖"," 消除所有的红砖,游戏胜利"," 小球落地,游戏失败"};
SetTextColor(hdc,RGB(0,255,0));
SetBkColor(hdc,RGB(0,0,0));
for(n=0;n<4;n++)
{
sizech_rule=strlen(s_rule[n]);
if(n==3)
sizech_rule+=1;
TextOut(hdc,rcClient.right/3,rcClient.bottom/2+n*20,s_rule[n],sizech_rule);
}
}
//主菜单
void menuset(int j)
{
int n;
int sizech_menu;
char *s_menu[4]={"1.难度1","2.难度2","3.游戏规则","4.退出游戏"};
SetTextColor(hdc,RGB(0,255,0));
SetBkColor(hdc,RGB(0,0,0));
for(n=0;n<4;n++)
{
sizech_menu=strlen(s_menu[n]);
TextOut(hdc,rcClient.right/2,rcClient.bottom/2+n*20,s_menu[n],sizech_menu);
}
SetTextColor(hdc,RGB(255,0,0));
sizech_menu=strlen(s_menu[j]);
TextOut(hdc,rcClient.right/2,rcClient.bottom/2+j*20,s_menu[j],sizech_menu);
}
//选择主菜单后跳转执行
void judgeid(int id_judge)
{
void menuinitialize();//声明
system("cls");
switch(id_judge)
{
case 0:
key_1();
picture(horizontal,vertical_1,gap_end);
stonedraw_mouse(0);
mouselimitxy();
play(horizontal,vertical_1);
menuinitialize();
break;
case 1:
key_1();
picture(horizontal,vertical_2,gap_end);
stonedraw_mouse(0);
mouselimitxy();
play(horizontal,vertical_2);
menuinitialize();
break;
case 2:
rule();
Sleep(4000);
menuinitialize();
break;
case 3:
SetTextColor(hdc,RGB(0,255,0));
TextOut(hdc,rcClient.right/2,rcClient.bottom/2,"再见",strlen("再见")+1);
Sleep(2000);
exit(0);
}
}
//进行主菜单选择
void menuinitialize()
{
void judgeid(int id_judge);//声明
system("cls");
clientsizeget();
menuset(id_menu);
key_2();
do
{
if(GetKeyState(VK_DOWN)<0)//下
{
id_menu++;
id_menu=id_menu%4;
menuset(id_menu);
}
if(GetKeyState(VK_UP)<0)//上
{
if(id_menu==0)
id_menu=4;
id_menu--;
id_menu=id_menu%4;
menuset(id_menu);
}
Sleep(100);
}while(GetKeyState(VK_RETURN)>=0);//单击enter键确认选择,退出
judgeid(id_menu);
}
void main(int argc,char *argv[])
{
creathdc();
clientsizeset(sizeclientx,sizeclienty);
menuinitialize();
}