简介
最近在学可视化程序设计,选定的项目是做一个小游戏——连连看,本篇主要整理下该游戏的控制台窗口实现过程。
程序框架
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;
}
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();
};
#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;
}