我的第一篇CSDN博文(只是感悟贴,举例子)—论计算几何的可视化

本文分享了作者从ACM竞赛转向学习实际应用的心得,特别是对计算几何可视化领域的兴趣。通过发现并使用EasyX库,作者体验到图形处理的便捷,并提供了一个基于EasyX的迷宫游戏示例,鼓励对此感兴趣的朋友一起探讨。
摘要由CSDN通过智能技术生成
            首先声明下我的这篇文章并非转载也非全部原创,我只是一名普通的厦门大学大二计算机系学生。前一段做了很多acm题目之后发现很空洞总像是缺了一点什么 快哭了,比如有一道题目是这样子的:

2036 改革春风吹满

Problem Description
  “ 改革春风吹满地,
不会AC没关系;
实在不行回老家,
还有一亩三分地。
谢谢!(乐队奏乐)”

话说部分学生心态极好,每天就知道游戏,这次考试如此简单的题目,也是云里雾里,而且,还竟然来这么几句打油诗。
好呀,老师的责任就是帮你解决问题,既然想种田,那就分你一块。
这块田位于浙江省温州市苍南县灵溪镇林家铺子村,多边形形状的一块地,原本是linle 的,现在就准备送给你了。不过,任何事情都没有那么简单,你必须首先告诉我这块地到底有多少面积,如果回答正确才能真正得到这块地。
发愁了吧?就是要让你知道,种地也是需要AC知识的!以后还是好好练吧...

Input
  输入数据包含多个测试实例,每个测试实例占一行,每行的开始是一个整数n(3<=n<=100),它表示多边形的边数(当然也是顶点数),然后是按照逆时针顺序给出的n个顶点的坐标(x1, y1, x2, y2... xn, yn),为了简化问题,这里的所有坐标都用整数表示。
输入数据中所有的整数都在32位整数范围内,n=0表示数据的结束,不做处理。

Output
  对于每个测试实例,请输出对应的多边形面积,结果精确到小数点后一位小数。
每个实例的输出占一行。

Sample Input
  3 0 0 1 0 0 1
4 1 0 0 1 -1 0 0 -1
0

Sample Output
  0.5
2.0

Algorithm Analyse
  可以利用多边形求面积公式:
S = 0.5 * ( (x0*y1-x1*y0) + (x1*y2-x2*y1) + ... + (xn*y0-x0*yn) )
其中点(x0, y0), (x1, y1), ... , (xn, yn)为多边形上按逆时针顺序的顶点。

简要证明:
1.我们先简单地从三个点入手(包括原点)。


面积S△OAB = SABCD - S△OAD - S△OBC ·SABCD = (y0 + y1) × (x0 - x1) ÷ 2 ·S△OAD = x0 × y0 ÷ 2 ·S△OBC = (-x1) × y1 ÷ 2 S△OAB = (x0 × y0 + x0 × y1 - x1 × y0 - x1 × y1 - x0 × y0 + x1 × y1) ÷ 2 = (x0 × y1 - x1 × y0) ÷ 2 公式成立。同理你可以算出其他情况也能符合这个公式。
2.假设该公式对于n个顶点的多边形成立。即:
S = 0.5 * ( (x0*y1-x1*y0) + (x1*y2-x2*y1) + ... + (xn*y0-x0*yn) )

再加如第n+1点后,面积S' = S + S△A0AnAn+1 ·S = 0.5 * ( (x0*y1-x1*y0) + (x1*y2-x2*y1) + ... + (xn*y0-x0*yn) ) ·S△A0AnAn+1 = 0.5 * ( (X0*Yn-Xn*Y0) + (Xn*Yn+1-Xn+1*Yn) + (Xn+1*Y0-X0*Yn+1) ) ∴S' = S = 0.5 * ( (X0*Y1-X1*Y0) + (X1*Y2-X2*Y1) + ... + (Xn*Yn+1-Xn+1*Yn) + (Xn+1*Y0-X0*Yn+1) )
综上所述,得到公式:S = 0.5 * ( (x0*y1-x1*y0) + (x1*y2-x2*y1) + ... + (xn*y0-x0*yn) )
得证! 
 

#include <math.h>
#include <stdio.h>

int main(void)
{
   
    int x[3], y[3], n;
    double sum;

    while (scanf("%d", &n), n)
    {
   
        scanf("%d%d", x, y);
        x[2] = x[0]; y[2] = y[0];
        sum = 0.0;
        while (--n)
        {
   
            scanf("%d%d", x+1, y+1);
            sum += x[0]*y[1] - x[1]*y[0];
            x[0] = x[1]; y[0] = y[1];
        }
        sum += x[0]*y[2] - x[2]*y[0];
        printf("%.1f\n", sum / 2.0);
    }

    return 0;
}
acm中有极多这种题,比如说open poj的肿瘤面积和肿瘤周长等,还有福大oj的光线的反射等问题,在vc6.0上只能显示数据。而图像题根据高中老师说的数形结合才能事半功倍, 冷冰冰的数字并不能完全解决图像问题,不仅容易产生讨论不够全面等弊病,而且长期以往会渐渐失去对编程的乐趣。这里我有基于几点的思考(那些神牛勿喷!!鄙人乃大一上才真正开始学计算机的菜鸟):

    1.在实际编程中,函数很多都是直接调用的!在一个功能完备的平台中,一些常见的算法比如qsort,isalpha.......都是不需要自己编的,而acm中由于设置的问题比较特别,或是有一些限定条件,需要一些比较特殊的技巧,所以大量经典的算法都是不能够直接用的。而且实际意义不大,很多题目思维的训练大于实际,比如说刚才那道题,我相信用图形处理软件或是matlab之类的处理肯定比用c的好,把几个点输入进去就可以出来面积,浪费时间不说,直接调用的效率还更高。。。

    2.这个寒假我想学一些实际方面的东西,开始选了php,还屁颠屁颠第去图书馆借了一本书,发现要装5个软件,php,一种神奇的语言,然后就此作罢!后来就去想编一编游戏啊什么的!但是网上的代码都指向了一个vc 中没有的库,就是它# include <graphics.h> ,游戏=图形+人机交互+算法(主要是计算几何),没了图形玩个毛线,又屁颠屁颠第折腾了半天,最后发现了http://www.easyx.cn/这个好东西,里面的游戏代码都开源,而且能跑,但是之前要先安装一个库。这是一个神奇的网站,对,它不是58同城生气,它是easyx,上面教授了一些计算机几何学,分形学等学科,我认为它好主要是它实例多,不是泛泛而谈,然后有帮助,如果哪个函数不懂可以在上面查,还有它的版主超赞的,会在贴吧上解决吧友们的问题

       下面是我最近研究的一个例子:(其实就是一个变形的走迷宫游戏)

///
// 程序名称:矿井逃生
// 编译环境:Visual C++ 6.0 / 2010,EasyX 2013霜降版
// 作  者:yangw80 <yw80@qq.com>
// 最后修改:2013-11-15
//
#include <easyx.h>
#include <time.h>
#include <math.h>
#include <stdio.h>

// 定义常量
#define PI			3.141592653589		// 圆周率
#define UNIT_GROUND	0					// 表示地面
#define UNIT_WALL	1					// 表示墙
#define LIGHT_A		PI / 3				// 灯光的角度范围
#define	LIGHT_R		120					// 灯光的照射距离
#define	WIDTH		480					// 矿井的宽度
#define	HEIGHT		480					// 矿井的高度
#define SCREENWIDTH	640					// 屏幕宽度
#define	SCREENHEIGHT 480				// 屏幕高度
#define	UNIT		20					// 每个墙壁单位的大小
#define PLAYER_R	5					// 游戏者的半径

// 定义常量
const	SIZE	g_utMap = {
   23, 23};		// 矿井地图的尺寸(基于 UNIT 单位)
const	POINT	g_utPlayer = {
   1, 1};	// 游戏者的位置(基于 UNIT 单位)
const	POINT	g_utExit = {
   21, 22};	// 出口位置(基于 UNIT 单位)
const	POINT	g_ptOffset = {
   10, 10};	// 矿井显示在屏幕上的偏移量

//
// 定义全局变量
//
POINT	g_ptPlayer;						// 游戏者的位置
POINT	g_ptMouse;						// 鼠标位置
IMAGE	g_imgMap(WIDTH, HEIGHT);		// 矿井平面图
DWORD*	g_bufMap;						// 矿井平面图的显存指针
IMAGE	g_imgRender(WIDTH, HEIGHT);		// 渲染
DWORD*	g_bufRender;					// 渲染的显存指针
DWORD*	g_bufScreen;					// 屏幕的显存指针

// 枚举用户的控制命令
enum CMD {
    CMD_QUIT = 1, CMD_UP = 2, CMD_DOWN = 4, CMD_LEFT = 8, CMD_RIGHT = 16, CMD_RESTART = 32 };



//
// 函数声明
//

// 初始化
void	Welcome();									// 绘制游戏界面
void	ReadyGo();									// 准备开始游戏
void	InitGame();									// 初始化游戏数据

// 矿井生成
void	MakeMaze(int width, int height);			// 初始化(注:宽高必须是奇数)
void	TravelMaze(int x, int y, BYTE** aryMap);	// 遍历 (x, y) 四周
void	DrawWall(int x, int y, bool left, bool top, bool right, bool bottom);
													// 画一面墙
// 绘制
void	Paint();									
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值