EGE五子棋(调节窗口大小,悔棋,重开,鼠标点击)

编译器必须包含EGE库,不然无法编译运行,最好使用小熊猫进行编译

在编译器选项中加上-mwindows可以关闭控制台

不想写博文,代码注释很详细

//首先是头文件

#include<graphics.h>
#include<cstring>
#include<windows.h>
#include<iostream>

//就这几个,其中第一个是必须的,其余的估计可以删
#define LSize 60
#define Msize 40
#define SSize 30
//定义了几类宏,分别表示大窗口小窗口中窗口的单个图片尺寸
using namespace std;
POINT mouse0;//这是一个鼠标结构体,用于获取鼠标的位置
int ESize;//这是用于表示当前窗口尺寸的
int x, y,tx,ty,flag,stepS,vic;//分别表示鼠标的坐标和对应的二维数组坐标,当前步数,记录胜利的一方
int Lx[300],Ly[300];//一个栈用于存储每一步方便悔棋
int logic[16][16];//进行逻辑运算的二维数组
int winB=0,winW=0;//表示黑旗与白棋赢的次数

PIMAGE picRI[4];

void getZoomImage(PIMAGE pimg, const char* fileName, int width, int height)
{
    PIMAGE temp = newimage();
    getimage(temp, fileName);
    
    if ((getwidth(pimg) != width) || (getheight(pimg) != height))
        resize(pimg, width, height);
    
    putimage(pimg, 0, 0, width, height, temp, 0, 0, getwidth(temp), getheight(temp));
    
    delimage(temp);
}//读入图片的函数,这是参考依稀大大的

void read()//载入图片
{
    for(int i=0;i<=3;i++)
        picRI[i]=newimage();
    getZoomImage(picRI[0],"0.png",ESize,ESize);
    //putimage(0, 0, picRI[0]);getch();
    getZoomImage(picRI[1],"1.png",ESize,ESize);
    //putimage(0, 0, picRI[1]);getch();
    getZoomImage(picRI[2],"-1.png",ESize,ESize);
    //putimage(0, 0, picRI[2]);getch();
    getZoomImage(picRI[3],"3.png",ESize,ESize);
    //putimage(0, 0, picRI[3]);getch();
    return;
}

int max(int a,int b)
{if(a>=b) return a;return b;}
int min(int a,int b)
{if(a<=b) return a;return b;}

void SizeFirst()//设置窗口大小的函数
{
    ESize=Msize;
    setcaption("五子棋");//设置窗口的标题
    initgraph(ESize*15, ESize*15+40,INIT_NOFORCEEXIT);
    xyprintf(0,0,"按下 S M L调整至窗口大小合适");
    for (; is_run(); delay_fps(ESize))
    {
        while(kbhit())//读入字符,调整窗口大小
        {
            int ch=getch();
            switch (ch) {
            case 's':
                ESize=SSize;
                closegraph();
                initgraph(ESize*15, ESize*15+40,INIT_NOFORCEEXIT);
                xyprintf(0,0,"按下 小写S M L调整至窗口大小合适");
                break;
            case 'm':
                ESize=Msize;
                closegraph();
                initgraph(ESize*15, ESize*15+40,INIT_NOFORCEEXIT);
                xyprintf(0,0,"按下 小写S M L调整至窗口大小合适");
                break;
            case 'l':
                ESize=LSize;
                closegraph();
                initgraph(ESize*15, ESize*15+40,INIT_NOFORCEEXIT);
                xyprintf(0,0,"按下 小写S M L调整至窗口大小合适");
                break;
            case 13:
                return;
            }
        }
    }
    return;
}

void First()//设置字体和颜色,初始化地图资源和胜利场数
{
    memset(logic,0,sizeof(logic));
    memset(Lx,0,sizeof(Lx));
    memset(Ly,0,sizeof(Ly));
    setfont(max(20,ESize/2), 0, "宋体");
    setbkcolor(BLACK);setcolor(WHITE);
    flag=1;//-1是白子存在2里面,1是黑子存在1里面
    stepS=1;
    vic=0;
}

void logicP()//用于输出棋盘
{
    cleardevice();
    if(logic[tx][ty]==0) logic[tx][ty]=3;//如果鼠标对应处没有棋子,标记,后续输出灰色待定图片
    for(int i=1;i<=15;i++)
        for(int j=1;j<=15;j++)
    {
        int P=logic[i][j];
        if(P==-1) P=2;
        putimage((i-1)*ESize, 40+(j-1)*ESize,picRI[P]);//输出黑白或者空的图片
    }
    if(vic!=0)//分别在获胜时输出对应信息并重开游戏
    {
        if(vic==1)
        {
            setcolor(BLACK);setbkcolor(LIGHTBLUE);winB++;
            xyprintf(0,0,"游戏结束!黑子获胜!!!按键盘上任意键重开");
        }
        else
        {
            setcolor(WHITE);setbkcolor(LIGHTBLUE);winW++;
            xyprintf(0,0,"游戏结束!白子获胜!!!按键盘上任意键重开");
        }
        getch();
        First();
        return;
    }
    if(flag==1) {setcolor(BLACK);setbkcolor(LIGHTBLUE);xyprintf(0,0,"当前执黑子      黑胜 %d  白胜 %d",winB,winW);}
    else {setcolor(WHITE);setbkcolor(LIGHTBLUE);xyprintf(0,0,"当前执白子      黑胜 %d  白胜 %d",winB,winW);}
    xyprintf(ESize*10,0,"R 悔棋");//在一般情况下输出当前棋子信息和悔棋对应的按键
    if(logic[tx][ty]==3) logic[tx][ty]=0;//注意将标记处复原
    return;
}

void logicCAL()//用于逻辑判断
{
    int sum=0;
    for(int i=max(1,tx-4);i<=min(15,tx+4);i++)//枚举四种方向,检验是否成五子即可
    {//注意边界是15,不能枚举超过15的子,当然实际上也可以,初始化时这些地方都是默认空棋子
        if(logic[i][ty]!=flag)//一旦碰到与当前棋子颜色不同的(含空棋子)就把计数器变成零
        {sum=0;continue;}
        else sum++;
        if(sum==5) {vic=flag;return;}
    }
    for(int i=max(1,ty-4);i<=min(15,ty+4);i++)
    {
        if(logic[tx][i]!=flag)
        {sum=0;continue;}
        else sum++;
        if(sum==5) {vic=flag;return;}
    }
    for(int i=tx-4,j=ty-4;i<=tx+4&&j<=ty+4;i++,j++)
    {
        if(i<1 || i>15 || j<1 || j>15) 
        {sum=0;continue;}
        if(logic[i][j]!=flag)
        {sum=0;continue;}
        else sum++;
        if(sum==5) {vic=flag;return;}
    }
    for(int i=tx-4,j=ty+4;i<=tx+4&&j>=ty-4;i++,j--)
    {
        if(i<1 || i>15 || j<1 || j>15) 
        {sum=0;continue;}
        if(logic[i][j]!=flag)
        {sum=0;continue;}
        else sum++;
        if(sum==5) {vic=flag;return;}
    }
    return;
}

int main()
{
    SizeFirst();
    First();
//    initgraph(ESize*15, ESize*15+40,INIT_NOFORCEEXIT);
//    setcaption("五子棋");//设置窗口的标题
    read();
//    setfont(30, 0, "宋体");        //设置文字宽度和字体
    for (; is_run(); delay_fps(60)) {
        //定义个鼠标结构体变量
        mouse_msg msg;
        //获取鼠标消息
        
        while (mousemsg()) 
            msg = getmouse();
        
        mousepos(&x, &y);
        tx=x/ESize;tx++;//由于我的强迫症,一般不会使用数组[0]处的变量而是自动变成正整数
        ty=max(y-40,0)/ESize;ty++;//这是根据鼠标位置计算对应的二维数组逻辑位置
        /*    key_msg jian=getkey();
          if(jian.msg==key_msg_down && jian.key==key_R && stepS!=1)
          {logic[Lx[stepS-1]][Ly[stepS-1]]=0;stepS--;flag=-flag;continue;}*/
        while(kbhit())
        {
            int ch=getch();
            if(ch=='r' && stepS>1)//这是在按下r时回溯一步
            {    
                stepS--;//出栈回溯一步
                flag=-flag;logic[Lx[stepS]][Ly[stepS]]=0;//出栈时棋子换手
                Lx[stepS+1]=Ly[stepS+1]=0;
                logicP();continue;//打印棋盘
            }
        }
        if(msg.is_left() && msg.is_down() && logic[tx][ty]==0 && y>40)
        {logic[tx][ty]=flag;flag=-flag;Lx[stepS]=tx;Ly[stepS]=ty;stepS++;}//保存这一步入栈,总步数加一,棋子换手
        flag=-flag;logicCAL();flag=-flag;//flag1和-1表示黑子和白子,判断时先换手回来,再换回去
        logicP();//打印棋盘
        //if(vic!=0) break;//此处去掉注释将在一方获胜时结束游戏
    }
    return 0;
}

这是对应的图片资源,记得保存成png格式,水印可以自己擦掉

有什么好点子可以找我,一起讨论一下啦

主要参考和学习了@依稀_yjxy的专栏,这是一位真带佬,快去膜拜!!!

分别命名为0.png  1.png  -1.png  3.png

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
EGE是Easy Graphics Library的缩写,是一款基于C语言的图形库,可以用于在Windows平台上进行图形编程。下面是实现通过鼠标滚轮缩放窗口大小的示例代码: ```c #include <graphics.h> #include <conio.h> int main() { initgraph(640, 480); // 创建一个640x480的窗口 setbkcolor(WHITE); cleardevice(); int x = 320, y = 240, r = 50; circle(x, y, r); // 在窗口中心画一个半径为50的圆 while (!kbhit()) // 循环,直到用户按下键盘 { int delta = 0; if (MouseHit()) // 如果有鼠标事件 { MOUSEMSG msg = GetMouseMsg(); if (msg.uMsg == WM_MOUSEWHEEL) // 如果是鼠标滚轮事件 { delta = (int)msg.wheel; // 获取滚轮滚动的距离 } } if (delta != 0) // 如果滚轮滚动了 { int width = getwidth(); // 获取当前窗口的宽度 int height = getheight(); // 获取当前窗口的高度 int new_width = width + delta * 10; // 计算新的窗口宽度 int new_height = height + delta * 7; // 计算新的窗口高度 resize(new_width, new_height); // 调整窗口大小 cleardevice(); // 清空窗口 circle(x, y, r); // 重新画圆 } } closegraph(); return 0; } ``` 在上面的代码中,我们首先创建了一个640x480的窗口,并在其中心画了一个半径为50的圆。然后进入一个循环,监听鼠标事件。如果有鼠标滚轮事件,就获取滚轮滚动的距离,根据这个距离计算新的窗口宽度和高度,并调用resize函数调整窗口大小,最后清空窗口并重新画圆。如果用户按下了键盘,就退出循环,关闭窗口。 需要注意的是,在EGE中,鼠标滚轮事件的消息类型是WM_MOUSEWHEEL,滚轮滚动的距离通过MOUSEMSG结构体的wheel成员获取。另外,getwidth和getheight函数可以获取当前窗口的宽度和高度,resize函数可以调整窗口大小
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值