C++项目实战-小游戏-连连看(CUI)

简介

最近在学可视化程序设计,选定的项目是做一个小游戏——连连看,本篇主要整理下该游戏的控制台窗口实现过程。

程序框架

main.cpp	//整个程序的入口

gamedata.h	//管理游戏数据
gamedata.cpp

gameview.h	//管理游戏界面
gameview.cpp

gamerule.h	//管理游戏规则
gamerule.cpp

因为实现过程比较简单,只贴出最终代码

main.cpp
#include <cstdlib>
#include <iostream>

#include "gamedata.h"
#include "gameview.h"
#include "gamerule.h"

using namespace std;

int main(int argc, char *argv[])
{
    //生成游戏数据
    GameData data;
    data.initData();
    
    //循环 
    int x1,y1,x2,y2;
    while(true)
    {
        //显示游戏界面
        GameView view;
        view.display();
        //用户输入坐标
        for(int j=0; j<(80-4*COL)/2; ++j)
        {
            cout<<" ";
        }
        cout<<"请输入要消除的坐标(x1 y1 x2 y2):";
        cin>>x1>>y1>>x2>>y2;
        //判断能否消除,如果可以,消除之 
        GameRule rule;
        if( rule.canClear(x1,y1,x2,y2) )
        {
            gameData[y1][x1] = 0;
            gameData[y2][x2] = 0;    
        }
    }
    system("PAUSE");
    return EXIT_SUCCESS;
}

gameview.h
class GameView
{
public:

    /***************************************************************
    *函数名:displayTitle 
    *用  途:显示游戏标题 
    *参  数:无 
    *返回值:无
    ****************************************************************/
    void displayTitle();
       
    /***************************************************************
    *函数名:display 
    *用  途:显示游戏界面 
    *参  数:无 
    *返回值:无
    ****************************************************************/
    void display();   
};

gameview.cpp
#include "gameview.h"

#include <iostream>

#include "gamedata.h"

using namespace std;

void GameView::displayTitle()
{
     cout<<"                      ***********************************"<<endl;
     cout<<"                      *      连连看游戏 ver0.1.0        *"<<endl;
     cout<<"                      *                                 *"<<endl;
     cout<<"                      *      UI设计  :赖炜             *"<<endl;
     cout<<"                      *                                 *"<<endl;
     cout<<"                      ***********************************"<<endl;
     cout<<endl;     
}

void GameView::display()
{
     system("cls");                        //执行系统清屏命令                                              
     displayTitle();
     for(int i=0; i<ROW; ++i)
        {
             for(int j=0; j<(80-4*COL)/2; ++j)
             {
                 cout<<" ";
             }
             
             for(int j=0; j<COL; ++j)
             {
                 //如果数字为0,说明已经消除,输出空格代替 
                 if(gameData[i][j]==0)
                 {
                     cout<<"    ";
                 } 
                 else 
                 {
                     //cout<<gameData[i][j];
                     printf("%4d",gameData[i][j]);
                 }
             }
             cout<<endl;
        }
}

gamedata.h
const int ROW = 4;      //游戏界面总行数 
const int COL = 4;      //游戏界面总列数 
extern int gameData[ROW][COL];

class GameData
{      
public:
    /***************************************************************
    *函数名:initData 
    *用  途:初始化游戏数据,存入数组。确保数字成对出现,顺序混乱 
    *参  数:无 
    *返回值:无
    ****************************************************************/
    void initData();
};

gamedata.cpp
#include "gamedata.h"

#include <cstdlib>
#include <iostream>

int gameData[ROW][COL];

void GameData::initData()
{   
   //成对产生数据
   int number = 0;
   for(int i=0; i<ROW; ++i)
   {
       for(int j=0; j<COL; ++j)
       {
           gameData[i][j] = number/2+1;
           ++number;    
       }
   }
   //打乱顺序 
   srand(time(NULL));   //使用当前系统时间作为随机数种子 
   for(int i=0; i<ROW*COL/2; ++i)
   {
       //随机得到两个数的坐标
       int x1 = rand()%COL;
       int y1 = rand()%ROW;
       int x2 = rand()%COL;
       int y2 = rand()%ROW;
       
       int temp = gameData[y1][x1];
       gameData[y1][x1] = gameData[y2][x2];
       gameData[y2][x2] = temp;
   }
}

gamerule.h
class GameRule
{
private:
    /***************************************************************
    *函数名:connect0 
    *用  途:判断给定的两个坐标处的数能否不转变连通 
    *参  数:int x1 - 第一个数的横坐标 
    *        int y1 - 第一个数的纵坐标
    *        int x2 - 第二个数的横坐标
    *        int y2 - 第二个数的纵坐标
    *返回值:如果可以不转变连通,返回true;否则返回false 
    ****************************************************************/
    bool connect0(int x1, int y1, int x2, int y2);

    /***************************************************************
    *函数名:connect1 
    *用  途:判断给定的两个坐标处的数能否不转变连通 
    *参  数:int x1 - 第一个数的横坐标 
    *        int y1 - 第一个数的纵坐标
    *        int x2 - 第二个数的横坐标
    *        int y2 - 第二个数的纵坐标
    *返回值:如果可以不转变连通,返回true;否则返回false 
    ****************************************************************/
    bool connect1(int x1, int y1, int x2, int y2);


public:
    /***************************************************************
    *函数名:canClear 
    *用  途:判断给定的两个坐标处的数能否消除 
    *参  数:int x1 - 第一个数的横坐标 
    *        int y1 - 第一个数的纵坐标
    *        int x2 - 第二个数的横坐标
    *        int y2 - 第二个数的纵坐标
    *返回值:如果可以消,返回true;否则返回false 
    ****************************************************************/
    bool canClear(int x1, int y1, int x2, int y2);
};

gamerule.cpp
#include "gamerule.h"
#include "gamedata.h"

bool GameRule::canClear(int x1, int y1, int x2, int y2)
{
    //如果两次选择的坐标相同,不能消
    if( x1 == x2 && y1 == y2 )
    {
        return false;
    }
     
    //如果两个数字不一样,不能消
    if(gameData[y1][x1]!=gameData[y2][x2])
    {
        return false;
    }
     
    //如果可以不转弯连通 
    if( connect0(x1,y1,x2,y2) )
    {
        return true;
    }
    
    //如果可以转一次弯连通
    if( connect1(x1,y1,x2,y2) )
    {
        return true;
    } 
    
    return false;
}  
    
bool GameRule::connect0(int x1, int y1, int x2, int y2)
{
    //如果在同一行
    if(y1 == y2)
    {
        int y = y1;
        //循环遍历中间所有数的坐标,累加
        int sum = 0;
        //确保x1一定小于x2
        if(x1>x2)
        {
            int temp = x1;
            x1 = x2;
            x2 = temp;        
        } 
        for(int x=x1+1; x<x2; ++x)
        {
            sum += gameData[y][x];        
        } 
        if(0==sum)      //说明中间所有数都为0
        {
            return true;
        } 
    }  
    //如果在同一列
    if(x1 == x2)
    {
        int x = x1;
        //循环遍历中间所有数的坐标,累加
        int sum = 0;
        //确保y1一定小于y2
        if(y1>y2)
        {
            int temp = y1;
            y1 = y2;
            y2 = temp;        
        } 
        for(int y=y1+1; y<y2; ++y)
        {
            sum += gameData[y][x];        
        } 
        if(0==sum)      //说明中间所有数都为0
        {
            return true;
        } 
    }  
     
    return false;            
}

bool GameRule::connect1(int x1, int y1, int x2, int y2)
{
    //通过x2,y1转
    // (x1,y1)~(x2,y1) && (x2,y1)~(x2,y2) && (x2,y1)==0
    if(connect0(x1,y1,x2,y1) && connect0(x2,y1,x2,y2) && gameData[y1][x2]==0 )
    {
        return true;
    }
    
    //通过x1,y2转 
    if(connect0(x1,y1,x1,y2) && connect0(x1,y2,x2,y2) && gameData[y2][x1]==0)
    {
        return true;                         
    }
    
    return false;
}




原文地址:https://www.cnblogs.com/tryitboy/p/4231156.html