C语言实现的五子棋(附源码),使用了easy x图形库(graphics.h)

五子棋功能及图片展示

游戏界面

开始的界面,黑子优先落子
功能一:落子提示,十字准星(可以跟踪鼠标,提示该位置可以落子)
在这里插入图片描述
在这里插入图片描述
功能二:左侧的落子颜色提示(避免落子太多忘记当前落什么颜色的棋子)
在这里插入图片描述
在这里插入图片描述
功能三:悔棋
在这里插入图片描述
鼠标右键悔棋
在这里插入图片描述
功能四:再来一局(鼠标右键,一方胜利时触发)
在这里插入图片描述
在这里插入图片描述`
判断输赢的规则:每落下一颗棋子,以该棋子为中心,分别朝八个方向寻找相连且同色的棋子计数,如果相反的两方向之和等于4,则判断胜利

游戏背景:13天学完C语言(一本书)后做的游戏,了解图形库用了两天,写逻辑部分用了一天,每天五小时。
游戏缺点:1.代码比较凌乱,想到什么写什么了,主要是主函数那一块有些臃肿;2.没能实现联网对战功能;3.命名也应该很不规范,小白作品。
涉及到的知识点:指针,数组,循环,函数
后续:现在在学习c++,学完后会再写一次五子棋的,争取能联网对战。

源码:
#include <graphics.h>
#include <conio.h>
#include<stdio.h>
#include <time.h>

#define NUM_B 225 //棋子数量
#define HL 15 //上下
#define X(x) 162+x50
#define Y(y) 30+y
50
#define BXY 15 //横轴/纵轴数量
void board(void);
int get_x(short xx);
int get_y(short yy);
int left_right(int(*arr)[BXY], short x, short y); //左右
int up_down(int(*arr)[BXY], short x, short y); //上下
int lu_rd(int(*arr)[BXY], short x, short y); //左上右下
int ld_ru(int(*arr)[BXY], short x, short y); //左下右上
void win_b(void);
void win_w(void);
void fall_w(void); //落白子
void fall_b(void); //落黑子

int main()
{
int undo_x = 0, undo_y = 0;
int again = 0; //用于胜利后开启下一局的开关
int cut = 0; //用于胜利后棋盘不可下棋的开关
int FLAG[BXY][BXY]; //棋盘,储存棋子,0代表空,1代表白子,2代表黑子
int x, y; //坐标
int i, j, wb; //i,j储存鼠标上一个状态,wb控制下一局开局的棋子颜色(这个感觉有没有都一样,,,写了就不删了)
i = j = wb = 0;
int x1[2] = { -2,-2 }, y1[2] = { -2,-2 }; //储存鼠标前后状态,用于消除十字准星
board(); //创建窗口
fall_b();
/* 储存所有棋子坐标,并且把棋子状态设为0 */
for (y = 0; y < 15; y++)
for (x = 0; x < 15; x++)
FLAG[x][y] = 0;

MOUSEMSG m;		// 定义鼠标消息

while (true)           //游戏无限循环
{
	m = GetMouseMsg();        //获取鼠标信息
	switch (m.uMsg)
	{
	case WM_MOUSEMOVE:        //鼠标移动
		if (cut == 0 && (get_x(m.x) > -1 && get_x(m.x) < 15) && (get_y(m.y) > -1 && get_y(m.y) < 15) && FLAG[get_x(m.x)][get_y(m.y)] < 1)    //十字准星
		{
			// 创建一个矩形区域
			HRGN rgn = CreateRectRgn(162, 30, 862, 730);
			// 将该矩形区域设置为裁剪区
			setcliprgn(rgn);
			// 不再使用 rgn,清理 rgn 占用的系统资源
			DeleteObject(rgn);

			if (i == 0)
			{
				x1[i] = get_x(m.x);
				y1[i] = get_y(m.y);
				i = 1;
				j = 0;
			}
			else if (i == 1)
			{
				x1[i] = get_x(m.x);
				y1[i] = get_y(m.y);
				i = 0;
				j = 1;
			}
			setfillcolor(LIGHTBLUE);
			solidrectangle(X(get_x(m.x)) - 15, Y(get_y(m.y)) - 3, X(get_x(m.x)) + 15, Y(get_y(m.y)) + 3);
			solidrectangle(X(get_x(m.x)) - 3, Y(get_y(m.y)) - 15, X(get_x(m.x)) + 3, Y(get_y(m.y)) + 15);
		}
		break;
	case WM_LBUTTONDOWN:   //鼠标左键点击
		if (cut == 0 && (get_x(m.x) > -1 && get_x(m.x) < 15) && (get_y(m.y) > -1 && get_y(m.y) < 15) && FLAG[get_x(m.x)][get_y(m.y)] < 1)
		{
			// 取消之前设置的裁剪区
			setcliprgn(NULL);

			if (wb == 0)
			{
				setfillcolor(BLACK);
				solidcircle(X(get_x(m.x)), Y(get_y(m.y)), 20);
				undo_x = get_x(m.x);
				undo_y = get_y(m.y);
				fall_w();
				wb = 1;
				FLAG[get_x(m.x)][get_y(m.y)] = 2;

				if (left_right(FLAG, m.x, m.y) > 0 || up_down(FLAG, m.x, m.y) > 0 || lu_rd(FLAG, m.x, m.y) > 0 || ld_ru(FLAG, m.x, m.y) > 0)
				{

					win_b();
					again = 1;
					cut = 1;
				}
			}
			else if (wb == 1)
			{
				setfillcolor(WHITE);
				solidcircle(X(get_x(m.x)), Y(get_y(m.y)), 20);
				undo_x = get_x(m.x);
				undo_y = get_y(m.y);
				fall_b();
				wb = 0;
				FLAG[get_x(m.x)][get_y(m.y)] = 1;
				if (left_right(FLAG, m.x, m.y) > 0 || up_down(FLAG, m.x, m.y) > 0 || lu_rd(FLAG, m.x, m.y) > 0 || ld_ru(FLAG, m.x, m.y) > 0)
				{
					win_w();
					again = 1;
					cut = 1;
				}
			}
		}
		break;
	case WM_RBUTTONUP:               //鼠标右键点击
		if (again == 1)
		{
			for (y = 0; y < 15; y++)
				for (x = 0; x < 15; x++)
					FLAG[x][y] = 0;
			// 取消之前设置的裁剪区
			setcliprgn(NULL);
			board();
			undo_x = undo_y = 0;
			again = 0;
			cut = 0;
			if (wb == 1)
			{
				wb = 0;
				fall_b();
			}
			else
			{
				wb = 1;
				fall_w();
			}
		}
		else
		{
			if (FLAG[undo_x][undo_y] == 1)
			{
				// 取消之前设置的裁剪区
				setcliprgn(NULL);
				setfillcolor(RGB(209, 186, 116));                              //填充背景颜色
				solidrectangle(X(undo_x) - 20, Y(undo_y) - 20, X(undo_x) + 20, Y(undo_y) + 20);
				line(X(undo_x) - 20, Y(undo_y), X(undo_x) + 20, Y(undo_y));
				line(X(undo_x), Y(undo_y) - 20, X(undo_x), Y(undo_y) + 20);
				/*9个带黑点的落子位置*/
				if (undo_x != 15 && undo_y != 15 && (undo_x + 1) % 4 == 0 && (undo_y + 1) % 4 == 0)
				{
					setfillcolor(BLACK);
					fillcircle(X(undo_x), Y(undo_y), 5);
				}
				fall_w();
				FLAG[undo_x][undo_y] = 0;
				wb = 1;
			}
			else if (FLAG[undo_x][undo_y] == 2)
			{
				// 取消之前设置的裁剪区
				setcliprgn(NULL);

				setfillcolor(RGB(209, 186, 116));                              //填充背景颜色
				solidrectangle(X(undo_x) - 20, Y(undo_y) - 20, X(undo_x) + 20, Y(undo_y) + 20);
				line(X(undo_x) - 20, Y(undo_y), X(undo_x) + 20, Y(undo_y));
				line(X(undo_x), Y(undo_y) - 20, X(undo_x), Y(undo_y) + 20);
				/*9个带黑点的落子位置*/
				if (undo_x != 15 && undo_y != 15 && (undo_x + 1) % 4 == 0 && (undo_y + 1) % 4 == 0)
				{
					setfillcolor(BLACK);
					fillcircle(X(undo_x), Y(undo_y), 5);
				}
				fall_b();
				FLAG[undo_x][undo_y] = 0;
				wb = 0;
			}
		}
		break;
	}
	if (((get_x(m.x)) != x1[j] || (get_y(m.y) != y1[j])) && FLAG[x1[j]][y1[j]] < 1)
	{
		setfillcolor(RGB(209, 186, 116));                              //填充背景颜色
		solidrectangle(X(x1[j]) - 15, Y(y1[j]) - 15, X(x1[j]) + 15, Y(y1[j]) + 15);
		line(X(x1[j]) - 15, Y(y1[j]), X(x1[j]) + 15, Y(y1[j]));
		line(X(x1[j]), Y(y1[j]) - 15, X(x1[j]), Y(y1[j]) + 15);
		/*9个带黑点的落子位置*/
		if (x1[j] != 15 && y1[j] != 15 && (x1[j] + 1) % 4 == 0 && (y1[j] + 1) % 4 == 0)
		{
			setfillcolor(BLACK);
			fillcircle(X(x1[j]), Y(y1[j]), 5);
		}
	}
}
// 关闭图形窗口
closegraph();

_getch();

return 0;

}

void board()
{
initgraph(1024, 760); //窗口大小
setbkcolor(RGB(190, 231, 233)); //窗口背景
cleardevice();
setlinecolor(BLACK); //线条颜色
setlinestyle(PS_SOLID | PS_ENDCAP_SQUARE, 2); //棋盘边框线条样式
setfillcolor(RGB(209, 186, 116)); //棋盘背景颜色
fillrectangle(132, 0, 892, 760);
fillrectangle(162, 30, 862, 730); //棋盘大小,棋盘规格15X15
setlinestyle(PS_SOLID | PS_ENDCAP_SQUARE, 2); //棋盘线条样式
for (int i = 80; i <= 730; i += 50) //棋盘横线
line(162, i, 862, i);
for (int i = 212; i <= 862; i += 50) //棋盘竖线
line(i, 30, i, 730);
setfillcolor(BLACK); //圆点填充颜色为黑色
for (int i = 3; i <= 12; i += 4) //绘制9个圆点
{
fillcircle(X(i), Y(3), 5);
fillcircle(X(i), Y(7), 5);
fillcircle(X(i), Y(11), 5);
}
setfillcolor(RGB(190, 237, 199)); //棋盘背景颜色
fillrectangle(20, 310, 115, 425);
settextcolor(BLACK);
settextstyle(25, 0, _T(“Consolas”));
wchar_t s[] = L"请落子";
outtextxy(30, 315, s);

fillrectangle(5, 460, 125, 495);
settextstyle(15, 0, _T("Consolas"));
wchar_t s2[] = L"点击鼠标右键悔棋";
outtextxy(10, 470, s2);

settextstyle(25, 0, _T("Consolas"));
wchar_t s1[] = L"yp_lien";
settextcolor(RGB(214, 213, 183));
outtextxy(930, 730, s1);

}

void fall_w()
{
setfillcolor(WHITE);
solidcircle(66, 380, 30);
}
void fall_b()
{
setfillcolor(BLACK);
solidcircle(66, 380, 30);
}

int get_x(short xx)
{
if (((162 - HL) <= xx) && ((162 + HL) >= xx))
return 0;
else if (((212 - HL) <= xx) && ((212 + HL) >= xx))
return 1;
else if (((262 - HL) <= xx) && ((262 + HL) >= xx))
return 2;
else if (((312 - HL) <= xx) && ((312 + HL) >= xx))
return 3;
else if (((362 - HL) <= xx) && ((362 + HL) >= xx))
return 4;
else if (((412 - HL) <= xx) && ((412 + HL) >= xx))
return 5;
else if (((462 - HL) <= xx) && ((462 + HL) >= xx))
return 6;
else if (((512 - HL) <= xx) && ((512 + HL) >= xx))
return 7;
else if (((562 - HL) <= xx) && ((562 + HL) >= xx))
return 8;
else if (((612 - HL) <= xx) && ((612 + HL) >= xx))
return 9;
else if (((662 - HL) <= xx) && ((662 + HL) >= xx))
return 10;
else if (((712 - HL) <= xx) && ((712 + HL) >= xx))
return 11;
else if (((762 - HL) <= xx) && ((762 + HL) >= xx))
return 12;
else if (((812 - HL) <= xx) && ((812 + HL) >= xx))
return 13;
else if (((862 - HL) <= xx) && ((862 + HL) >= xx))
return 14;
else
return -1;
}

int get_y(short yy)
{
if (((30 - HL) <= yy) && ((30 + HL) >= yy))
return 0;
else if (((80 - HL) <= yy) && ((80 + HL) >= yy))
return 1;
else if (((130 - HL) <= yy) && ((130 + HL) >= yy))
return 2;
else if (((180 - HL) <= yy) && ((180 + HL) >= yy))
return 3;
else if (((230 - HL) <= yy) && ((230 + HL) >= yy))
return 4;
else if (((280 - HL) <= yy) && ((280 + HL) >= yy))
return 5;
else if (((330 - HL) <= yy) && ((330 + HL) >= yy))
return 6;
else if (((380 - HL) <= yy) && ((380 + HL) >= yy))
return 7;
else if (((430 - HL) <= yy) && ((430 + HL) >= yy))
return 8;
else if (((480 - HL) <= yy) && ((480 + HL) >= yy))
return 9;
else if (((530 - HL) <= yy) && ((530 + HL) >= yy))
return 10;
else if (((580 - HL) <= yy) && ((580 + HL) >= yy))
return 11;
else if (((630 - HL) <= yy) && ((630 + HL) >= yy))
return 12;
else if (((680 - HL) <= yy) && ((680 + HL) >= yy))
return 13;
else if (((730 - HL) <= yy) && ((730 + HL) >= yy))
return 14;
else
return -1;
}

void win_b()
{
setbkcolor(RGB(214, 213, 183));
settextcolor(RGB(244, 96, 108));
wchar_t s[] = L"黑棋胜利,黑棋优先落子";
wchar_t s1[] = L"点击鼠标右键开始下一局";
settextstyle(30, 0, _T(“Consolas”));
outtextxy(380, 5, s);
outtextxy(380, 35, s1);

}
void win_w()
{
setbkcolor(RGB(214, 213, 183));
settextcolor(RGB(244, 96, 108));
wchar_t s[] = L"白棋胜利,白棋优先落子";
wchar_t s1[] = L"点击鼠标右键开始下一局";
settextstyle(30, 0, _T(“Consolas”));
outtextxy(380, 5, s);
outtextxy(380, 35, s1);
}

int left_right(int(*p)[BXY], short x, short y)
{
int k, i, j;

i = j = 0;
for (k = 1; k < 5; k++)
	if (p[get_x(x) - k][get_y(y)] == p[get_x(x)][get_y(y)])
		i++;
	else
		k = 5;
for (k = 1; k < 5; k++)
	if (p[get_x(x) + k][get_y(y)] == p[get_x(x)][get_y(y)])
		j++;
	else
		k = 5;

return ((i + j) > 3) ? 1 : -1;

}

int up_down(int(*p)[BXY], short x, short y) //上下
{
int k, i, j;

i = j = 0;
for (k = 1; k < 5; k++)
	if (p[get_x(x)][get_y(y) - k] == p[get_x(x)][get_y(y)])
		i++;
	else
		k = 5;
for (k = 1; k < 5; k++)
	if (p[get_x(x)][get_y(y) + k] == p[get_x(x)][get_y(y)])
		j++;
	else
		k = 5;

return ((i + j) > 3) ? 1 : -1;

}

int lu_rd(int(*p)[BXY], short x, short y) //左上右下
{
int k, i, j;

i = j = 0;
for (k = 1; k < 5; k++)
	if (p[get_x(x) - k][get_y(y) - k] == p[get_x(x)][get_y(y)])
		i++;
	else
		k = 5;
for (k = 1; k < 5; k++)
	if (p[get_x(x) + k][get_y(y) + k] == p[get_x(x)][get_y(y)])
		j++;
	else
		k = 5;

return ((i + j) > 3) ? 1 : -1;

}

int ld_ru(int(*p)[BXY], short x, short y) //左下右上
{
int k, i, j;

i = j = 0;
for (k = 1; k < 5; k++)
	if (p[get_x(x) - k][get_y(y) + k] == p[get_x(x)][get_y(y)])
		i++;
	else
		k = 5;
for (k = 1; k < 5; k++)
	if (p[get_x(x) + k][get_y(y) - k] == p[get_x(x)][get_y(y)])
		j++;
	else
		k = 5;

return ((i + j) > 3) ? 1 : -1;

}

  • 13
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值