C/C++项目实战:华容道游戏开发丨570 行源码分享来啦~

每天一个C/C++小项目,提升你的编程能力!

华容道是古老的中国民间益智游戏,以其变化多端、百玩不厌的特点与魔方、独立钻石一起被国外智力专家并称为“智力游戏界的三个不可思议”。它与七巧板、九连环等中国传统益智玩具还有个代名词叫作“中国的难题”。据《资治通鉴》注释中说“从此道可至华容也”。华容道原是中国古代的一个地名,相传当年曹操曾经败走此地。由于当时的华容道是一片沼泽,所以曹操大军要割草填地,不少士兵更惨被活埋,惨烈非常。

游戏玩法

通过移动各个棋子,帮助曹操从初始位置移到棋盘最下方中部,从出口逃走。不允许跨越棋子,还要设法用最少的步数把曹操移到出口。曹操逃出华容道的最大障碍是关羽,关羽立马华容道,一夫当关,万夫莫开。关羽与曹操当然是解开这一游戏的关键。四个刘备军兵是最灵活的,也最容易对付,如何发挥他们的作用也要充分考虑周全。“华容道”有一个带二十个小方格的棋盘,代表华容道。

游戏效果图:

游戏素材图:

本项目编译环境:Visual Studio 2019/2022,EasyX(2022最新版)插件

操作方式:鼠标左键移动棋子,将曹操移动到出口处,过关。

简单了解游戏后我们就来试试吧!

代码展示:

(直接上源码,大家可以看注释)

#include <iostream>
#include <cmath>
#include <graphics.h>
#include "resource.h"//对话框资源
using namespace std;


enum BLOCK {BORDER=0,EMPTY=1,CC=2,GY=3,ZF=4,ZY=5,MC=6,HZ=7,BING=8}; //木块

IMAGE border,empty,cc,gy,zf,zy,mc,hz,bing,buffer(500,350),gameinterface,menuitf,aboutitf,cmapitf,winimg; //图片

BLOCK map[6][7];//地图

struct BLock//点结构体
{
    int x;
    int y;
};

int msmode,mapnum,movenum,lstdir=-3;
char mapname[11];

void about();//关于游戏
void win();//胜利
void game(int mapnum);//核心函数:执行游戏
void menu();//菜单
void choosemap();//地图菜单
void draw();//绘制

//窗口回调函数
BOOL WINAPI HelpDlg_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)// 处理 WM_XX 消息
    {
		case WM_INITDIALOG:
			return true;

		case WM_COMMAND:
			if((HWND)lParam==GetDlgItem(hWnd,IDC_CLOSE))
			{
				EndDialog(hWnd,1);
			}
    }
    return false;
}

//判断点与矩形位置算法
bool inrect(int x,int y,int x1,int y1,int w1,int h1)
{
    if(x>=x1&&x<x1+w1&&y>=y1&&y<y1+h1)
    {
        return true;
    }
    else
    {
        return false;
    }
}

//加载地图
void loadmap(int number)
{
    FILE *fp;
    char filename[50];
    sprintf(filename,"关卡\\关卡%d.map",number);
    fp=fopen(filename,"r");
    int i,j;
    for(i=0; i<6; i++)
        for(j=0; j<7; j++)
        {
            map[i][j]=BORDER;
        }

    for(j=0; j<5; j++)
        for(i=0; i<4; i++)
        {
            switch(fgetc(fp))
            {
				case 'E':	map[i+1][j+1]=EMPTY;	break;
				case 'C':	map[i+1][j+1]=CC;		break;
				case 'G':	map[i+1][j+1]=GY;		break;
				case 'Z':	map[i+1][j+1]=ZF;		break;
				case 'z':	map[i+1][j+1]=ZY;		break;
				case 'M':	map[i+1][j+1]=MC;		break;
				case 'H':	map[i+1][j+1]=HZ;		break;
				case 'B':	map[i+1][j+1]=BING;		break;
            }
        }
    fscanf(fp,"%s",mapname);
}

//加载图片
void loadres()
{
    loadimage(&empty,"IMAGE","EMPTY");
    loadimage(&bing,"IMAGE","BING");
    loadimage(&border,"IMAGE","BORDER");
    loadimage(&cc,"IMAGE","CC");
    loadimage(&gy,"IMAGE","GY");
    loadimage(&zf,"IMAGE","ZF");
    loadimage(&zy,"IMAGE","ZY");
    loadimage(&mc,"IMAGE","MC");
    loadimage(&hz,"IMAGE","HZ");
    loadimage(&gameinterface,"IMAGE","GAMEITF");
    loadimage(&menuitf,"IMAGE","MENU");
    loadimage(&cmapitf,"IMAGE","MAPMENU");
    loadimage(&aboutitf,"IMAGE","ABTGAME");
    loadimage(&winimg,"IMAGE","WIN");
}

//寻找五虎上将,曹操的位置
BLock FindBlock(BLOCK block)
{
    struct BLock Block= {0,0};
    int x,y;
    for(x=0; x<=6;)
    {
        for(y=0; y<=7;)
        {
            if(map[x][y]==block)
            {
                Block.x=x;
                Block.y=y;
                return Block;
            }
            else
            {
                y+=1;
            }
        }
        x+=1;
    }
    return Block;
}

//核心函数:移动木块函数
bool move(BLOCK block,int dx,int dy)
{
    bool win=false,moved=false;

	//兵
    if(msmode>10)
    {
        if(map[msmode/10+dx][msmode%10+dy]==EMPTY)
        {
            map[msmode/10][msmode%10]=EMPTY;
            map[msmode/10+dx][msmode%10+dy]=BING;
            msmode+=dx*10+dy;
            moved=true;
        }
    }

    //竖着的将
    if(block>GY&&block<BING)
    {
        BLock blk;
        blk=FindBlock(block);
        if(dx!=0)
        {
            if(map[blk.x+dx][blk.y]==EMPTY&&map[blk.x+dx][blk.y+1]==EMPTY)
            {
                map[blk.x][blk.y]=EMPTY;
                map[blk.x][blk.y+1]=EMPTY;
                map[blk.x+dx][blk.y]=block;
                map[blk.x+dx][blk.y+1]=block;
                moved=true;
            }
        }
        if(dy==1)
        {
            if(map[blk.x][blk.y+2]==EMPTY)
            {
                map[blk.x][blk.y]=EMPTY;
                map[blk.x][blk.y+2]=block;
                moved=true;
            }
        }
        if(dy==-1)
        {
            if(map[blk.x][blk.y-1]==EMPTY)
            {
                map[blk.x][blk.y+1]=EMPTY;
                map[blk.x][blk.y-1]=block;
                moved=true;
            }
        }
    }

    //关羽
    if(block==GY)
    {
        BLock blk2;
        blk2=FindBlock(block);
        if(dy!=0)
        {
            if(map[blk2.x][blk2.y+dy]==EMPTY&&map[blk2.x+1][blk2.y+dy]==EMPTY)
            {
                map[blk2.x][blk2.y]=EMPTY;
                map[blk2.x+1][blk2.y]=EMPTY;
                map[blk2.x][blk2.y+dy]=GY;
                map[blk2.x+1][blk2.y+dy]=GY;
                moved=true;
            }
        }
        if(dx==1)
        {
            if(map[blk2.x+2][blk2.y]==EMPTY)
            {
                map[blk2.x+2][blk2.y]=GY;
                map[blk2.x][blk2.y]=EMPTY;
                moved=true;
            }
        }
        if(dx==-1)
        {
            if(map[blk2.x-1][blk2.y]==EMPTY)
            {
                map[blk2.x-1][blk2.y]=GY;
                map[blk2.x+1][blk2.y]=EMPTY;
                moved=true;
            }
        }
    }

    //曹操
    if(block==CC)
    {
        BLock blk3;
        blk3=FindBlock(block);
        if(dx==1)
        {
            if(map[blk3.x+2][blk3.y]==EMPTY&&map[blk3.x+2][blk3.y+1]==EMPTY)
            {
                map[blk3.x+2][blk3.y]=CC;
                map[blk3.x+2][blk3.y+1]=CC;
                map[blk3.x][blk3.y]=EMPTY;
                map[blk3.x][blk3.y+1]=EMPTY;
                moved=true;
            }
        }
        if(dx==-1)
        {
            if(map[blk3.x-1][blk3.y]==EMPTY&&map[blk3.x-1][blk3.y+1]==EMPTY)
            {
                map[blk3.x-1][blk3.y]=CC;
                map[blk3.x-1][blk3.y+1]=CC;
                map[blk3.x+1][blk3.y]=EMPTY;
                map[blk3.x+1][blk3.y+1]=EMPTY;
                moved=true;
            }
        }
        if(dy==1)
        {
            if(blk3.x==2&&blk3.y==4)
            {
                win=true;
            }
            else if(map[blk3.x][blk3.y+2]==EMPTY&&map[blk3.x+1][blk3.y+2]==EMPTY)
            {
                map[blk3.x][blk3.y+2]=CC;
                map[blk3.x+1][blk3.y+2]=CC;
                map[blk3.x][blk3.y]=EMPTY;
                map[blk3.x+1][blk3.y]=EMPTY;
                moved=true;
            }
        }
        if(dy==-1)
        {
            if(map[blk3.x][blk3.y-1]==EMPTY&&map[blk3.x+1][blk3.y-1]==EMPTY)
            {
                map[blk3.x][blk3.y-1]=CC;
                map[blk3.x+1][blk3.y-1]=CC;
                map[blk3.x][blk3.y+1]=EMPTY;
                map[blk3.x+1][blk3.y+1]=EMPTY;
                moved=true;
            }
        }
    }

	//移动成功处理
    if(moved)
    {
        lstdir=dx*2+dy;
    }

    return win;
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
	//禁止本游戏同时运行
    if(FindWindow(NULL,"华容道——左慈编写")!=NULL)
    {
        exit(0);
    }
    loadres();
    initgraph(500,350);
	//修改标题
    SetWindowText(GetHWnd(),"华容道——左慈编写");
    menu();
    return 0;
}

//游戏函数
void game(int mapnum)
{
    loadmap(mapnum);
    MOUSEMSG msg;
    int pmx,pmy;
    while(true)
    {
        while(MouseHit())
        {
            msg=GetMouseMsg();
            if(msg.uMsg==WM_LBUTTONDOWN)//按下时
            {
				//在游戏区
                if(msg.x<250&&msg.x>=50&&msg.y>=50&&msg.y<300)
                {
					//记录下开始按下的坐标
                    pmx=msg.x;
                    pmy=msg.y;
                    if(map[msg.x/50][msg.y/50]!=EMPTY&&map[msg.x/50][msg.y/50]!=BING)//鼠标之前没选中过
                    {
                        msmode=map[msg.x/50][msg.y/50];
                    }
                    else if(map[msg.x/50][msg.y/50]==BING)//选中兵
                    {
                        msmode=msg.x/50*10+msg.y/50;
                    }
                }
                else if(inrect(msg.x,msg.y,350,225,50,50))//重选地图
                {
                    msmode=0;
                    mapnum=0;
                    lstdir=-3;
                    *mapname=NULL;
                    choosemap();
                }
                else if(inrect(msg.x,msg.y,425,225,50,50))//重置游戏
                {
                    msmode=0;
                    lstdir=-3;
                    loadmap(mapnum);
                }
                else if(inrect(msg.x,msg.y,350,150,50,50))//后退一步
                {
                    switch(lstdir)//根据上次的移动后退
                    {
						case -3:
							break;
						case 1:
						{
							move((BLOCK)msmode,0,-1);
							break;
						}
						case 2:
						{
							move((BLOCK)msmode,-1,0);
							break;
						}
						case -1:
						{
							move((BLOCK)msmode,1,0);
							break;
						}
						case -2:
						{
							move((BLOCK)msmode,1,0);
							break;
						}
                    }
                    msmode=0;
                }
                else if(inrect(msg.x,msg.y,425,150,50,50))//游戏帮助
                {
					//从资源里创建窗口
                    DialogBox(GetModuleHandle(0),MAKEINTRESOURCE(HELPDLG),GetHWnd(),HelpDlg_Proc);
                }
            }
            else if(msg.uMsg==WM_LBUTTONUP)//鼠标弹起
            {
				//根据鼠标拖动轨迹移动

				//左右动
                if(abs(msg.x-pmx)>=abs(msg.y-pmy)&&abs(msg.x-pmx)>30)
                {
                    if(msg.x-pmx>0)
                    {
                        move((BLOCK)msmode,1,0);
                    }
                    else
                    {
                        move((BLOCK)msmode,-1,0);
                    }
                }
                
				//上下动
                if(abs(msg.x-pmx)<abs(msg.y-pmy)&&abs(msg.y-pmy)>30)
                {
                    if(msg.y-pmy>0)
                    {
                        move((BLOCK)msmode,0,1);
                    }
                    else
                    {
                        move((BLOCK)msmode,0,-1);
                    }
                }
            }
        }
		//画
        draw();
    }
}

//关于游戏
void about()
{
    MOUSEMSG msg;
    putimage(0,0,&aboutitf);
    while(true)
    {
        if(MouseHit())
        {
            msg=GetMouseMsg();
            if(msg.uMsg==WM_LBUTTONDOWN)
            {
                if(msg.x>=450&&msg.x<=490&&msg.y>=300&&msg.y<=340)
                {
                    menu();
                }
            }
        }
    }
}

//胜利
void win()
{
    putimage(0,0,&winimg);
    msmode=0;
    Sleep(2000);
	//胜利后重新选地图
    choosemap();
}

//选地图
void choosemap()
{
    MOUSEMSG msg;
    putimage(0,0,&cmapitf);
    int x,y;
    while(true)
    {
        while(MouseHit())
        {
            msg=GetMouseMsg();
            if(msg.uMsg==WM_LBUTTONDOWN)
            {
                for(y=0; y<3; y++)
                    for(x=0; x<4; x++)
                    {
                        if(msg.x>=x*125+30&&msg.x<=x*125+100&&msg.y<=y*70+90&&msg.y>=y*70+60)
                        {
							//地图号
                            mapnum=y*4+x+1;
							//执行游戏
                            game(mapnum);
                        }
                    }
                if(msg.x>=450&&msg.x<=490&&msg.y>=300&&msg.y<=340)
                {
					//返回菜单
                    menu();    
                }
            }
        }
    }
}

//菜单
void menu()
{
    MOUSEMSG mmsg;
    putimage(0,0,&menuitf);
    while(true)
    {
        while(MouseHit())
        {
            mmsg=GetMouseMsg();
            if(mmsg.uMsg==WM_LBUTTONDOWN)
            {
                if(mmsg.x>=150&&mmsg.x<=350)
                {
                    if(mmsg.y>=125&&mmsg.y<=175)
                    {
						//选地图
                        choosemap();   
                    }
                    if(mmsg.y>=225&&mmsg.y<=275)
                    {
						//关于游戏
                        about();    
                    }
                }
            }
        }
    }
}

//每一帧的绘制
void draw()
{
    int i,j;
    BLock BLOCK1;
    SetWorkingImage(&buffer);
    putimage(300,0,&gameinterface);

    //画兵,方格
    for(i=0; i<6; i++)
        for(j=0; j<7; j++)
        {
            if(map[i][j]==BORDER)
            {
                putimage(i*50,j*50,&border);
            }
            if(map[i][j]==EMPTY)
            {
                putimage(i*50,j*50,&empty);
            }
            if(map[i][j]==BING)
            {
                putimage(i*50,j*50,&bing);
            }
        }

    //把每个木块画一遍
    BLOCK1=FindBlock(CC);
    putimage(BLOCK1.x*50,BLOCK1.y*50,&cc);
    BLOCK1=FindBlock(GY);
    putimage(BLOCK1.x*50,BLOCK1.y*50,&gy);
    BLOCK1=FindBlock(ZF);
    putimage(BLOCK1.x*50,BLOCK1.y*50,&zf);
    BLOCK1=FindBlock(ZY);
    putimage(BLOCK1.x*50,BLOCK1.y*50,&zy);
    BLOCK1=FindBlock(MC);
    putimage(BLOCK1.x*50,BLOCK1.y*50,&mc);
    BLOCK1=FindBlock(HZ);
    putimage(BLOCK1.x*50,BLOCK1.y*50,&hz);

    //画出口和华容道
    putimage(100,300,&empty);
    putimage(150,300,&empty);
    setbkmode(TRANSPARENT);
    settextcolor(BLACK);
    settextstyle(50,0,"宋体");
    outtextxy(100,300,"出口");
    settextstyle(50,0,"楷体");
    outtextxy(150-textwidth("华容道")/2,0,"华容道");
	//写关卡名称编号
    settextstyle(40,0,"宋体");
    char mapnumtxt[9];
    sprintf(mapnumtxt,"第%d关",mapnum);
    outtextxy(320,70,mapnumtxt);
    outtextxy(320,110,mapname);
    SetWorkingImage();
    putimage(0,0,&buffer);
}

大家赶紧去动手试试吧!

此外,我也给大家分享我收集的其他资源,从最零基础开始的教程到C语言C++项目案例,帮助大家在学习C语言的道路上披荆斩棘!

整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)最重要的是你可以在群里面交流提问编程问题哦!

欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!

(资料素材领取↓↓↓↓↓↓↓↓)

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以回答你的问题。以下是一个使用 switch 语句实现猜拳游戏C++ 代码: ```c++ #include <iostream> #include <cstdlib> #include <ctime> using namespace std; int main() { int playerChoice; int computerChoice; // 生成随机数种子 srand(time(0)); // 让玩家输入选择(1:石头,2:剪刀,3:布) cout << "请出拳(1:石头,2:剪刀,3:布):" << endl; cin >> playerChoice; // 生成计算机的选择(1-石头,2-剪刀,3-布) computerChoice = rand() % 3 + 1; // 根据玩家和计算机的选择确定胜负 switch (playerChoice) { case 1: // 玩家出石头 if (computerChoice == 1) { cout << "平局!" << endl; } else if (computerChoice == 2) { cout << "你赢了!" << endl; } else { cout << "你输了!" << endl; } break; case 2: // 玩家出剪刀 if (computerChoice == 1) { cout << "你输了!" << endl; } else if (computerChoice == 2) { cout << "平局!" << endl; } else { cout << "你赢了!" << endl; } break; case 3: // 玩家出布 if (computerChoice == 1) { cout << "你赢了!" << endl; } else if (computerChoice == 2) { cout << "你输了!" << endl; } else { cout << "平局!" << endl; } break; default: cout << "选择无效!" << endl; break; } return 0; } ``` 这段代码首先让玩家输入选择(1:石头,2:剪刀,3:布),然后生成计算机的选择。接着使用 switch 语句判断玩家和计算机的选择,输出对应的胜负结果。注意,这里使用了 srand 函数来生成随机数种子,以保证每次运程序生成的随机数不同。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值