应天论坛

 找回密码
 参与我们

QQ登录

只需一步,快速开始

搜索
查看: 753|回复: 0

C语言游戏:消三连色

[复制链接]

68

主题

72

帖子

451

积分

少校

勘查大队长

Rank: 6Rank: 6

积分
451
发表于 2017-4-28 19:54:01 | 显示全部楼层 |阅读模式
该游戏类似于俄罗斯方块,游戏规则是:电脑随机出逐渐下落的三个色块,你通过左右移动该色块,尽量让横、竖、斜线上的颜色相同,当横竖斜线上相同色超过3个时,即可消色,否则色块越堆越高,堆到顶你就输了。
由于windows控制台模式,颜色方块较小,很多颜色相近的区分起来较困难,程序里对不同颜色方块都有相应的颜色号,同时为对准底部相同色,程序里还加了对准线,方便玩家游戏。先上效果图

20170319_bdd1aae1e090704616deDTuFgFfSndli.jpg

程序代码:
[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]
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 参与我们

本版积分规则

QQ|Archiver|手机版|小黑屋|应天社区 ( 湘ICP备17015224号 )

GMT+8, 2024-12-22 18:38 , Processed in 0.078125 second(s), 28 queries .

Powered by Discuz!

© 2001-2017 Comsenz Inc.


免责声明:
本站所发布的第三方软件及资源(包括但不仅限于文字/图片/音频/视频等仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢某程序或某个资源,请支持正版软件及版权方利益,注册或购买,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To: admin@yzqz.cn

快速回复 返回顶部 返回列表