|
该游戏类似于俄罗斯方块,游戏规则是:电脑随机出逐渐下落的三个色块,你通过左右移动该色块,尽量让横、竖、斜线上的颜色相同,当横竖斜线上相同色超过3个时,即可消色,否则色块越堆越高,堆到顶你就输了。
由于windows控制台模式,颜色方块较小,很多颜色相近的区分起来较困难,程序里对不同颜色方块都有相应的颜色号,同时为对准底部相同色,程序里还加了对准线,方便玩家游戏。先上效果图
程序代码:
[mw_shl_code=c,true]/*******************************************
* 消三连色(Windows系统)C代码 *
* 程序媛:xzlxzlxzl *
* 仅供学习,转载请注明作者 *
* 2017.3 *
********************************************/
#include "stdafx.h" //在vs、vc中可用,gcc编译器可注释掉
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
#include <conio.h>
#define framex 30 //图形框左边距
#define Rows 11 //游戏区域宽度,宽度可调整,太宽游戏难度则低
struct
{
int rol,col,birth,m[3];
}rndcolor,putcolor; //定义两个结构体,一个用于存储随机色,一个用于游戏场景
struct
{
char name[10];
int score;
long tt;
int crc;
}tempscore,scorefile[5]; //用于存储游戏成绩
int playmap[Rows][23]; //游戏场景
int playSpeed,pauseFlg; //游戏速度及暂停标志
int colorCount,Score; //颜色计数和成绩
float scopro; //成绩调整比例,消分速度越快,成绩越高
void setColor(int ForeColor,int BackColor)
{//设置字符前景色和底色,ForeColor:字色,BackColor:背景色,基本颜色0-7,8-15是亮度加强的基本色
HANDLE hConsole = GetStdHandle((STD_OUTPUT_HANDLE)) ;
SetConsoleTextAttribute(hConsole,BackColor*16+ForeColor) ;
}
void setCursor(int flg)
{ //设置光标,flg=1:显示光标 flg=0:隐藏光标
HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursor_info={100,flg};
SetConsoleCursorInfo(hOut,&cursor_info);
}
void setLocate(int x,int y)
{//设置字符显示位置
HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
COORD loc={x,y};
SetConsoleCursorPosition(hOut,loc);
}
void drawFrame(int x,int w)
{//画外框
int i,j;
setColor(7,15); //白底灰字
for(i=0;i<25;i++)
{
for(j=x;j<x+w;j++)
{
setLocate(j,i);
if(i==0||i==24||j==x||j==x+w-1)printf("#");
}
}
setLocate(x+7,24);
printf(" 制作:xzlxzlxzl ");
}
void drawplay()
{//画游戏场景数据
int i,j,f=1;
if(playmap[putcolor.rol][putcolor.col+2])f=0;
else
for(i=0;i<3;i++)playmap[putcolor.rol][putcolor.col+i]=putcolor.m;; //将游戏色块加入游戏场景
for(i=0;i<Rows;i++)
{
for(j=0;j<23;j++)
{
if(playmap[j])
{
setLocate(framex+i*2,j+1);
setColor(playmap[j],playmap[j]+8);
printf("%c%c",162,playmap[j]+215); //画带编号的色块
}
else
{
setLocate(framex+i*2,j+1);
setColor(9,1);
if(i==putcolor.rol&&j>putcolor.col+2&&pauseFlg)printf("┊"); //画瞄准线
else printf(" ");
}
}
}
if(f) for(i=0;i<3;i++)playmap[putcolor.rol][putcolor.col+i]=0;; //将游戏场景的游戏色块清除,便于后续操作
}
void getRndcolor()
{//产生随机颜色色块,并显示在游戏框右上
int i;
for(i=0;i<3;i++)
{
rndcolor.m=rand()%5+2;
setLocate(Rows*2+framex+2,i+1);
setColor(rndcolor.m,rndcolor.m+8);
printf("%c%c",162,rndcolor.m+215);
}
rndcolor.rol=Rows/2;
rndcolor.col=0;
rndcolor.birth=clock(); //随机色块出生时间,用于计算得分,出生到消失时间越短,分数越高
}
void dispMenu()
{//显示菜单
setColor(14,8);
setLocate(5,1);printf(" %s","移动:← → ");
setLocate(5,2);printf(" %s","换色:↑ ");
setLocate(5,3);printf(" %s","暂停:P键 ");
setLocate(5,4);printf(" %s","直达:↓ ");
setLocate(5,5);printf(" %s","重玩:R键 ");
setLocate(5,6);printf(" %s","退出:Esc键 ");
}
int moveColor(int x,int y)
{//移动色块
int i;
if(x<0||x>Rows-1||y+3>23)return 0; //坐标不合法
i=playmap[x][y]+playmap[x][y+1]+playmap[x][y+2];
if(i>0)return 0;
putcolor.rol=x;
putcolor.col=y;
return 1;
}
void flash(int a[][23],int b[][23])
{//消色闪烁
int i,j,n=3;
putcolor.m[0]=putcolor.m[1]=putcolor.m[2]=0;
while(n--)
{
drawplay();
Beep(440,50);
for(i=0;i<Rows;i++)
for(j=0;j<23;j++)
playmap[j]=b[j];;
drawplay();
Beep(550,50);
for(i=0;i<Rows;i++)
for(j=0;j<23;j++)
playmap[j]=a[j];;
}
}
int delc(int a[][23],int rol,int col,int c,int s,int n)
{//消色递归
int j,b[4][2]={0,1,1,0,1,-1,1,1};
if(col<0||col>22||rol>Rows-1||playmap[rol][col]!=c)return n-1;
j=delc(a,rol+b[0],col+b[1],c,s,n+1);
if(a[rol][col]<j)a[rol][col]=j;
return j;
}
void delcolor()
{//消连续超过3个的横向、斜向、竖向同色色块
int i,j,k,k1,l,a[Rows][23],b[Rows][23];
for(i=0;i<Rows;i++)
for(j=0;j<23;j++)a[j]=0;;
for(i=0,k=0;i<Rows;i++)
{
for(j=0;j<23;j++)
{
b[j]=playmap[j];
if(playmap[j])
for(l=0;l<4;l++)delc(a,i,j,playmap[j],l,1);;
if(a[j]>2)
{
playmap[j]=0;
k++;
}
a[j]=playmap[j];
}
}
if(k)
{//对同色进行消色,递归自己直到没有颜色可消
flash(a,b);
for(i=0;i<Rows;i++)
{
for(j=23,l=22;j;j--)
if(playmap[j-1])
{
playmap[l]=playmap[j-1];
if(j-1<l)playmap[j-1]=0;
l--;
}
}
Score=Score+k+k*scopro;
setColor(14,0);
setLocate(framex+Rows*2+2,22);
printf("成绩:%d",Score); //根据消色数量和消色速度得到成绩并在指定位置显示成绩
delcolor(); //这里递归,直到无色可消
drawplay();
}
}
int getkey()
{//获得键值
unsigned char a;
int n=0;
if(!kbhit())return 0;
a=getch();
if(a>127)
{
n=a*256;
a=getch();
}
n=n+a;
return n;
}
int crc(int p)
{
int i,j=0;
for(i=0;scorefile[p].name&&i<10;i++)j+=scorefile[p].name;
j^=scorefile[p].score;
j^=scorefile[p].tt;
if(!scorefile[p].score)j=scorefile[p].crc;
return j;
}
void sortscore()
{//成绩排序
int i,j;
for(i=0;i<4;i++)
{
for(j=i+1;j<5;j++)
{
if(scorefile.score<scorefile[j].score)
{
tempscore=scorefile;
scorefile=scorefile[j];
scorefile[j]=tempscore;
}
}
}
setColor(15,9);
setLocate(1,14);printf(" 成绩单 ");
setColor(15,4);
for(i=0,j=15;i<8;i++)
{
setLocate(1,j+i);printf(" ");
if(i&&i<6&&scorefile[i-1].score)
{
setLocate(2,j+i);printf("%s",scorefile[i-1].name);
setLocate(16,j+i);printf("%d",scorefile[i-1].score);
}
}
}
void savescore()
{//存储游戏成绩
FILE *f;
if((f=fopen("score.dat","wb"))==NULL)return;
fwrite(scorefile,sizeof(scorefile),1,f);
fclose(f);
}
void loadscore()
{//读取游戏成绩
int i,j;
FILE *f;
for(i=0;i<5;i++)scorefile.score=0;
if((f=fopen("score.dat","rb"))==NULL)return;
fread(scorefile,sizeof(scorefile),1,f);
fclose(f);
for(i=0;i<5;i++)
{
if(crc(i)!=scorefile.crc)scorefile.score=0;
}
sortscore();
}
void gameover()
{//游戏结束,这里可使用文件存储游戏排名
int i;
if(Score>scorefile[4].score)
{
setColor(10,8);
setLocate(framex+1,10);
printf(" 新记录,请输入姓名 ");
setLocate(framex+1,11);
setCursor(1);
for(i=0;i<8;i++)
{
scorefile[4].name=getchar();
if(scorefile[4].name==10)break;
}
scorefile[4].name=0;
scorefile[4].score=Score;
scorefile[4].crc=crc(4);
sortscore();
savescore();
setCursor(0);
}
pauseFlg=0;
setColor(10,8);
setLocate(framex+1,10);
printf(" ********************* ");
setLocate(framex+1,11);
printf(" * Game Over * ");
setLocate(framex+1,12);
printf(" ********************* ");
}
void init()
{//初始化,这里可用文件读出游戏成绩排名
int i,j;
for(i=0;i<Rows;i++)
for(j=0;j<23;j++)
playmap[j]=0;;
playSpeed=600;
colorCount=0;
Score=0;
pauseFlg=0;
rndcolor.m[0]=rndcolor.m[1]=rndcolor.m[2]=0;
putcolor=rndcolor; //初始化游戏数据
srand(clock()); //初始化随机函数
setCursor(0); //隐藏光标
dispMenu(); //显示操作菜单
setColor(7,15); //白底灰字
drawFrame(framex-1,Rows*2+2); //画边框
drawplay(); //画游戏区域
setColor(14,2);
setLocate(framex+1,10);
printf(" 按回车键开始游戏 ");
setColor(14,0);
setLocate(framex+Rows*2+2,22);
printf("成绩: ");
loadscore();
}
void playgame()
{
int key=0,t,c,i;
while(key!=27) //按Esc键退出循环
{
key=getkey();
if(key=='p'||key=='P'||key==32)pauseFlg=!pauseFlg; //空格键和P键均可设置游戏暂停
if(key=='r'||key=='R'||(!pauseFlg&&key==13))
{//重新玩游戏
init();
pauseFlg=1;
getRndcolor();
putcolor=rndcolor;
drawplay();
getRndcolor();
t=clock();
}
if(!pauseFlg&&key!=27)key=0; //如果是暂停状态,后面的按键均不需要处理
c=0;
if(key==57419)c=moveColor(putcolor.rol-1,putcolor.col); //左移
if(key==57421)c=moveColor(putcolor.rol+1,putcolor.col); //右移
if(key==57416)
{//颜色上移一次
c=putcolor.m[0];
putcolor.m[0]=putcolor.m[1];
putcolor.m[1]=putcolor.m[2];
putcolor.m[2]=c;
}
if(key==57424)
{//直达
for(;!playmap[putcolor.rol][putcolor.col+3]&&(putcolor.col+3)<23;putcolor.col++);
t=0;
}
if((clock()-t)>playSpeed&&pauseFlg)
{//时间到,下移一格。难度逐渐增加,时间间隔越来越短
t=clock();
if(!moveColor(putcolor.rol,putcolor.col+1))
{
for(i=0;i<3;i++)playmap[putcolor.rol][putcolor.col+i]=putcolor.m;; //将游戏色块加入游戏场景
scopro=1000.0/(clock()-putcolor.birth+1);
Beep(110,50);
delcolor(); //此处加入消色和计成绩函数
putcolor=rndcolor;
getRndcolor();
if(++colorCount>50)
{
if(playSpeed>100)playSpeed-=100; //提升难度
colorCount=0;
}
}
c=1;
}
if(c&&pauseFlg)drawplay();
if(pauseFlg&&!moveColor(putcolor.rol,putcolor.col))gameover(); //通过色块是否能够原位叠加来判断游戏是否结束
}
setCursor(1); //退出游戏还原光标
}
void main()
{
init();
playgame();
}[/mw_shl_code]
|
|