编译器必须包含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