2048纯手工制作
程序员文章站
2022-04-07 19:13:24
...
说明:
刚学完easyx.h的使用,做了一个2048小游戏
第一次制作,有些简陋,勿笑
游戏:C语言 2048自制版
使用开发软件:VS2010
游戏背景图来源于网络搜索
图片放于:工程文件夹/image/
重要库文件: graphics.h easyx.h
库文件安装来源:https://www.easyx.cn
工程适用编辑软件:vc6.0 vs2010 vs2012 等
作者信息:鼠瓜
工程代码:
/*
2048.cpp
*/
#include "2048.h"
void main()
{
initgraph(640, 480); // 创建绘图窗口
srand((unsigned)time(NULL)); // 设置随机种子
Welcome(); // 绘制游戏界面
InitImage(); // 初始化游戏图片
InitGame(); // 初始化游戏数据
char c;
// 游戏过程
while(1)
{
c=GetCmd(); //获取按键命令,并处理
if (c==27) //检测是否结束
{
if(Quit())
{
settextstyle(70, 50, _T("幼圆")); //设置字体样式
settextcolor(RED); //设置字体颜色
outtextxy(-200,152, _T("GAME OVER !!"));
break;
}
}
if(Checkover()) //检测是否结束
{
outtextxy(-200,152, _T("GAME OVER !!"));
_getch();
break;
}
}
// 关闭图形模式
closegraph();
}
/*
2048.h
*/
/*
游戏:C语言 2048自制版
使用开发软件:VS2010
游戏背景图来源于网络搜索
图片放于:工程文件夹/image/
使用重要库文件: graphics.h easyx.h
库文件安装来源:https://www.easyx.cn
工程适用编辑软件:vc6.0 vs2010 vs2012 等
作者信息:鼠瓜
拿走不用谢
请保留此处,敲代码不容易
*/
#include <graphics.h>
#include <time.h>
#include <stdio.h>
#include <conio.h>
#define W 640 //游戏界面宽
#define H 480 //游戏界面高
IMAGE g_imgSight(350, 350); // 游戏的视野
SIZE g_szMap; // 2048的格子数 //这是一个SIZE结构体,里面有 LONG cx; LONG cy;两个变量
struct gGEZI
{
int num; //格子的数字
COLORREF rgb; //格子的颜色
};
gGEZI Gnum[4][4]; //定义4*4的格子数
int oldnum[4][4]={0}; //存放未按按键时格子上的数字
int Score; //存放分数
TCHAR s[5]; //声明数组,用来存放字符串
IMAGE Clc; //分数更新清除背景图
//函数
void Welcome(); // 绘制游戏界面
void InitImage(); // 初始化游戏图片
void InitGame(); // 初始化游戏数据
void Paint(); // 绘制数值更新图
char GetCmd(); // 获取用户输入的命令
void DispatchCmd(int cmd); // 处理用户输入的命令
void OnUp(); // 向上移动
void OnLeft(); // 向左移动
void OnRight(); // 向右移动
void OnDown(); // 向下移动
void Randnum(); //随机产生新的数字
bool Checkover(); //检测是否结束
bool Quit(); // 询问用户是否退出游戏
void Welcome() // 绘制游戏界面
{
IMAGE back; //声明游戏界面背景图
loadimage(&back,_T("..\\image\\back.jpg"),W,H+40); //获取背景图
putimage(0,0,W, H, &back,0,0); //显示背景图
// 设置字体样式 白色 字体背景透明
settextcolor(BLACK);
setbkmode(TRANSPARENT);
// 绘制标题
settextstyle(36, 32, _T("宋体"));
outtextxy(150, 40, _T("2048自制版"));
settextstyle(30, 0, _T("幼圆"));
outtextxy(200, 100, _T("经典版"));
// 绘制操作说明
settextstyle(18, 0, _T("宋体"));
outtextxy(72,382, _T("控制说明:"));
outtextxy(56, 400, _T("A/S/D/W:移动"));
outtextxy(56, 420, _T("ESC:退出程序"));
//等待1000ms
Sleep(1000);
}
void InitImage() // 初始化游戏图片
{
cleardevice(); // 清屏
//绘制游戏背景
IMAGE gback;
loadimage(&gback,_T("..\\image\\dgback.jpg"),W,H);
putimage(0,0, &gback);
setorigin(250,65);// 设置坐标原点 145, 65
//画线条
//设置线条样式 实线
setlinestyle(PS_SOLID,1);
setlinecolor(RGB(128,128,0));//设置线条颜色
for(int i=0;i<5;i++)
{
for(int j=0;j<10;j++)
{
line(90*i+j, 0, 90*i+j,368);
line(0, 90*i+j, 368, 90*i+j);
}
}
//画格子
setfillcolor(RGB(85,85,0));
for(int i=0; i<4; i++)
{
for(int j=0;j<4; j++)
{
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
}
}
//绘制必要的文字
settextstyle(32, 0, _T("幼圆"));
outtextxy(-200, -60, _T("2048经典版"));
settextstyle(20, 15, _T("幼圆"));
outtextxy(50, -40, _T("得 分: 分"));
outtextxy(50, 380, _T("暂 停"));
outtextxy(150, 380, _T("继 续"));
outtextxy(250, 380, _T("退 出"));
settextstyle(18, 0, _T("宋体"));
outtextxy(-222,335, _T("控制说明:"));
outtextxy(-240,360, _T("A/S/D/W:移动"));
outtextxy(-240,380, _T("ESC:退出程序"));
//显示分数
Score=0;
swprintf(s, 5,_T("%d"), Score); //将整形score转换成字符串
settextstyle(40, 20, _T("微软雅黑")); //设置字体
settextcolor(YELLOW); // 设置文字颜色为黄色
getimage(&Clc,150,-50,200,40);
outtextxy(150, -50, s);
}
void InitGame() // 初始化游戏数据
{
int i,j;
//初始化格子数据
for( i = 0; i<4; i++)
{
for( j=0; j<4; j++)
{
Gnum[i][j].num=0;
Gnum[i][j].rgb=RGB(85,85,0); //数字为0时显示格子本身颜色
oldnum[i][j]=Gnum[i][j].num; //
}
}
//随机在一个格子产生初始数值 2 或4
i=rand()%4;
j=rand()%4;
Gnum[i][j].num=(rand()%2+1)*2; //产生随机数 2 或 4
oldnum[i][j]=Gnum[i][j].num; //更新oldnum的数值
Paint(); //绘制图像
}
void Paint() //绘制
{
settextcolor(WHITE); //设置文字颜色
for(int i = 0; i < 4; i++) //重新绘制一遍
{
for(int j = 0; j < 4; j++)
{
switch(Gnum[i][j].num) //
{
case 0:
{
//设置格子填充色
setfillcolor(RGB(85,85,0));
//填充格子
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
break;
}
case 2:
{
//设置格子填充色 下同
setfillcolor(RGB(128,64,0));
//填充格子 下同
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
//设置格子上的数字字体,大小 ,下同
settextstyle(70, 70, _T("幼圆"));
//输出文字 ,下同
outtextxy(80*i+10*(i+1)+5, 80*j+10*(j+1)+5, _T("2"));
break;
}
case 4:
{
setfillcolor(RGB(0,64,64));
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
settextstyle(70, 70, _T("幼圆"));
outtextxy(80*i+10*(i+1)+5, 80*j+10*(j+1)+5, _T("4"));
break;
}
case 8:
{
setfillcolor(RGB(0,128,128));
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
settextstyle(70, 70, _T("幼圆"));
outtextxy(80*i+10*(i+1)+5, 80*j+10*(j+1)+5, _T("8"));
break;
}
case 16:
{
setfillcolor(RGB(128,0,64));
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
settextstyle(40, 30, _T("幼圆"));
outtextxy(80*i+10*(i+1)+5, 80*j+10*(j+1)+20, _T("16"));
break;
}
case 32:
{
setfillcolor(MAGENTA);
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
settextstyle(40, 30, _T("幼圆"));
outtextxy(80*i+10*(i+1)+5, 80*j+10*(j+1)+20, _T("32"));
break;
}
case 64:
{
setfillcolor(RGB(0,255,255));
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
settextstyle(40, 30, _T("幼圆"));
outtextxy(80*i+10*(i+1)+5, 80*j+10*(j+1)+20, _T("64"));
break;
}
case 128:
{
setfillcolor(CYAN);
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
settextstyle(35, 20, _T("幼圆"));
outtextxy(80*i+10*(i+1)+10, 80*j+10*(j+1)+25, _T("128"));
break;
}
case 256:
{
setfillcolor(GREEN);
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
settextstyle(35, 20, _T("幼圆"));
outtextxy(80*i+10*(i+1)+10, 80*j+10*(j+1)+25, _T("256"));
break;
}
case 512:
{
setfillcolor(YELLOW);
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
settextstyle(35, 0, _T("幼圆"));
outtextxy(80*i+10*(i+1)+15, 80*j+10*(j+1)+35, _T("512"));
break;
}
case 1024:
{
setfillcolor(RGB(255,126,0));
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
settextstyle(25, 0, _T("幼圆"));
outtextxy(80*i+10*(i+1)+10, 80*j+10*(j+1)+35, _T("1024"));
break;
}
case 2048:
{
setfillcolor(RED);
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
settextstyle(25, 0, _T("幼圆"));
outtextxy(80*i+10*(i+1)+10, 80*j+10*(j+1)+35, _T("2048"));
break;
}
case 4096:
{
setfillcolor(RED);
solidrectangle(80*i+10*(i+1), 80*j+10*(j+1), 80*i+10*(i+1)+80, 80*j+10*(j+1)+80);
settextstyle(25, 0, _T("幼圆"));
outtextxy(80*i+10*(i+1)+10, 80*j+10*(j+1)+35, _T("4096"));
break;
}
}
}
}
//显示分数
putimage(150,-50,200,40,&Clc,0,0); //清除原来的分数
swprintf(s, 5,_T("%d"), Score); //将整形score转换成字符串
settextstyle(40, 20, _T("微软雅黑")); //设置字体
settextcolor(YELLOW); // 设置文字颜色为黄色
outtextxy(150, -50, s); //显示新的分数
}
// 获取用户输入的命令并处理
char GetCmd()
{
char c = 0;
if (_kbhit()) //判断是否有按键按下
{
Sleep(20); //延时
if (_kbhit())
{
c = _getch(); //获取所按下的按键
switch(c)
{
case 'w': OnUp();break; //向上
case 'a': OnLeft();break; //向左
case 's': OnDown(); break; //向下
case 'd': OnRight();break; //向右
case 27: break; //ESC键 退出
}
}
}
return c;
}
// 向上移动处理
void OnUp()
{
for(int i = 0; i < 4; i++ )
{
for(int j = 0; j < 3; j++)
{
if(Gnum[i][0].num==0)
{
Gnum[i][0].num=Gnum[i][1].num;
Gnum[i][1].num=Gnum[i][2].num;
Gnum[i][2].num=Gnum[i][3].num;
Gnum[i][3].num=0;
}
if(Gnum[i][1].num==0)
{
Gnum[i][1].num=Gnum[i][2].num;
Gnum[i][2].num=Gnum[i][3].num;
Gnum[i][3].num=0;
}
if(Gnum[i][2].num==0)
{
Gnum[i][2].num=Gnum[i][3].num;
Gnum[i][3].num=0;
}
}
}
for(int i = 0; i < 4; i++ )
{
if(Gnum[i][0].num == Gnum[i][1].num )
{
Gnum[i][0].num =Gnum[i][0].num+Gnum[i][1].num;
Gnum[i][1].num=Gnum[i][2].num;
Gnum[i][2].num=Gnum[i][3].num;
Gnum[i][3].num=0;
}
if(Gnum[i][1].num == Gnum[i][2].num )
{
Gnum[i][1].num =Gnum[i][1].num+Gnum[i][2].num;
Gnum[i][2].num=Gnum[i][3].num;
Gnum[i][3].num=0;
}
if((Gnum[i][2].num == Gnum[i][3].num ) )
{
Gnum[i][2].num =Gnum[i][2].num+Gnum[i][3].num;
Gnum[i][3].num=0;
}
}
Randnum(); //产生新的2或4的格子
}
// 向左移动处理
void OnLeft()
{
for(int j = 0; j < 4; j++ )
{
for(int i = 0; i < 4; i++)
{
if(Gnum[0][j].num==0)
{
Gnum[0][j].num=Gnum[1][j].num;
Gnum[1][j].num=Gnum[2][j].num;
Gnum[2][j].num=Gnum[3][j].num;
Gnum[3][j].num=0;
}
if(Gnum[1][j].num==0)
{
Gnum[1][j].num=Gnum[2][j].num;
Gnum[2][j].num=Gnum[3][j].num;
Gnum[3][j].num=0;
}
if(Gnum[2][j].num==0)
{
Gnum[2][j].num=Gnum[3][j].num;
Gnum[3][j].num=0;
}
}
}
for(int j = 0; j < 4; j++ )
{
if(Gnum[0][j].num == Gnum[1][j].num )
{
Gnum[0][j].num=Gnum[0][j].num+Gnum[1][j].num;
Gnum[1][j].num=Gnum[2][j].num;
Gnum[2][j].num=Gnum[3][j].num;
Gnum[3][j].num=0;
}
if(Gnum[1][j].num == Gnum[2][j].num )
{
Gnum[1][j].num=Gnum[1][j].num+Gnum[2][j].num;
Gnum[2][j].num=Gnum[3][j].num;
Gnum[3][j].num=0;
}
if(Gnum[2][j].num == Gnum[3][j].num )
{
Gnum[2][j].num=Gnum[2][j].num+Gnum[3][j].num;
Gnum[3][j].num=0;
}
}
Randnum(); //产生新的2或4的格子
}
// 向右移动处理
void OnRight()
{
for(int j = 3; j >=0; j-- )
{
for(int i = 3; i >=0; i--)
{
if(Gnum[3][j].num==0)
{
Gnum[3][j].num=Gnum[2][j].num;
Gnum[2][j].num=Gnum[1][j].num;
Gnum[1][j].num=Gnum[0][j].num;
Gnum[0][j].num=0;
}
if(Gnum[2][j].num==0)
{
Gnum[2][j].num=Gnum[1][j].num;
Gnum[1][j].num=Gnum[0][j].num;
Gnum[0][j].num=0;
}
if(Gnum[1][j].num==0)
{
Gnum[1][j].num=Gnum[0][j].num;
Gnum[0][j].num=0;
}
}
}
for(int j = 3; j >=0; j-- )
{
if(Gnum[3][j].num == Gnum[2][j].num )
{
Gnum[3][j].num =Gnum[3][j].num+Gnum[2][j].num;
Gnum[2][j].num=Gnum[1][j].num;
Gnum[1][j].num=Gnum[0][j].num;
Gnum[0][j].num=0;
}
if(Gnum[2][j].num == Gnum[1][j].num )
{
Gnum[2][j].num =Gnum[2][j].num+Gnum[1][j].num;
Gnum[1][j].num=Gnum[0][j].num;
Gnum[0][j].num=0;
}
if(Gnum[1][j].num == Gnum[0][j].num )
{
Gnum[1][j].num =Gnum[1][j].num+Gnum[0][j].num;
Gnum[0][j].num=0;
}
//}
}
Randnum(); //产生新的2或4的格子
}
// 向下移动处理
void OnDown()
{
for(int i = 3; i >=0; i-- )
{
for(int j = 3; j >=0; j--)
{
if(Gnum[i][3].num==0)
{
Gnum[i][3].num=Gnum[i][2].num;
Gnum[i][2].num=Gnum[i][1].num;
Gnum[i][1].num=Gnum[i][0].num;
Gnum[i][0].num=0;
}
if(Gnum[i][2].num==0)
{
Gnum[i][2].num=Gnum[i][1].num;
Gnum[i][1].num=Gnum[i][0].num;
Gnum[i][0].num=0;
}
if(Gnum[i][1].num==0)
{
Gnum[i][1].num=Gnum[i][0].num;
Gnum[i][0].num=0;
}
}
}
for(int i = 3; i >=0; i-- )
{
/*for(int j = 3; j >=0; j--)
{*/
if(Gnum[i][3].num == Gnum[i][2].num )
{
Gnum[i][3].num =Gnum[i][3].num+Gnum[i][2].num;
Gnum[i][2].num=Gnum[i][1].num;
Gnum[i][1].num=Gnum[i][0].num;
Gnum[i][0].num=0;
}
if(Gnum[i][2].num == Gnum[i][1].num )
{
Gnum[i][2].num =Gnum[i][2].num+Gnum[i][1].num;
Gnum[i][1].num=Gnum[i][0].num;
Gnum[i][0].num=0;
}
if((Gnum[i][1].num == Gnum[i][0].num ) )
{
Gnum[i][1].num =Gnum[i][1].num+Gnum[i][0].num;
Gnum[i][0].num=0;
}
//}
}
Randnum(); //产生新的2或4的格子
}
void Randnum() //随机产生新的数字 2或4
{
int i,j,flag=0;
for(i=0;i<4;i++) //判断格子上的数字是否有改的
{
for(j=0;j<4;j++)
{
if(oldnum[i][j]!=Gnum[i][j].num)
flag=1;
}
}
if(flag==1) //有
{
i=rand()%4;
j=rand()%4;
while(Gnum[i][j].num !=0) //判断随机位置上是否有数字,没有则跳出
{
i=rand()%4;
j=rand()%4;
}
Gnum[i][j].num=(rand()%2+1)*2; //产生随机数 2 或 4
//加分处理
if(Score<200)
Score+=2;
if(Score<1000&&Score>=200)
Score+=4;
if(Score<3000&&Score>=1000)
Score+=8;
Paint(); //绘制
}
for(i=0;i<4;i++) //更新oldnum数值
{
for(j=0;j<4;j++)
{
oldnum[i][j]=Gnum[i][j].num;
flag=0;
}
}
}
bool Checkover() //检测是否结束
{
for(int i = 0; i < 4; i++)
{
for(int j = 0; j < 4; j++)
{
if(Gnum[i][j].num == 0)
return false;
if(j<3)
{
if((Gnum[i][j].num == Gnum[i][j+1].num))
return false;
}
if(i<3)
{
if((Gnum[i][j].num == Gnum[i+1][j].num))
return false;
}
}
}
Sleep(200);
return true;
}
bool Quit() // 询问用户是否退出游戏
{
HWND hwnd = GetHWnd();
return (MessageBox(hwnd, _T("您确定要退出游戏吗?"), _T("询问"), MB_OKCANCEL | MB_ICONQUESTION) == IDOK);
}
下一篇: Lifeform Detector(栈)