最近在忙着做一个很小的七巧板,锻炼一下自己的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数组,不划算!

 

python绘制七巧板 七巧板的编程_数组

python绘制七巧板 七巧板的编程_System_02

板的绘制,移动,旋转

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();
            }
        }
    }
}