IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C++】2048游戏系列—优化模块第四稿【补充整理】 -> 正文阅读

[C++知识库]【C++】2048游戏系列—优化模块第四稿【补充整理】

2048-优化篇四稿-激活最高分数输出【补充文件操作】

(更新中……)
参考博客:https://blog.csdn.net/qq_39151563/article/details/104283217
目前写完的:

补充之前遗漏的(历史)最高分数输出,重点是文件操作

一、基本文件操作模板

看了很多关于C++文件操作的博客,感觉C++没有C好用,所以还是用C的文件操作格式,C++中可以用C的代码

#include <iostream>
using namespace std;
const char FILE_NAME[10] = "test.txt";

int main()
{
	//利用 fprintf 函数向文件中写入格式化数据 
	FILE* fp = fopen(FILE_NAME,"w");//"w"表示 write,写 
	fprintf(fp,"这是一个测试,输入:%d",30);
	fclose(fp); 
	
	//利用 fscanf 函数从文件中读取格式化数据(相当于匹配)
	int a = 0; 
	fp = fopen(FILE_NAME,"r"); //"r"表示 read,读
	fscanf(fp,"这是一个测试,输入:%d",&a);
	cout << a << endl; 
	
	return 0;
} 

二、激活最高分数输出

重点在于记录下历史最高分,所以涉及到文件操作

2.1-上篇类封装后的代码总览

图中画红线的部分就是要改的部分:
1.游戏开始时通过LoadRecord()函数读取历史最高分数给m_TopSocre
2.每一次合并数字后判断当前分数是否大于历史最高分数(在Move()函数中),如果大于,通过GameSave()函数保存最高分数
3.绘制图像时读取m_TopSocre

代码总览

2.2-GameSave()LoadRecord()函数

具体细节请参考后面的全部代码

const char RECORD_FILE_NAME[15] = "RECORD.txt";//存档文件名 (ConstDate.h中)

void Game2048::GameSave()//游戏保存
{
	FILE* fp = fopen(RECORD_FILE_NAME,"w");
	if(fp==NULL)
	{
		this->RestartDate();
		fclose(fp);
		return;
	}
	fprintf(fp,"TopSocre:%d",this->m_TopScore);
	fclose(fp);	
} 

void Game2048::LoadRecord()//读档
{
	FILE* fp = fopen(RECORD_FILE_NAME,"r");
	if(fp==NULL)
	{
		this->RestartDate();
		fclose(fp);
		return;
	}
	fscanf(fp,"TopSocre:%d",&this->m_TopScore);
	fclose(fp);
}

三、删除不必要的代码

  • 删除与// void PrintGrid();//打印函数,void ShowInfo();//显示信息 两个函数有关的代码
  • 项目->项目设置->Win32图形界面程序(这样就没有控制台了)

四、全部代码和运行结果

录的时候还没删除相关代码和改设置

运行结果

#ifndef CONST_DATE_H
#define CONST_DATE_H

const char RECORD_FILE_NAME[15] = "RECORD.txt";//存档文件名 

const int DEVIDE = 15;					//间隔 
const int GRID_WIDTH = 106;				//格子宽 

const int WIDTH  = 500+2*DEVIDE;		//总界面宽 
const int HEIGHT = 660+3*DEVIDE; 		//总界面高 

const int BOARD_X = 0+DEVIDE;			//棋盘起始点x
const int BOARD_Y = 160+2*DEVIDE;		//棋盘起始点y
const int LOGO_X = 25+DEVIDE;			//2048logo起始点x 
const int LOGO_Y = 20+DEVIDE;			//2048logo起始点y

const int RESTART_X = 0+DEVIDE;			//restart起始点x
const int RESTART_Y = 80+LOGO_Y;		//restart起始点y
const int RESTART_WIDTH = 220;			//restart 宽度
const int RESTART_HEIGHT = 50;			//restart 高度 
 
const int SCOREGB_X = 230+DEVIDE;		//分数背景图起始点x 
const int SCOREGB_Y = 0+DEVIDE; 		//分数背景图起始点y 

const color_t TEXT_COLOR = EGERGB(241, 231, 214); //字体颜色
const color_t BG_COLOR = EGERGB(250,248, 239);//背景颜色淡黄色 

const int MAXVALUE_X = SCOREGB_X+160;	//最大值起始点x 
const int MAXVALUE_Y = SCOREGB_Y+112; 	//最大值起始点y 

const int SCORE_X = MAXVALUE_X;			//本次分数起始点x 
const int SCORE_Y = MAXVALUE_Y-45;		//本次分数起始点y 

const int TOP_SCORE_X = SCORE_X;		//最高分数起始点x 
const int TOP_SCORE_Y = SCORE_Y-45;		//最高分数起始点y 

/*-----------------------------------------------------------*/ 
//移动函数中使用 
static int x0[4] = {0, 0, 3, 0};
static int y0[4] = {0, 0, 0, 3};
static int firstOffset[4][2]  = {{1,0},{0,1},{-1,0},{0,-1}};
static int secondOffset[4][2] = {{0,1},{1,0},{0,1} ,{1,0}};
/*-----------------------------------------------------------*/ 
/*-----------------------------------------------------------*/ 
//图片存储 
PIMAGE BlockImgs[18];//0-背景图,1-17数字图 
PIMAGE GameOverImg;//游戏结束图 
PIMAGE GameLogoImg;//游戏 Logo 图 
PIMAGE RestartImg;//重新开始图
PIMAGE AIImg;//AI按键图 
PIMAGE ScoreBgImg;//分数背景图 
/*-----------------------------------------------------------*/
#endif	//CONST_DATE_H
#include <iostream>
#include "graphics.h"
#include <cmath>
//#include <fstream> 
#include "ConstDate.h"

using namespace std;
int Grid[4][4] = {0};			//【全局变量】4*4矩阵

class Game2048{
	//private:
	public:
		int m_Dir;								// 方向:0-左,1-上,2-右,3-下 
		int m_EmptyBlock;		//空格数 
		int m_Score;			//记录分数 
		int m_MaxValue;			//记录合成的最大值
		int m_TopScore;			//记录最高分数 
		
	public:
		Game2048();//初始化 
		int CalculateEmpty();//计算空格函数 	
		int GetMaxValue();//计算合成的最大值 
		void Move(int dir);//移动函数 
		void Addnum(int n);//添加新数
		void LoadImgs();//加载图片
		void ReleaseImgs();//释放图片 
		void Draw();//绘制图像 
		bool isGameOver();//判断游戏结束 
		void RestartDate();//重新开始
		bool isClicInRectangle(int xClick,int yClick,int Rectangle_X,int Rectangle_Y,
                       int Rectangle_WIDTH,int Rectangle_HEIGHT);//检测是否点击在矩形区域内
		void GameSave();//游戏保存 
		void LoadRecord();//读档
		void AI();//AI自动到2048 
		
};

int main()
{
/*初始化-------------------------------------------------------------------------------*/ 
	initgraph(WIDTH, HEIGHT);
	setcaption("2048Game");								//设置游戏标题 
	setbkcolor(BG_COLOR); 
	setfont(25,0,"黑体");  
	setbkmode(TRANSPARENT);								//文字输出为透明 
	
	Game2048 MainObj; 
	MainObj.Addnum(2); 									//在随机2个位置添加新数 
	MainObj.m_MaxValue = MainObj.GetMaxValue();			//更新最大值 
	MainObj.LoadImgs();									//加载图片 
	MainObj.LoadRecord();
	MainObj.Draw(); 									//画出初始界面 
/*-------------------------------------------------------------------------------初始化*/ 

/*开始游戏-------------------------------------------------------------------------------*/ 	  
    for ( ; is_run(); delay_fps(60) )
	{	
		//按键检测	
		while(kbmsg())
		{
		    key_msg keyMsg = getkey();
		    if(keyMsg.msg == key_msg_down)
		    {
		        switch(keyMsg.key)
		        {
		            case 'A':case key_left  : MainObj.m_Dir = 0; break;//左 
		            case 'W':case key_up  	: MainObj.m_Dir = 1; break;//上 
		            case 'D':case key_right : MainObj.m_Dir = 2; break;//右 
		            case 'S':case key_down	: MainObj.m_Dir = 3; break;//下 
		        }
		    }
		}   
		if(MainObj.m_Dir!=-1)
		{
		    //图形更新           
		    bool flag = false;    //移动标志位 
			int tempGrid[4][4];	 //暂存数组 
			int i,j; 
			for(i=0;i<4;i++)
				for(j=0;j<4;j++)
					tempGrid[i][j] = Grid[i][j];
			MainObj.Move(MainObj.m_Dir);
			//比较 
			for(i=0; i<4; i++)
				for(j=0; j<4; j++)
					if(Grid[i][j]!=tempGrid[i][j])	
					{
						flag = true;
						break;
					} 
			if(flag)	MainObj.Addnum(1);	
			MainObj.Draw();
			MainObj.m_Dir = -1;//将 Dir 置为无效
		}
		
		//鼠标检测 
		bool RestartClickflag = false;
		while (mousemsg())
	    {
				mouse_msg msg = getmouse();
	    		if (msg.is_left() && msg.is_down()&&
					MainObj.isClicInRectangle(msg.x,msg.y,RESTART_X,RESTART_Y,RESTART_WIDTH,RESTART_HEIGHT))
	    		{
	                RestartClickflag = true;
	    		} 
	    }
	    	    
	    if(RestartClickflag)
	    {
	       MainObj.RestartDate();
	       MainObj.Draw();
	    }
	    
		if(MainObj.isGameOver())
		{
			putimage_withalpha(NULL,GameOverImg,120,200);
			break;
		}		
	} 
/*------------------------------------------------------------------------------开始游戏-*/ 
	MainObj.ReleaseImgs();
	getch();
    closegraph();  
    return 0;	
} 

Game2048::Game2048()//初始化 
{
	this->m_Dir = -1;
	this->m_EmptyBlock = 16;
	this->m_MaxValue = 0;
	this->m_Score = 0;
	this->m_TopScore = 0;
} 

int Game2048::CalculateEmpty()//计算空格函数 
{
	int cnt = 0;
    for(int i=0; i<4; i++)
        for(int j=0; j<4; j++)
            if(Grid[i][j]==0)   cnt++;
    return cnt;
} 

int Game2048::GetMaxValue()//计算合成的最大值 
{
	int temp=0;
	for(int i=0; i<4; i++)
		for(int j=0; j<4; j++)
		{
			if(Grid[i][j]>temp)	temp = Grid[i][j];
		}
	return temp;
}

void Game2048::Move(int dir)//移动函数 
{
	if(dir==-1)	return;
    int tx, ty;
    int t1x, t1y;
    int t2x, t2y;
    for(int i=0; i<4; i++)
    {
        tx = x0[dir] + i*secondOffset[dir][0];
        ty = y0[dir] + i*secondOffset[dir][1];

        t1x = tx;
        t1y = ty;
        
        t2x = tx + firstOffset[dir][0]; 
        t2y = ty + firstOffset[dir][1];
        for( ;t2x>=0&&t2x<=3&&t2y>=0&&t2y<=3; t2x+=firstOffset[dir][0],t2y+=firstOffset[dir][1])
        {
            if(Grid[t2y][t2x]!=0)
            {
                if(Grid[t1y][t1x]==0)
                {
                    Grid[t1y][t1x] = Grid[t2y][t2x];
                    Grid[t2y][t2x] = 0;
                }
                else if(Grid[t1y][t1x]==Grid[t2y][t2x])
                {
                	
                    Grid[t1y][t1x]++;//合并 
                    
                    this->m_MaxValue = this->GetMaxValue();
                    this->m_Score += (int)pow(2,Grid[t1y][t1x]); 
                    if(this->m_TopScore<this->m_Score)
                    {
                    	this->m_TopScore = this->m_Score;
                    	this->GameSave();
					} 
					                  
                    Grid[t2y][t2x] = 0;
                    t1x += firstOffset[dir][0];
                    t1y += firstOffset[dir][1];
                   // moved = true;
                }
                else if(t1x+firstOffset[dir][0]!=t2x||t1y+firstOffset[dir][1]!=t2y)
                {
                    Grid[t1y+firstOffset[dir][1]][t1x+firstOffset[dir][0]] = Grid[t2y][t2x];
                    Grid[t2y][t2x] = 0;
                    t1x += firstOffset[dir][0];
                    t1y += firstOffset[dir][1];
                    //cout << "Move Test" << endl;
                   // moved = true;
                }
                else
                {
                    t1x += firstOffset[dir][0];
                    t1y += firstOffset[dir][1];
                }
            }
            
        }
    }
    //return moved;
}

void Game2048::Addnum(int n)//添加新数
{
	while(n--)//添加n个
	{
		this->m_EmptyBlock = this->CalculateEmpty();
		if(this->m_EmptyBlock<=0)	return;		
		int cnt = random(this->m_EmptyBlock)+1;//随机得到一个空格数以内的数	
		int *p = &Grid[0][0]-1;//记录矩阵首地址前一个 ,因为后面的 p 在找到时还会 ++ 
		for(int i=0; i<4&&cnt; i++)
			for(int j=0; j<4&&cnt; j++)
			{
				if(Grid[i][j]==0 && cnt)//如果有空格并且cnt有效	
				{
					cnt--;//找到一个划一个
				}
                p++;//p 指向下一个再进行判断
			}
        //循环结束时 p 指向我们之前随机指定的空格
		*p = (random(10)==0)?2:1;// 0.1 的概率为2,0.9 的概率为1
		//*p = (random(10)==0)+1;//这样写也可以
		this->m_EmptyBlock--;
	}
}

void Game2048::LoadImgs()//加载图片
{
	char imgAdress[40];
	for(int i=1,num=2; i<18; i++,num*=2)
	{	
		sprintf(imgAdress,"..\\image\\block_%d.png",num);
		BlockImgs[i] = newimage();;
      	getimage(BlockImgs[i], imgAdress);
		//cout << imgAdress << endl;
	}
	BlockImgs[0] = newimage();
	GameOverImg = newimage();
	GameLogoImg = newimage();
	RestartImg = newimage();
	ScoreBgImg = newimage();
	getimage(BlockImgs[0], "..\\image\\background.png");	
	getimage(GameOverImg,  "..\\image\\gameOver.png");
	getimage(GameLogoImg,  "..\\image\\gamelogo.png"); 
	getimage(RestartImg,   "..\\image\\restart.png");
	getimage(ScoreBgImg,   "..\\image\\scorebg.png"); 
} 

void Game2048::ReleaseImgs()//释放图片 
{
	for(int i=0; i<18; i++)
	{
		delimage(BlockImgs[i]);
	}
	delimage(GameOverImg);
	delimage(GameLogoImg);
	delimage(RestartImg);
	delimage(ScoreBgImg);	
}

void Game2048::Draw()//绘制图像 
{
	cleardevice();
	putimage_withalpha(NULL, BlockImgs[0], BOARD_X,   BOARD_Y);//格子背景图 
	putimage_withalpha(NULL, GameLogoImg,  LOGO_X,    LOGO_Y);//Logo图 
	putimage_withalpha(NULL, RestartImg,   RESTART_X, RESTART_Y);//重新开始图 
	putimage_withalpha(NULL, ScoreBgImg,   SCOREGB_X, SCOREGB_Y);//计分背景图 
	
	//MaxValue = GetMaxValue();//更新最大值
	setcolor(TEXT_COLOR);
	xyprintf(MAXVALUE_X, MAXVALUE_Y, "%4d",(int)pow(2,this->m_MaxValue));//当前合成的最大数字 
	xyprintf(SCORE_X,    SCORE_Y,    "%4d",this->m_Score);//当前分数
	xyprintf(TOP_SCORE_X,TOP_SCORE_Y,"%4d",this->m_TopScore);//历史最高分数 

	for(int i=0;i<4;i++) 
	{	
		for(int j=0;j<4;j++)
		{
			int x = (j+1)*DEVIDE + j*GRID_WIDTH + BOARD_X ;
			int y = (i+1)*DEVIDE + i*GRID_WIDTH + BOARD_Y ;
			//cout << "(x,y) = " << "(" << x << ","<< y << ")" << endl;
			if(Grid[i][j]!=0)
			{
				putimage_withalpha(NULL,BlockImgs[Grid[i][j]],x,y);
			}
		}
	}
	
}

bool Game2048::isGameOver()//判断游戏结束 
{
	this->m_EmptyBlock = this->CalculateEmpty();
	if(this->m_EmptyBlock>0)	return false;
	for(int i=0;i<4;i++)
	{
		int t1=0,t2=1;
		while(t2<=3)
		{
			if(Grid[i][t1]==Grid[i][t2] || Grid[t1][i]==Grid[t2][i])//  横 ||纵 
			{
				return false;
			}
			else
			{
				t1++;
				t2++;
			}
		}
	}
	return true;
}

void Game2048::RestartDate()//重新开始
{
	for(int i=0; i<4; i++)
		for(int j=0; j<4; j++)
			Grid[i][j] = 0;
	Addnum(2);
	this->m_MaxValue = this->GetMaxValue();
	this->m_Dir = -1;
	this->m_EmptyBlock = 14;
	this->m_Score = 0;
	//this->m_TopScore = 0;	
} 
	
bool Game2048::isClicInRectangle(int xClick,int yClick,int Rectangle_X,int Rectangle_Y,int Rectangle_WIDTH,int Rectangle_HEIGHT)//检测是否点击在矩形区域内
{
	if(xClick>Rectangle_X&&xClick<Rectangle_X+Rectangle_WIDTH && 
       yClick>Rectangle_Y&&yClick<Rectangle_Y+Rectangle_HEIGHT)
	return true;
	return false;	
}
 
void Game2048::GameSave()//游戏保存
{
	FILE* fp = fopen(RECORD_FILE_NAME,"w");
	if(fp==NULL)
	{
		this->RestartDate();
		fclose(fp);
		return;
	}
	fprintf(fp,"TopSocre:%d",this->m_TopScore);
	fclose(fp);	
} 

void Game2048::LoadRecord()//读档
{
	FILE* fp = fopen(RECORD_FILE_NAME,"r");
	if(fp==NULL)
	{
		this->RestartDate();
		fclose(fp);
		return;
	}
	fscanf(fp,"TopSocre:%d",&this->m_TopScore);
	fclose(fp);
}

优化篇到这里就结束了!!!
感谢您看到这里。
这已经是一个相对完整的小项目了。
接下来是进阶篇
1. 滑块效果
2. AI 自动到2048

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-11 15:32:36  更:2021-12-11 15:34:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:08:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码