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