刚学C语言不久,写了一个羊了个羊第二关的代码。目前还有一些问题,一是在7个槽都满的时候,无法渲染出来失败那张图片,不知道是什么原因,暂时呢用了个窗口来作为提示;二是下方三个工具栏,第一个本来是要推出去三个卡牌,但是不知道要怎么做,就设为了直接消除,这个在看广告复活那里也是一样的,然后是第二个“撤回”工具是空着的没写,第三个工具有个BUG,点了后会把全部卡牌刷新成最初的样子,就是还没有开始消时候。
这些问题在我以后会解决的,毕竟我现状只是个菜鸟。
下面就附上源码:
#include<stdio.h>
#include<easyx.h>
#include<graphics.h>
#include<time.h>
#include<Windows.h>
#include<mmsystem.h>
//#include<fstream>
#include"tools.h"
#pragma comment (lib,"winmm.lib")
#define CEN 59
bool update = true;
struct fang_kuai
{
int ceng;//第几层
int row, col;//第几行,第几列
int x, y;
int lei_xing;//方块类型
bool top;//true没有被覆盖,false被覆盖
int bian_jie_x, bian_jie_y;//这一层的第一个方块的边界
};
struct fang_kuai** maps[CEN] = { 0 };
struct fang_kuai* clickedBlock;
IMAGE imgb_j[2];//背景
IMAGE FANG_KUAI[15][2];
IMAGE fu_huo;
IMAGE jie_shu;
int cao[7] = { 0 };
int h = 0;
int mn = 0;
//加载图片
void loading() {
loadimage(&imgb_j[0], "./res/bg1.png");
loadimage(&imgb_j[1], "./res/bg2.png");
srand(time(NULL));
char fileName[256];
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 2; j++) {
sprintf_s(fileName, sizeof(fileName), "./res/%d_%d.png", i + 1, j);
loadimage(&FANG_KUAI[i][j], fileName);
}
}
loadimage(&fu_huo, "./res/tishi.png");
loadimage(&jie_shu, "./res/false.png");
}
//绘制图片
void hui_zhi() {
putimage(0, 0, &imgb_j[0]);
for (int i = 0; i < CEN; i++) {
for (int k = 0; maps[i][k]; k++) {
struct fang_kuai* p = maps[i][k];
if (p->lei_xing == 0) {
continue;
}
IMAGE* img = &FANG_KUAI[p->lei_xing - 1][p->top];
putimagePNG(p->x, p->y, img);
}
}
//槽中方块的绘制
for (int s = 0; s < 7; s++) {
if (cao[s]) {
int x = 26 + s * 64.7;
int y = 778;
putimagePNG(x, y, &FANG_KUAI[cao[s] - 1][1]);
}
}
}
//初始化层
void CENG(int ceng, int rows, int cols, int bian_jie_x, int bian_jie_y) {
maps[ceng] = (struct fang_kuai**)malloc(sizeof(struct fang_kuai*) * (rows * cols + 1));
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
maps[ceng][row * cols + col] = (struct fang_kuai*)malloc(sizeof(struct fang_kuai));
maps[ceng][row * cols + col]->bian_jie_x = bian_jie_x;
maps[ceng][row * cols + col]->bian_jie_y = bian_jie_y;
maps[ceng][row * cols + col]->row = row;
maps[ceng][row * cols + col]->col = col;
maps[ceng][row * cols + col]->lei_xing = 1 + rand() % 15;
maps[ceng][row * cols + col]->top = true;
maps[ceng][row * cols + col]->x = bian_jie_x + col * 61;
maps[ceng][row * cols + col]->y = bian_jie_y + row * 68;
maps[ceng][row * cols + col]->ceng = ceng;
}
}
maps[ceng][rows * cols] = NULL;
}
//方块的布局构建
void initMAP() {
int i = 0;
for (i; i < 12; i++) {
CENG(i, 1, 1, 30, 440 + i * 11);
}
for (i; i < 24; i++) {
CENG(i, 1, 1, 414, 440 + (i - 12) * 11);
}
for (i; i < 30; i++) {
CENG(i, 1, 1, 94, 583 + (i - 24) * 11);
}
for (i; i < 36; i++) {
CENG(i, 1, 1, 346, 583 + (i - 30) * 11);
}
for (i; i < 42; i++) {
CENG(i, 1, 1, 30 + (i - 36) * 11, 130);
}
for (i; i < 48; i++) {
CENG(i, 1, 1, 413 - (i - 42) * 11, 130);
}
CENG(i++, 4, 3, 159, 309);
CENG(i++, 5, 3, 159, 228);
CENG(i++, 5, 4, 129, 204);
CENG(i++, 5, 5, 99, 180);
CENG(i++, 3, 6, 70, 209);
CENG(i++, 1, 4, 134, 133);
CENG(i++, 1, 4, 134, 118);
CENG(i++, 1, 4, 134, 103);
CENG(i++, 2, 5, 100, 258);
CENG(i++, 2, 5, 100, 243);
CENG(i++, 2, 5, 100, 228);
}
//判断是否发生覆盖
bool fu_gai(struct fang_kuai* b1, struct fang_kuai* b2) {
int off = 4;//加上偏移量,防止距离较近的方块误判
return rectIntersect(b1->x + off, b1->y + off, b1->x + 61 - off, b1->y + 68 - off,
b2->x + off, b2->y + off, b2->x + 61 - off, b2->y + 68 - off);
}
//方块的亮暗
void ming_an() {
for (int i = CEN - 1; i >= 0; i--) {
for (int j = 0; maps[i][j]; j++) {
if (maps[i][j]->lei_xing == 0) {
continue;
}
for (int n = 0; n < i; n++) {
for (int index = 0; maps[n][index]; index++) {
if (maps[n][index]->lei_xing == 0) {
continue;
}
//判断是否发生覆盖
if (fu_gai(maps[n][index], maps[i][j])) {
maps[n][index]->top = false;
}
}
}
}
}
}
//用户点击
bool dian_ji() {
ExMessage msg;
if (peekmessage(&msg) && msg.message == WM_LBUTTONDOWN) {
for (int c = CEN - 1; c >= 0; c--) {
for (int k = 0; maps[c][k]; k++) {
struct fang_kuai* p = maps[c][k];
if (p->lei_xing && msg.x > p->x && msg.x < p->x + 61 && msg.y > p->y && msg.y < p->y + 68) {
clickedBlock = p;
return p->top;
}
}
}
}
return false;
}
//方块的更新,暗->亮
void geng_xin(struct fang_kuai* block) {
if (!block || block->lei_xing == 0)return;
for (int z = 0; z < block->ceng; z++) {
for (int index = 0; maps[z][index]; index++) {
if (maps[z][index]->lei_xing == 0)continue;
if (fu_gai(maps[z][index], block)) {
maps[z][index]->top = true;
}
}
}
}
//
void work() {
geng_xin(clickedBlock);
int cnt = 0;
int ii = 0;
for (ii; cao[ii] && ii < 7; ii++);//将点击到的方块填到卡槽中
//槽中一样的三个方块清除
if (ii < 7) {
cao[ii] = clickedBlock->lei_xing;
for (int j = 0; j < 7; j++) {
if (cao[j] == clickedBlock->lei_xing) {
cnt++;
}
}
if (cnt == 3) {
for (int j = 0; j < 7; j++) {
if (cao[j] == clickedBlock->lei_xing) {
cao[j] = 0;
}
}
}
}
else {
h += 1;
//putimage(0, 0, &fu_huo);
}
clickedBlock->lei_xing = 0;
}
//工具栏
void gong_jv() {
ExMessage asd;
if (peekmessage(&asd) && asd.message == WM_LBUTTONDOWN) {
//移出方块
//同样暂时是直接消除,且暂时只能移出后三个
if (asd.x > 47 && asd.x < 143 && asd.y>892 && asd.y < 976) {
for (int i = 4; i < 7; i++) {
cao[i] = 0;
}
}
//撤回
//后期完善
/*if (asd.x > 204 && asd.x < 301 && asd.y>892 && asd.y<976) {
}*/
//洗牌
if (asd.x > 360 && asd.x < 457 && asd.y>892 && asd.y < 976) {
initMAP();
ming_an();
hui_zhi();
}
}
}
//音乐
void BGM() {
mciSendString("play res/sheep.mp3", 0, 0, 0);
}
int main() {
initgraph(504, 1000);
loading();
initMAP();
clickedBlock = 0;
BGM();
int Time = 0;
while (1) {
/*for (int i = 0; i < 2; i++) {
putimage(0, 0, &imgb_j[i]);
Sleep(300);
}*/
//这里两个背景图的交替实现动态,后期完善
BeginBatchDraw();
Time += getDelay();
if (Time >= 10) {
Time = 0;
update = true;
}
if (update) {
ming_an();
hui_zhi();
}
if (dian_ji()) {
update = true;
work();//点击的方块放在槽中
}
if (h != 0)//这里int h是在work函数中else,cao[]>7时控制弹出看广告复活或者直接结束游戏
{
if (mn == 0) {
putimage(0, 0, &fu_huo);
ExMessage xuan;
if (peekmessage(&xuan) && xuan.message == WM_LBUTTONDOWN) {
//如果点击广告,就弹出广告
if (xuan.x > 142 && xuan.x < 361 && xuan.y>562 && xuan.y < 615) {
//播放广告,广告先不放
//暂时先让后三个直接消失,后期再完善
for (int a = 4; a < 7; a++) {
cao[a] = 0;
}
h = 0;//看了广告后h归0,便于第二次卡槽满后的 else if语句执行
mn = 1;//这里是为了控制只能有一次复活的机会
}
else if (xuan.x > 142 && xuan.x < 361 && xuan.y>640 && xuan.y < 695)
{
//游戏结束
MessageBox(GetHWnd(), "7个卡槽已满", "游戏结束", MB_OKCANCEL);//下面这条语句渲染不出来,只能用窗口来提示
//putimage(0, 0, &jie_shu);//不知道为什么渲染不出来,下面那个也一样
Sleep(300);
closegraph();
//break;
}
}
}
else {
MessageBox(GetHWnd(), "1次机会用完\n7个卡槽已满", "游戏结束", MB_OKCANCEL);
//putimage(0, 0, &jie_shu);
Sleep(3000);
closegraph();
break;
}
}
gong_jv();
FlushBatchDraw();
}
return 0;
}
欢迎指正。