七巧板

最近在忙着做一个很小的七巧板,锻炼一下自己的mind吧,其实看似很小的项目都蕴含着很不一样的经历,这篇随笔主要记录我做这个小七巧板的过程,声明:我是C#新手,绝对的业余,因为本人现在主攻嵌入式,只是对开发语言和Embeded System一样很感兴趣,所以如果您感觉这践踏了这门语言,请见谅!

首先我要做的是单个板的绘制和移动

绘制图形算是比较简单的GDI,以本程序为例,只要了解几个点的坐标值,使用AddLines顺次连接相邻的坐标点,然后FillPath填充一下就行了。板的移动属于图形重绘部分,将原有图形的坐标位置切换到你要移动的位置,然后执行重绘操作就行了,但是前提是鼠标需要找到它要移动的图像,这是需要调用Region.IsVisible(Point)函数。

为了实现鼠标左键按下后开始移动,然后鼠标左键弹起后能够停止移动,代码中定义了两个bool类型变量move和mouseup,其中move用于判断图形什么时候可以移动,为true的条件是鼠标在你所绘制的图形内;mousemove为true的条件左键按下。显然只有move为true,mouseup为false的时候,图形才能在跟随你的鼠标移动。

接着做了板的旋转

板的旋转是通过点击鼠标右键触发的,因此只要判断鼠标右键的坐标是否在板的范围内,然后根据数学知识写出代码即可。首先找到旋转的支点,也就是图形边界矩形的中心代码中通过RectangleF rf = path1.GetBounds();来返回边界矩形(float型,包含(top,left)和(width,height)),然后根据x0 = rf.Left + rf.Width / 2; y0 = rf.Top + rf.Height / 2;找到中心点(x0,y0),接着在rotation函数中数显翻转。程序中也要对点是否在板的范围内进行判断。

接下来做了板的自动匹配

板的自动匹配就是当板接近正确位置时自动识别并正确放置。我所想到的方法是:构建一个比正确区域稍大的区域,判断板的三个或者四个顶点是否全部落到这个区域内,假如全部落到的话,将正确位置的顶点坐标传给全局的pt变量,接着只要重绘一下就行了!当时也想到另一个差不多的,就是以正确位置的顶点为圆心,创建3个小矩形区域,判断3个顶点是否能够落到各个顶点的区域,但是这种方法正确率不如前者,而且还要用object数组或者Rectangle数组,不划算!

 

ContractedBlock.gif ExpandedBlockStart.gif 板的绘制,移动,旋转
 
   
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
Point[] pt;
int puint = 70 ;
Point ptmouse;
bool move = false ;
bool mouseup = false ;
bool rot = false ;
double x0, y0;
public Form1()
{
InitializeComponent();
pt
= new Point[] { new Point( 64 , 23 ), new Point( 64 , 4 * puint + 23 ), new Point( 64 + 2 * puint, 23 + puint * 2 ) };
}

public bool ptinchip(Point pt0,Point[] pts)
{
GraphicsPath path
= new GraphicsPath();
path.AddLines(pts);
Region rg
= new Region(path);
return rg.IsVisible(pt0);
}

public void rotation()
{
double dx,dy;
for ( int i = 0 ; i < pt.Length; i ++ )
{
dx
= pt[i].X - x0;
dy
= pt[i].Y - y0;
pt[i].X
= ( int )(x0 + dx * 0.7071 - dy * 0.7071 );
pt[i].Y
= ( int )(y0 + dx * 0.7071 + dy * 0.7071 );
Invalidate(
false );
}
}

private void Form1_Paint( object sender, PaintEventArgs e)
{

Graphics gp
= e.Graphics;
GraphicsPath path1
= new GraphicsPath();
path1.AddLines(pt);
gp.FillPath(Brushes.Red, path1);
RectangleF rf
= path1.GetBounds();
x0
= rf.Left + rf.Width / 2 ;
y0
= rf.Top + rf.Height / 2 ;
}

private void Form1_MouseDown( object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
mouseup
= false ;
ptmouse
= new Point(e.X, e.Y);
if (ptinchip(ptmouse, pt))
{
move
= true ;
}
else
move
= false ;
}
else if (e.Button == MouseButtons.Right)
{
ptmouse
= new Point(e.X, e.Y);
if (ptinchip(ptmouse, pt))
{
rot
= true ;
}
else
rot
= false ;
}
}

private void Form1_MouseMove( object sender, MouseEventArgs e)
{
Point pt0
= new Point(e.X, e.Y);
if (ptinchip(pt0, pt))
{
this .Cursor = Cursors.Hand;
}
else
this .Cursor = Cursors.Arrow;
if (move &&! mouseup)
{
Point offpt
= new Point(pt0.X - ptmouse.X, pt0.Y - ptmouse.Y);
for ( int i = 0 ; i < pt.Length; i ++ )
{
pt[i].Offset(offpt);
}
Invalidate(
false );
}
}

private void Form1_MouseUp( object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
mouseup
= true ;
}
else if (e.Button == MouseButtons.Right && rot)
{
rotation();
}
}
}
}

 

转载于:https://www.cnblogs.com/doucontorl/archive/2010/07/24/qiqiaoban.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值