尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

用C语言绘制开心消消乐游戏

用C语言绘制开心消消乐游戏
📅 发布时间:2026/6/20 15:37:09

#include <graphics.h>
#include <conio.h>
#include <time.h>
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

//游戏常量定义
const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 600;
const int GRID_SIZE = 8;
const int BLOCK_SIZE = 60;
const int COLORS_COUNT = 6;

//计算居中位置
const int MARGIN_X = (WINDOW_WIDTH - GRID_SIZE * BLOCK_SIZE) / 2;
const int MARGIN_Y = (WINDOW_HEIGHT - GRID_SIZE * BLOCK_SIZE) / 2 - 20;

//游戏状态
enum GameState {
PLAYING,
ANIMATING,
GAME_OVER
};

//方块结构
struct Block
{
int x, y; //在网格中的位置
int color; //颜色索引
int offsetX, offsetY; //动画偏移量
bool selected; //是否被选中
bool removing; //是否正在消除
float alpha; //透明度(用于消除动画)
};

//游戏全局变量
Block grid[GRID_SIZE][GRID_SIZE];
GameState gameState = PLAYING;
int score = 0;
int selectedX = -1, selectedY = -1; //当前选中的方块
bool hasSelected = false; //是否有方块被选中
int targetScore = 1000; //目标分数
bool showHelp = true; //是否显示帮助

//柔和的颜色定义
COLORREF colors[COLORS_COUNT] = {
RGB(255,178,178), //柔和的红色
RGB(178,255,178), //柔和的绿色
RGB(178,178,255), //柔和的蓝色
RGB(255,255,178), //柔和的黄色
RGB(255,178,255), //柔和的紫色
RGB(178,255,255) //柔和的青色
};

//数字字符(对应颜色)
TCHAR numberCharts[COLORS_COUNT] = { _T('1'),_T('2'),_T('3'),_T('4'),_T('5'),_T('6') };

//检查是否有可消除的组合
bool checkMatches() {
bool hasMatches = false;

//检查水平方向
for (int y = 0; y < GRID_SIZE;y++) {
for (int x = 0; x < GRID_SIZE - 2;x++) {
if (grid[x][y].color == grid[x + 1][y].color &&
grid[x][y].color == grid[x + 2][y].color) {
grid[x][y].removing = true;
grid[x+1][y].removing = true;
grid[x + 2][y].removing = true;
hasMatches = true;
}
}
}

//检查垂直方向
for (int x = 0; x < GRID_SIZE;x++) {
for (int y = 0;y < GRID_SIZE - 2;y++) {
if (grid[x][y].color == grid[x][y + 1].color &&
grid[x][y].color == grid[x][y + 2].color) {
grid[x][y].removing = true;
grid[x][y +1].removing = true;
grid[x][y + 2].removing = true;
hasMatches = true;
}
}
}
return hasMatches;
}

//检查特定位置是否有匹配
bool hasMatchAt(int x, int y) {
//检查水平方向
if (x >= 2 &&
grid[x][y].color == grid[x - 1][y].color &&
grid[x][y].color == grid[x - 2][y].color) {
return true;
}
if (x >= 1 && x < GRID_SIZE - 1 &&
grid[x][y].color == grid[x - 1][y].color &&
grid[x][y].color == grid[x + 1][y].color) {
return true;
}

if (x < GRID_SIZE - 2 &&
grid[x][y].color == grid[x + 1][y].color &&
grid[x][y].color == grid[x + 2][y].color) {
return true;
}

//检查垂直方向
if (y >= 2 &&
grid[x][y].color == grid[x][y - 1].color &&
grid[x][y].color == grid[x][y - 2].color) {
return true;
}

if (y >= 1 && y < GRID_SIZE - 1 &&
grid[x][y].color == grid[x][y - 1].color &&
grid[x][y].color == grid[x][y + 1].color) {
return true;
}

if (y < GRID_SIZE - 2 &&
grid[x][y].color == grid[x][y + 1].color &&
grid[x][y].color == grid[x][y + 2].color) {
return true;
}
return false;
}


//检查交换两个方块后能否形成匹配
bool checkSwapWillMatch(int x1, int y1, int x2, int y2) {
//临时交换方块
int tempColor = grid[x1][y1].color;
grid[x1][y1].color = grid[x2][y2].color;
grid[x2][y2].color == tempColor;

//检查是否有匹配
bool willMatch = false;

//检查交换后的两个位置及其周围
willMatch = hasMatchAt(x1, y1) || hasMatchAt(x2, y2);

//如果没有直接匹配,检查整个网络
if (!willMatch) {
willMatch = checkMatches();

//重置removing标志
for (int i = 0;i < GRID_SIZE;i++) {
for (int j = 0; j < GRID_SIZE;j++) {
grid[i][j].removing = false;
}
}
}

//交换回来
tempColor = grid[x1][y1].color;
grid[x1][y1].color = grid[x2][y2].color;
grid[x2][y2].color = tempColor;

return willMatch;
}

//初始化游戏
void initGame() {
srand((unsigned int)time(NULL));

//初始化网格,确保没有初始三个相连的情况
for (int i = 0;i < GRID_SIZE;i++) {
for (int j = 0;j < GRID_SIZE;j++) {
grid[i][j].x = i;
grid[i][j].y = j;
grid[i][j].offsetX = 0;
grid[i][j].offsetY = 0;
grid[i][j].selected = false;
grid[i][j].removing = false;
grid[i][j].alpha = 1.0f;

//生成颜色,确保不会形成三个相连
int color;
do {
color = rand() % COLORS_COUNT;
grid[i][j].color = color;
} while (hasMatchAt(i, j));
}
}

//重置游戏状态
score = 0;
selectedX = -1;
selectedY = -1;
hasSelected = false;
gameState = PLAYING;
}

//绘制圆角矩形
void drawRoundRect(int x, int y, int width, int height, int radius, COLORREF color) {
setfillcolor(color);
solidroundrect(x, y, x + width, y + height, radius, radius);
}

//绘制方块
void drawBlock(int x, int y, int color, bool selected, float alpha = 1.0f) {
int screenX = MARGIN_X + x * BLOCK_SIZE;
int screenY = MARGIN_Y + y * BLOCK_SIZE;

//绘制选中效果,先绘制红色边框,确保在方块下面
if (selected) {
setlinecolor(RGB(255, 0, 0)); //红色边框
setlinestyle(PS_SOLID, 4); //4像素粗的边框
roundrect(screenX - 3, screenY - 3, screenX + BLOCK_SIZE + 3, screenY + BLOCK_SIZE + 3, 12, 12);

//添加发光效果
setlinecolor(RGB(255, 100, 100)); //淡红色发光
setlinestyle(PS_SOLID, 2);
roundrect(screenX - 6, screenY - 6, screenX + BLOCK_SIZE + 6, screenY + BLOCK_SIZE + 6, 14, 14);

//恢复默认线条样式
setlinestyle(PS_SOLID, 1);
}

//绘制方块主体
COLORREF blockColor = colors[color];

//应用透明度
if (alpha < 1.0f) {
int r = GetRValue(blockColor) * alpha;
int g = GetGValue(blockColor) * alpha;
int b = GetBValue(blockColor) * alpha;
blockColor = RGB(r, g, b);
}

drawRoundRect(screenX, screenY, BLOCK_SIZE, BLOCK_SIZE, 8, blockColor);

//绘制内部颜色(带渐变效果)
for (int i = 0;i < 4;i++) {
int offset = 8 + i * 4;
int size = BLOCK_SIZE - offset * 2;
int r = GetRValue(blockColor) + (255 - GetRValue(blockColor)) * i / 4;
int g = GetGValue(blockColor) + (255 - GetGValue(blockColor)) * i / 4;
int b = GetBValue(blockColor) + (255 - GetBValue(blockColor)) * i / 4;
COLORREF innerColor = RGB(r, g, b);

setfillcolor(innerColor);
solidroundrect(screenX + offset, screenY + offset, screenX + offset + size, screenY + offset + size, 5, 5);
}

//绘制数字
settextcolor(RGB(0, 0, 0)); //黑色数字
settextstyle(24, 0, _T("Arial"));
setbkmode(TRANSPARENT);

TCHAR numStr[2] = { numberCharts[color],_T('\0') };
int textWidth = textwidth(numStr);
int textHeight = textheight(numStr);
outtextxy(screenX + (BLOCK_SIZE - textWidth) / 2, screenY + (BLOCK_SIZE - textHeight) / 2,
numStr);
}

//绘制游戏界面
void drawGame() {
//绘制背景
setbkcolor(RGB(245, 245, 250));
cleardevice();

//绘制分数,使用更明显的样式
settextcolor(RGB(220, 80, 80));
settextstyle(24, 0, _T("Arial"));
TCHAR scoreText[50];
_stprintf_s(scoreText, _T("分数:%d /%d"), score, targetScore);

//绘制分数背景
setfillcolor(RGB(255, 240, 240));
fillroundrect(WINDOW_WIDTH / 2 - 100, 65, WINDOW_WIDTH / 2 + 100, 105, 10, 10);


//绘制分数边框
setlinecolor(RGB(220, 80, 80));
setlinestyle(PS_SOLID, 2);
roundrect(WINDOW_WIDTH / 2 - 100, 65, WINDOW_WIDTH / 2 + 100, 105, 10, 10);
setlinestyle(PS_SOLID, 1);


//绘制分数文本
outtextxy(0, 20, scoreText);

//绘制游戏区域背景
setfillcolor(RGB(230, 230, 240));
solidroundrect(MARGIN_X - 10, MARGIN_Y - 10, MARGIN_X + GRID_SIZE * BLOCK_SIZE + 10, MARGIN_Y + GRID_SIZE * BLOCK_SIZE + 10, 15, 15);

//绘制所有方块
for (int i = 0;i < GRID_SIZE;i++) {
for (int j = 0;j < GRID_SIZE;j++) {
if (!grid[i][j].removing) {
drawBlock(i, j, grid[i][j].color, grid[i][j].selected, grid[i][j].alpha);
}
}
}

//绘制操作说明
settextcolor(RGB(120, 120, 160));
settextstyle(16, 0, _T("Arial"));

//如果显示帮助,绘制详细说明
if (showHelp) {
outtextxy(20, MARGIN_Y + GRID_SIZE * BLOCK_SIZE + 20, _T("游戏说明:"));
outtextxy(20, MARGIN_Y + GRID_SIZE * BLOCK_SIZE + 45, _T("1.点击选择一个方块"));
outtextxy(20, MARGIN_Y + GRID_SIZE * BLOCK_SIZE + 65, _T("2.点击相邻方块交换位置"));
outtextxy(20, MARGIN_Y + GRID_SIZE * BLOCK_SIZE + 85, _T("3.三个相同颜色连成一线即可消除"));
outtextxy(20, MARGIN_Y + GRID_SIZE * BLOCK_SIZE + 105, _T("4.达到目标分数获胜"));

outtextxy(WINDOW_WIDTH - 250, MARGIN_Y + GRID_SIZE * BLOCK_SIZE + 20, _T("操作提示:"));
outtextxy(WINDOW_WIDTH - 250, MARGIN_Y + GRID_SIZE * BLOCK_SIZE + 45, _T("R-重新开始游戏"));
outtextxy(WINDOW_WIDTH - 250, MARGIN_Y + GRID_SIZE * BLOCK_SIZE + 65, _T("H-显示/隐藏帮助"));
}
else {
//只显示简短的提示
outtextxy(WINDOW_WIDTH / 2 - 100, MARGIN_Y + GRID_SIZE * BLOCK_SIZE + 30,
_T("按H显示游戏帮助"));
}

//绘制游戏结束提示 -使用深色背景替代半透明效果
if (gameState == GAME_OVER) {
//绘制一个深色背景
setfillcolor(RGB(50, 50, 80));
solidrectangle(WINDOW_WIDTH / 2 - 200, WINDOW_HEIGHT / 2 - 100,
WINDOW_WIDTH / 2 + 200, WINDOW_HEIGHT / 2 + 100);

//绘制边框
setlinecolor(RGB(100, 100, 200));
setlinestyle(PS_SOLID, 3);
rectangle(WINDOW_WIDTH / 2 - 200, WINDOW_HEIGHT / 2 - 100,
WINDOW_WIDTH / 2 + 200, WINDOW_HEIGHT / 2 + 100);
setlinestyle(PS_SOLID, 1);

settextcolor(RGB(255, 255, 255));
settextstyle(40, 0, _T("Arial"));

if (score >= targetScore) {
outtextxy(WINDOW_WIDTH / 2 - 100, WINDOW_HEIGHT / 2 - 50, _T("游戏胜利"));
}
else {
outtextxy(WINDOW_WIDTH / 2 - 100, WINDOW_HEIGHT / 2 - 50, _T("游戏结束"));
}

//显示最终分数
settextstyle(20, 0, _T("Arial"));
TCHAR finalScoreText[50];
_stprintf_s(finalScoreText, _T("最终分数:%d"), score);
outtextxy(WINDOW_WIDTH / 2 - textwidth(finalScoreText) / 2, WINDOW_HEIGHT / 2, finalScoreText);

outtextxy(WINDOW_WIDTH / 2 - 80, WINDOW_HEIGHT / 2 + 30, _T("按R键重新开始"));
}
}

//检查两个方块是否相邻
bool isAdjacent(int x1, int y1, int x2, int y2) {
return (abs(x1 - x2) == 1 && y1 == y2) || (abs(y1 - y2) == 1 && x1 == x2);
}

//交换两个方块
void swapBlocks(int x1, int y1, int x2, int y2)
{
Block temp = grid[x1][y1];
grid[x1][y1] = grid[x2][y2];
grid[x2][y2] = temp;

//交换后立即取消选中状态
grid[x1][y1].selected = false;
grid[x2][y2].selected = false;
hasSelected = false;
selectedX = -1;
selectedY = -1;
}

//处理消除动画
void processRemoval() {
bool stillRemoving = false;

for (int i = 0;i < GRID_SIZE;i++) {
for (int j = 0;j < GRID_SIZE;j++) {
if (grid[i][j].removing) {
grid[i][j].alpha -= 0.05f;
if (grid[i][j].alpha > 0) {
stillRemoving = true;
}
else {
//方块完全消失,重新生成
grid[i][j].color = rand() % COLORS_COUNT;
grid[i][j].removing = false;
grid[i][j].alpha = 1.0f;
score += 10; //没消除一个方块得10分
}
}
}
}
if (!stillRemoving) {
gameState = PLAYING;

//检查游戏是否结束
if (score >= targetScore) {
gameState = GAME_OVER;
}
}
}

//处理鼠标点击
void handleMouseClick(int x, int y) {
if (gameState != PLAYING) return;

//转换为网格坐标
int gridX = (x - MARGIN_X) / BLOCK_SIZE;
int gridY = (y - MARGIN_Y) / BLOCK_SIZE;

//检查点击是否在网格内
if (gridX < 0 || gridX >= GRID_SIZE || gridY < 0 || gridY >= GRID_SIZE) {
return;
}

if (!hasSelected) {
//第一次选择方块
selectedX = gridX;
selectedY = gridY;
grid[selectedX][selectedY].selected = true;
hasSelected = true;
}
else {
//第二次选择方块
if (selectedX == gridX && selectedY == gridY)
{
//取消选择
grid[selectedX][selectedY].selected = false;
hasSelected = false;
selectedX = -1;
selectedY = -1;
}
else if (isAdjacent(selectedX, selectedY, gridX, gridY)) {
//检查交换后是否能形成匹配
if (checkSwapWillMatch(selectedX, selectedY, gridX, gridY)) {
//交换方块
swapBlocks(selectedX, selectedY, gridX, gridY);

//检查并标识匹配
if (checkMatches()) {
gameState = ANIMATING;
}
}
else {
//不能形成匹配
}
}
else {
//选择新的方块
grid[selectedX][selectedY].selected = false;
selectedX = gridX;
selectedY = gridY;
grid[selectedX][selectedY].selected = true;

}
}
}


int main()
{
initgraph(WINDOW_WIDTH, WINDOW_HEIGHT);

//设置字体背景透明
setbkmode(TRANSPARENT);

//开启批量绘图
BeginBatchDraw();

//初始化游戏
initGame();

ExMessage msg;

//游戏主循环
while (true) {
while (peekmessage(&msg, EX_MOUSE | EX_KEY)) {
switch (msg.message)
{
case WM_LBUTTONDOWN:
handleMouseClick(msg.x, msg.y);
break;
case WM_KEYDOWN:
if (msg.vkcode == 'R' || msg.vkcode == 'r') {
initGame();
}
else if (msg.vkcode == 'H' || msg.vkcode == 'h') {
showHelp = !showHelp;
}
break;
}
}
//处理消除动画
if (gameState == ANIMATING) {
processRemoval();
}

//绘制游戏
drawGame();

//刷新显示
FlushBatchDraw();

//降低CPU占用率
Sleep(10);
}
//关闭图形窗口
closegraph();
return 0;
}

相关新闻

  • 官网-江苏省医疗保障条例
  • mysql的 order by是怎么工作的?redo-log和binlog为什么采用双确认机制?
  • PaddlePaddle镜像中的模型解释性工具SHAP集成方法

最新新闻

  • 2026年法穆兰官方售后服务体系升级公告:全新官方维修门店新址升级落地,最新服务热线同步开通 - 亨得利中国服务中心
  • Ultimate ASI Loader终极指南:3分钟掌握游戏MOD加载神器
  • 2026年龙华区靠谱的驾校,科技赋能龙华便民驾培!专访宝华驾校 AI 驾驶馆,观平路新联大厦双模式智能教学,服务产业园上班族与青年学子 - GrowthUME
  • 官方最新发布!2026安徽合肥中考分数在普高线上下徘徊?这所学校的综合高中班可以关注 - 小张zc
  • 2026 安徽省宠物护理特色专业招录,咨询方式看最新简章 - cc江江
  • 元气AI助手实战指南:结构化信息处理与工作流嵌入方法

日新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号