首页 > 编程语言 >C语言例题,五子棋在判断胜负,下棋落子上的算法参考,以及基于easyx的实现源码

C语言例题,五子棋在判断胜负,下棋落子上的算法参考,以及基于easyx的实现源码

时间:2024-06-14 21:32:19浏览次数:15  
标签:int 五子棋 number 50 源码 && 100 例题 mouse

赘述

首先我们需要在外部定义一个(n+4)*(n+4)且全为0的二维数组(为什么要加4见判断胜负部分)

          以及鼠标消息变量mouse

        (设成0只是为了判断是否是未落子区域),其中n为我们所绘制棋盘各行/列单位元个数+1

如在800*800的棋盘中我们的n就是9

当我们将这个二维数组可视化那就是一个13*13的矩阵

其中框起来的区域就是我们所绘制的棋盘转换成矩阵的区域。也就是说将棋盘上的各个交点视为矩阵内元素

正式判断落子

这里棋盘为800*800,且上左界面间隔均为50,单位格为100*100,(边缘隔出区域为了能让边缘落子能清晰显示)

对此我们可以写出棋盘坐标与矩阵坐标的关系

num[x+4][y+4]→(x*100+50,y*100+50)

(下棋时我们以1代表黑棋,2代表白棋)

int locate(ExMessage mouse, int n)
{
	int x, y;
	mouse.x -= 50, mouse.y -= 50;
	mouse.x % 100 <= 50 ? x = mouse.x / 100 : x = mouse.x / 100 + 1;//判断落子区域
	mouse.y % 100 <= 50 ? y = mouse.y / 100 : y = mouse.y / 100 + 1;
	if (number[x + 4][y + 4] != 0) return 0;//判断区域内是否已落子
	else number[x + 4][y + 4] = n;
	fillcircle(x * 100+50, y * 100+50, 35);
	if (win(x + 4, y + 4, n))	gameover(n);//判断是否分胜负
    return 1;
}

1:为何开始要都减50。

                减完就可以将原本的坐标方程x*100+50,y*100+50)视为(x*100,y*100)方便后续,只需要在画棋时再加上去。

        可以不减,也可以在最初就直接使用setorigin改变坐标

2:判断部分。(棋盘某交点为圆心50为半径的区域都视为在该交点下落子)

        

                其中

mouse.x % 100 <= 50 ? x = mouse.x / 100 : x = mouse.x / 100 + 1;
mouse.y % 100 <= 50 ? y = mouse.y / 100 : y = mouse.y / 100 + 1;

        可理解为判断落子距离哪一行(列)更近

最后画子时直接fillcircle(x*100+50,y*100+50,35);

判断胜负部分

直接上:

int win(int x, int y, int k)
{
	for (int n = 0; n < 5; n++)
		if (number[x - n][y] == k && number[x - n + 1][y] == k && number[x - n + 2][y] == k && number[x - n + 3][y] == k && number[x - n + 4][y] == k)
			return 1;
	for (int n = 0; n < 5; n++)
		if (number[x][y - n] == k && number[x][y - n + 1] == k && number[x][y - n + 2] == k && number[x][y - n + 3] == k && number[x][y - n + 4] == k)
			return 1;
	for (int n = 0; n < 5; n++)
		if (number[x - n][y - n] == k && number[x - n + 1][y - n + 1] == k && number[x - n + 2][y - n + 2] == k && number[x - n + 3][y - n + 3] == k && number[x - n + 4][y - n + 4] == k)
			return 1;
	for (int n = 0; n < 5; n++)
		if (number[x - n][y + n] == k && number[x - n + 1][y + n - 1] == k && number[x - n + 2][y + n - 2] == k && number[x - n + 3][y + n - 3] == k && number[x - n + 4][y + n - 4] == k)
			return 1;
	return 0;
}

参考http://t.csdnimg.cn/vT9HH

其中可拆解为4道直线方程

即理解为在所下点的位置沿这四条直线前后观察是否有连续五个与自己相同的元素

而在棋盘边缘,如最左边的点,再往左看就找不到棋子了。于是我们便在棋盘所代表的矩阵边缘再填充元素0。这样9*9的矩阵就构造成了13*13,同时在棋盘范围内每个点的每个方向都能保证有包括自己在内的五个点

全部

左键下黑,右键下白,且黑先手

#define _CRT_SECURE_NO_WARNINGS 
#undef UNICODE
#undef _UNICODE
#include<stdio.h>
#include<graphics.h>
#include<windows.h>
#include<stdlib.h>
static int number[9 + 4][9 + 4] = { 0 };//类似矩阵初期的沙补填充法
void buildboard()
{
	initgraph(900 + 300, 900, 1);
	setbkcolor(BROWN);
	cleardevice();
	setbkmode(TRANSPARENT);
	setlinestyle(PS_SOLID | PS_ENDCAP_SQUARE, 4);
	setlinecolor(BLACK);
	settextcolor(YELLOW);
	for (int a = 0; a < 900; a += 100)
	{
		line(a + 50, 50, a + 50, 850);//画竖线
		line(50, a + 50, 850, a + 50);//画横线
	}
	IMAGE pic;
	loadimage(&pic, "捷豹3.png");
	putimage(980, 35, &pic);
}
void gameover(int n)
{
	settextstyle(200, 0, "宋体");
	IMAGE  pic1, pic2;
	loadimage(&pic1, "捷豹1.png");
	loadimage(&pic2, "捷豹2.png");
	const char* whitewin = "白方胜利";
	const char* blackwin = "黑方胜利";
	int x = textwidth(blackwin);
	if (n == 1)
	{
		putimage(0, 0, &pic1);
		outtextxy(225 + (450 - x) / 2, 500, blackwin);
	}
	else
	{
		putimage(0, 0, &pic2);
		outtextxy(225 + (450 - x) / 2, 500, whitewin);
	}
	getchar();
	closegraph();
	exit(0);
}
int win(int x, int y, int k)
{
	for (int n = 0; n < 5; n++)
		if (number[x - n][y] == k && number[x - n + 1][y] == k && number[x - n + 2][y] == k && number[x - n + 3][y] == k && number[x - n + 4][y] == k)
			return 1;
	for (int n = 0; n < 5; n++)
		if (number[x][y - n] == k && number[x][y - n + 1] == k && number[x][y - n + 2] == k && number[x][y - n + 3] == k && number[x][y - n + 4] == k)
			return 1;
	for (int n = 0; n < 5; n++)
		if (number[x - n][y - n] == k && number[x - n + 1][y - n + 1] == k && number[x - n + 2][y - n + 2] == k && number[x - n + 3][y - n + 3] == k && number[x - n + 4][y - n + 4] == k)
			return 1;
	for (int n = 0; n < 5; n++)
		if (number[x - n][y + n] == k && number[x - n + 1][y + n - 1] == k && number[x - n + 2][y + n - 2] == k && number[x - n + 3][y + n - 3] == k && number[x - n + 4][y + n - 4] == k)
			return 1;
	return 0;
}
int locate(ExMessage mouse, int n)
{
	int x, y;
	mouse.x -= 50, mouse.y -= 50;
	mouse.x % 100 <= 50 ? x = mouse.x / 100 : x = mouse.x / 100 + 1;
	mouse.y % 100 <= 50 ? y = mouse.y / 100 : y = mouse.y / 100 + 1;
	if (number[x + 4][y + 4] != 0)return 0;
	else number[x + 4][y + 4] = n;
	fillcircle(x * 100+50, y * 100+50, 35);
	if (win(x + 4, y + 4, n))	gameover(n);
	return 1;
}
void game()
{
	int n = 2;
	while (1)
	{
		ExMessage mouse;
		peekmessage(&mouse, EM_MOUSE);
		if (mouse.message == WM_LBUTTONDOWN)//左键黑棋
		{
			if (n % 2)
				continue;
			if (mouse.x < 30 || mouse.x>870 || mouse.y > 870 || mouse.y < 30) continue;//落子在区域外
			setfillcolor(BLACK);
			if (!locate(mouse, 1)) continue;
			n++;
		}
		if (mouse.message == WM_RBUTTONDOWN)//右
		{
			if ((n + 1) % 2)
				continue;
			if (mouse.x < 50 || mouse.x>850 || mouse.y > 850 || mouse.y < 50) continue;
			setfillcolor(WHITE);
			if (!locate(mouse, 2)) continue;
			n++;
		}
	}
}
int main()
{
	buildboard();
	game();
}

有多繁琐部分

标签:int,五子棋,number,50,源码,&&,100,例题,mouse
From: https://blog.csdn.net/2403_82795090/article/details/139678699

相关文章