⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compic.cpp

📁 别人做的一个拼图的小游戏
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* WM_PAINT 消息处理函数 */
void OnPaint(HDC hDC)
{
	int i = 0, j = 0;

	/* 填充背景和绘制线条 */
	SelectObject(h_MemDC, hPen);
	SelectObject(h_MemDC, h_CliBm);

	apiBitBlt(hDC, 0, 0, rc.right-rc.left,rc.bottom-rc.top);

	SelectObject(h_MemDC, h_PicBkGnd);
	apiBitBlt(hDC, rc.left, rc.top, ROW*y_cell+4, rc.bottom);

	/* 绘制背景各个坐标位图 */
	for(i = 0; i < LINE; i ++)
	{
		for(j = 0; j < ROW; j ++)
		{
			if(map[i][j].status == 1) continue;
			drawPic(hDC, i, j);
		}
	}

	/* 绘制右上角小的全图 */
	SelectObject(h_MemDC, h_SmPicBm);
	apiBitBlt(hDC, rc.right-261, 2, 260, 210);
}

/* 设置鼠标形状 */
void OnSetCursor()
{
	int x = 0, y = 0, dx = 0, dy = 0;
	int ret = 0;

	if(mcur_x <= 0 || mcur_y <= 0)
	{
		SetCursor(LoadCursor(NULL, (LPCTSTR)IDC_ARROW));
		return;
	}
	x = (mcur_x - 1)/x_cell;
	y = (mcur_y - 2)/y_cell;
	if(gameStatus == GMGOING)
	{
		if(y < 0 || y >= ROW || x < 0 || x >= LINE)
		{
			SetCursor(LoadCursor(NULL, (LPCTSTR)IDC_ARROW));
			return;
		}
		ret = chkStatus(x, y, &dx, &dy);
		if(ret < 0)     /* 不可移动 */
		{
			SetCursor(LoadCursor(hInst, (LPCTSTR)IDC_CURSOR_NO));
			return;
		}
		switch(ret)
		{
		case UP:        /* 可以向上移动 */
			SetCursor(LoadCursor(hInst, (LPCTSTR)IDC_CURSOR_UP));
			break;
		case DOWN:      /* 可以向下移动 */
			SetCursor(LoadCursor(hInst, (LPCTSTR)IDC_CURSOR_DOWN));
			break;
		case LEFT:      /* 可以向左移动 */
			SetCursor(LoadCursor(hInst, (LPCTSTR)IDC_CURSOR_LEFT));
			break;
		case RIGHT:     /* 可以向右移动 */
			SetCursor(LoadCursor(hInst, (LPCTSTR)IDC_CURSOR_RIGHT));
			break;
		}
	}
	else
		SetCursor(LoadCursor(NULL, (LPCTSTR)IDC_ARROW));
}

/* 鼠标点击消息处理 */
int OnMouseClick(HDC hDC)
{
	int i = 0, j = 0, ret = 0;
	int mx = 0, my = 0, nx = 0, ny = 0, x = 0, y = 0;
	RECT rt;

	/* 计算鼠标点击的坐标对应的背景坐标 */
	mx = (mouse_x - 1)/x_cell;
	my = (mouse_y - 2)/y_cell;

	/* 检查点击的图片的状态,判断是否该图片块可以移动 */
	ret = chkStatus(mx, my, &nx, &ny);
	if(ret < 0) return 0;

	intSteps ++;
	swapPic(&map[mx][my], &map[nx][ny]);
	drawPic(hDC, mx, my);

	/* 获得重画的矩形区域,使该区域立即生效 */
	x = (mx < nx ? mx : nx);
	y = (my < ny ? my : ny);

	rt.left = y*y_cell + 2;
	rt.top = x*x_cell + 1;
	rt.right = rt.left + y_cell+4;
	rt.bottom = rt.top + x_cell+4;

	switch(ret)
	{
	case UP:
	case DOWN:
		rt.bottom += x_cell;
		break;
	case RIGHT:
	case LEFT:
		rt.right += y_cell;
		break;
	}
	InvalidateRect(hWndMain, &rt, FALSE);

	/* 检查游戏是否结束 */
	for(i = 0; i < LINE; i ++)
	{
		for(j = 0; j < ROW; j ++)
		{
			if(map[i][j].x != map[i][j].px ||
			   map[i][j].y != map[i][j].py)
			{
				if(map[i][j].status != 1) return 0;
			}
		}
	}
	rt.left = rc.left;
	rt.top = rc.top;
	rt.bottom = rc.bottom;
	rt.right = ROW*y_cell + 2;
	gameStatus = GMOVER;

	/* 游戏结束显示背景图 */
	for(i = 0; i < LINE; i ++)
	{
		for(j = 0; j < ROW; j ++)
		{
			map[i][j].status = 1;
		}
	}
	InvalidateRect(hWndMain, &rt, FALSE);
	MessageBox(hWndMain, "真棒!恭喜你(^_^)", "游戏结束", MB_OK);

	/* 恢复拼图图片显示 */
	for(i = 0; i < LINE; i ++)
	{
		for(j = 0; j < ROW; j ++)
		{
			map[i][j].status = 0;
		}
	}
	InvalidateRect(hWndMain, &rt, FALSE);

	rt.left = rc.right-230;
	rt.top = rc.top+285;
	rt.bottom = rc.top+345;
	rt.right = rc.right;

	/* 清除统计信息 */
	SelectObject(h_MemDC, h_CliBm);
	FillRect(h_MemDC, &rt, hBrush);

	InvalidateRect(hWndMain, &rt, FALSE);

	return 0;
}

/* 随机生成游戏的初始图片序列 */
int OnNewGame(HDC hDC)
{
	int cur_x = 0, cur_y = 0, x= 0, y = 0, dx = 0, dy = 0;
	int i = 0, j = 0, dir = 0, ret = 0;
	RECT rt;

	intSteps = 0;
	startT = time(NULL);

	/* 恢复背景坐标到初始状态 */
	for(i = 0; i <= LINE; i ++)
	{
		for(j = 0; j <= ROW; j++)
		{
			map[i][j].x = i;
			map[i][j].y = j;
			map[i][j].status = 0;
			map[i][j].px = i;
			map[i][j].py = j;
		}
	}

	cur_x = rand()%LINE;
	cur_y = rand()%ROW;

	map[cur_x][cur_y].status = 1;
	x = cur_x;
	y = cur_y;
	dir = UP;
	for(i = 0; i < 4*LINE*ROW; i ++)
	{
		switch(dir)
		{
		case RIGHT:
			y ++; break;
		case DOWN:
			x ++; break;
		case LEFT:
			y --; break;
		case UP:
			x --; break;
		}
		ret = chkStatus(x, y, &dx, &dy);
		if(ret < 0)
		{
			dir = rand()%4;
			x = cur_x;
			y = cur_y;
			continue;
		}

		swapPic(&map[x][y], &map[dx][dy]);

		cur_x = x;
		cur_y = y;
		dir = rand()%4;
	}

	/* 绘制背景坐标各个点的位图 */
	for(i = 0; i < LINE; i ++)
	{
		for(j = 0; j < ROW; j ++)
		{
			if(map[i][j].status == 1) continue;
			drawPic(hDC, i, j);
		}
	}

	rt.left = 1;
	rt.top = 1;
	rt.right = rt.left + ROW*y_cell;
	rt.bottom = rt.top + LINE*x_cell;

	InvalidateRect(hWndMain, &rt, FALSE);

	return 0;
}

/* 交换两个坐标点的位图 */
void swapPic(MAPSTATUS *s, MAPSTATUS *t)
{
	MAPSTATUS tMap;

	tMap.px = s->px;
	tMap.py = s->py;
	tMap.status = s->status;

	s->px = t->px;
	s->py = t->py;
	s->status = t->status;

	t->px = tMap.px;
	t->py = tMap.py;
	t->status = tMap.status;
}

/* 检查坐标点(x,y) 的状态,如果成功返回其移动的方向 */
int chkStatus(int x, int y, int *px, int *py)
{
	int i = 0, ret = -1;

	if(gameStatus != GMGOING) return -1;
	if(y < 0 || y >= ROW || x < 0 || x >= LINE) return -1;

	if(map[x][y].status == 1) return -1;

	for(i = 0; i < 4; i ++)
	{
		*px = x;
		*py = y;
		ret = -1;
		switch(i)
		{
		case RIGHT:
			(*py) ++; break;
		case DOWN:
			(*px) ++; break;
		case LEFT:
			(*py) --; break;
		case UP:
			(*px) --; break;
		}
		if(*py < 0 || *py >= ROW || *px < 0 || *px >= LINE) continue;
		if(map[*px][*py].status == 1)
		{
			ret = i;
			break;
		}
	}
	return ret;
}

void displayText(int posx, int posy, char *text, int len)
{
	RECT rt;

	rt.left = posx;
	rt.top = posy;
	rt.right=rt.left + len + 8;
	rt.bottom=rt.top + 20;

	SelectObject(h_MemDC, h_CliBm);

	FillRect(h_MemDC, &rt, hBushText);

	TextOut(h_MemDC, posx+4, posy+2, text, strlen(text));
	
	InvalidateRect(hWndMain, &rt, FALSE);	
}

void showInfo()
{
	RECT rt;
	char tmp[256];
	time_t curT = 0;

	displayText(rc.right-200, rc.top+250, curtime("%y-%m-%d %h:%i:%s"), 132);
	displayText(rc.right-230, rc.top+390, "支持拖其他BMP图片到游戏窗口", 210);

	if(gameStatus == GMGOING)
	{
		memset(tmp, 0x00, sizeof(tmp));
		sprintf(tmp, "步数: %08d", intSteps);
		displayText(rc.right-230, rc.top+290, tmp, 7*strlen(tmp)+2);

		curT = time(NULL);
		memset(tmp, 0x00, sizeof(tmp));
		sprintf(tmp, "用时: %02d分%02d秒", ((curT-startT)/60)%99, (curT-startT)%60);
		displayText(rc.right-230, rc.top+320, tmp, 7*strlen(tmp));
	}

	if(gameStatus == GMINIT || gameStatus == GMOVER)
	{
		displayText(rc.right-230, rc.top+360, "请选择游戏开始新游戏", 150);
	}
	else
	{
		rt.left = rc.right-230;
		rt.top = rc.top+360;
		rt.right=rt.left + 230 + 8;
		rt.bottom=rt.top + 25;

		SelectObject(h_MemDC, h_CliBm);
		FillRect(h_MemDC, &rt, hBrush);
		InvalidateRect(hWndMain, &rt, FALSE);

		displayText(rc.right-230, rc.top+360, "正在游戏中", 75);
	}
}

char *curtime(char *fmt)
{
    int i = 0;
    time_t t;
    struct tm *lt = NULL;
    static char res[128];
    char *p = fmt;

    memset(res, 0x00, sizeof(res));   
    if(!fmt) return res;

    t = time(NULL);
    lt = (struct tm *)localtime(&t);
    while(*p)
    {
        if(*p != '%') 
        {
            res[i++] = *p; p ++; 
            continue; 
        }
        switch(*(p+1))
        {
        case '\0':
            res[i++] = *p;
            res[i] = '\0';
            return res;
        case 'y':
            sprintf(&res[i], "%04d", lt->tm_year + 1900);
            i += 2;
            p ++;
            break;
        case 'm':
            sprintf(&res[i], "%02d", lt->tm_mon + 1);
            p ++;
            break;
        case 'd':
            sprintf(&res[i], "%02d", lt->tm_mday);
            p ++;
            break;
        case 'h':
            sprintf(&res[i], "%02d", lt->tm_hour);
            p ++;
            break;
        case 'i':
            sprintf(&res[i], "%02d", lt->tm_min);
            p ++;
            break;
        case 's':
            sprintf(&res[i], "%02d", lt->tm_sec);
            p ++;
            break;
        default:
            res[i] = *p;
            i --;
            break;
        }
        i += 2;
        p ++;
    }
    res[i] = '\0';
    return res;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -