WPF介绍和简单的2D跳棋程序

WPF(Windows Presentation Foundation)是微软推出的基于Windows Vista的用户界面框架,属于.NET Framework 3.0的一部分。它提供了统一的编程模型、语言和框架,真正做到了分离界面设计人员与开发人员的工作;同时它提供了全新的多媒体交互用户图形界面。(来自百度百科)

在WPF的框架下,可以使用C#和xmal语言来设计界面。两种设计方法各自的好处,xmal语言是一种标记性语言,使用比较简单和灵活。C#下设计和一般的设计差别不大,但是要注意WPF下的类和接口等。具体的可以参考相关的教程。

关于WPF的入门,可以购买刘铁猛的《深入浅出WPF》,这是一本很好的书,这是他的博客:http://blog.csdn.net/fantasiax ,上面有很多很好的文章,值得一看。

既然WPF可以用来设计很好的界面,所以利用它来做一个简单的跳棋游戏。这里主要使用的C#来设计,下面是主要的程序。程序写的很好乱,没有按照一定的编码规则进行设计和类的设计很差,但是这个程序是我2天之内写出来的,大家可以看看。

源代码:

 

代码
   
     
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPF3
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Canvas mainPanel
= new Canvas();
const int North = 1 ;
const int NorthWest = 2 ;
const int SouthWest = 3 ;
const int South = 4 ;
const int SouthEast = 5 ;
const int NorthEast = 6 ;
const int TotalChess = 10 ; // the total chesss on the panel for one player
Point center;
double r;
const int APlayer = 1 ; int AEnterZoon = 0 ;
const int BPlayer = - 1 ; int BEnterZoon = 0 ;
Choise choise
= new Choise();
Brush Bs;
public MainWindow()
{
InitializeComponent();
this .Content = mainPanel;
DrawMailPanel();
center
= GetCenter();
r
= GetR();
DrawPanel();
}
/// <summary>
/// this function draw the outline of the mainpanel
/// </summary>
public void DrawMailPanel()
{
this .Width = 800 ;
this .Height = 600 ;
LinearGradientBrush myLinearGradientBrush
= new LinearGradientBrush();
myLinearGradientBrush.GradientStops.Add(
new GradientStop(Colors.Red, 0.0 ));
myLinearGradientBrush.GradientStops.Add(
new GradientStop(Colors.LimeGreen, 0.5 ));
myLinearGradientBrush.GradientStops.Add(
new GradientStop(Colors.Yellow, 1.0 ));
mainPanel.Background
= myLinearGradientBrush;
}

//
// draw the whole panel
//
public void DrawPanel()
{
choise.r
= r * 7 / ( 1.732 * 30 );
int flag = 0 ;
for ( int i = 0 ; i < 7 ; i ++ )
{
flag
= i + 1 ;
PointCollection PC
= GetPoints(r, flag);
DrawPoly(PC, flag);
}
List
< KeyValuePair < double , Point >> LKP = new List < KeyValuePair < double , Point >> ();
for ( int i = 0 ; i < 6 ; i ++ )
{
flag
= i + 1 ;
PointCollection newPC
= GetChessPoints(r * 14 / 15 , flag);
// used to ommit the same point
for ( int j = 0 ; j < newPC.Count; j ++ )
{
int FlagOfDraw = 0 ;
Point p
= newPC.ElementAt(j);
double key = (p.Y - center.Y) / (p.X - center.X);
KeyValuePair
< double ,Point > kp = new KeyValuePair < double ,Point > (key,p);
if (Math.Abs(key - 1.732 ) < 0.001 || Math.Abs(key + 1.732 ) < 0.001 || Math.Abs(key) < 0.001 )
{
for ( int k = 0 ;k < LKP.Count;k ++ )
{
if (Math.Abs(key - LKP.ElementAt(k).Key) < 0.001 )
{
if (clacNorm(p,LKP.ElementAt(k).Value) == 0 )
{
FlagOfDraw
= 1 ;
break ;
}
}
}
}
if ( 0 == FlagOfDraw)
{
LKP.Add(kp);
DrawPoint(p, flag, r
/ 30 );
}
}
}
DrawPoint(center, flag, r
/ 30 );
}

//
// get the center of the panel
//
public Point GetCenter()
{
Point center
= new Point();
center.X
= this .Width / 2 ; center.Y = this .Height / 2 ;
return center;
}

//
// get the radius
//
public double GetR()
{
return this .Height > this .Width ? this .Width * 2 / 5 : this .Height * 2 / 5 ;
}

//
// return a collection of points
//
public PointCollection GetPoints( double radius, int flag)
{
PointCollection PC
= new PointCollection();
double Offset1 = radius / 2 * Math.Tan( 30 * Math.PI / 180 );
double Offset2 = radius / 2 / Math.Cos( 30 * Math.PI / 180 );
// return a set of points which represent the three points in a triangle
switch (flag)
{
case North:
PC.Add(
new Point(center.X - Offset1, center.Y - radius / 2 ));
PC.Add(
new Point(center.X, center.Y - radius));
PC.Add(
new Point(center.X + Offset1, center.Y - radius / 2 ));
Bs
= Brushes.Yellow;
break ;
case NorthWest:
PC.Add(
new Point(center.X - Offset1, center.Y - radius / 2 ));
PC.Add(
new Point(center.X - Offset1 - Offset2, center.Y - radius / 2 ));
PC.Add(
new Point(center.X - Offset2, center.Y));
Bs
= Brushes.Green;
break ;
case SouthWest:
PC.Add(
new Point(center.X - Offset2, center.Y));
PC.Add(
new Point(center.X - Offset1 - Offset2, center.Y + radius / 2 ));
PC.Add(
new Point(center.X - Offset1, center.Y + radius / 2 ));
Bs
= Brushes.Orange;
break ;
case South:
PC.Add(
new Point(center.X - Offset1, center.Y + radius / 2 ));
PC.Add(
new Point(center.X, center.Y + radius));
PC.Add(
new Point(center.X + Offset1, center.Y + radius / 2 ));
Bs
= Brushes.Red;
break ;
case SouthEast:
PC.Add(
new Point(center.X + Offset2, center.Y));
PC.Add(
new Point(center.X + Offset1 + Offset2, center.Y + radius / 2 ));
PC.Add(
new Point(center.X + Offset1, center.Y + radius / 2 ));
Bs
= Brushes.Blue;
break ;
case NorthEast:
PC.Add(
new Point(center.X + Offset1, center.Y - radius / 2 ));
PC.Add(
new Point(center.X + Offset1 + Offset2, center.Y - radius / 2 ));
PC.Add(
new Point(center.X + Offset2, center.Y));
Bs
= Brushes.Purple;
break ;
default : // draw the center origon.
PC.Add( new Point(center.X - Offset1, center.Y - radius / 2 ));
PC.Add(
new Point(center.X - Offset2, center.Y));
PC.Add(
new Point(center.X - Offset1, center.Y + radius / 2 ));
PC.Add(
new Point(center.X + Offset1, center.Y + radius / 2 ));
PC.Add(
new Point(center.X + Offset2, center.Y));
PC.Add(
new Point(center.X + Offset1, center.Y - radius / 2 ));
Bs
= Brushes.LightYellow;
break ;
}
return PC;
}
//
// get tht position of the chess,the return result is only a set of points
//
public PointCollection GetChessPoints( double radius, int flag)
{
PointCollection PC
= GetPoints(radius, flag);
PointCollection NewPC
= new PointCollection();
Point[] MiddleP
= new Point[ 5 ];
PC.Add(center);
PC.Add(PC.ElementAt(
0 ));
for ( int i = 0 ; i < PC.Count - 1 ; i ++ )
{
Point[] p
= new Point[ 3 ];
GetMiddlePoint(PC.ElementAt(i),PC.ElementAt(i
+ 1 ),p);
MiddleP[i]
= p[ 1 ];
for ( int j = 0 ; j < p.Length; j ++ )
{
NewPC.Add(p[j]);
}
NewPC.Add(PC.ElementAt(i));
}
NewPC.RemoveAt(NewPC.Count
- 1 );
Point[] MiddlePP
= new Point[ 5 ];
MiddleP[
4 ] = MiddleP[ 0 ];
for ( int i = 0 ; i < 4 ; i ++ )
{
MiddlePP[i]
= new Point((MiddleP[i].X + MiddleP[i + 1 ].X) / 2 , (MiddleP[i].Y + MiddleP[i + 1 ].Y) / 2 );
NewPC.Add(MiddlePP[i]);
}
MiddlePP[
4 ] = MiddlePP[ 0 ];
for ( int i = 0 ; i < 4 ; i ++ )
{
NewPC.Add(
new Point((MiddlePP[i].X + MiddlePP[i + 1 ].X) / 2 , (MiddlePP[i].Y + MiddlePP[i + 1 ].Y) / 2 ));
}
NewPC.Add(
new Point((MiddlePP[ 0 ].X + MiddlePP[ 2 ].X) / 2 , (MiddlePP[ 0 ].Y + MiddlePP[ 2 ].Y) / 2 ));
return NewPC;
}
//
// get the innner point on a line.
//
public void GetMiddlePoint(Point p1, Point p2,Point[] p)
{
for ( int i = 0 ; i < p.Length; i ++ )
{
p[i]
= new Point(p1.X + (p2.X - p1.X) * (i + 1 ) / 4 , p1.Y + (p2.Y - p1.Y) * (i + 1 ) / 4 );
}
}

//
// draw a polygon in the panel.
//
public void DrawPoly(PointCollection PC, int flag)
{
if (flag > 7 || flag < 1 )
{
MessageBox.Show(
" Error: The input flag is error.Please change the falg! " );
return ;
}
Polygon DrawPolygon
= new Polygon();
DrawPolygon.Fill
= Bs;
DrawPolygon.Stroke
= Brushes.Black;
DrawPolygon.StrokeThickness
= 0.5 ;
DrawPolygon.Points
= PC;
// this is a drawing procedure.
mainPanel.Children.Add(DrawPolygon);
}
/// <summary>
/// draw a point using a cirsle(ellipse)
/// </summary>
/// <param name="PC"></param>
/// <param name="flag"></param>
public void DrawPoint(Point p, int flag, double EllipseR)
{
if (flag > 6 || flag < 1 )
{
MessageBox.Show(
" Error: The input flag is error.Please change the falg! " );
return ;
}
Ellipse ellipse
= new Ellipse();
ellipse.Stroke
= System.Windows.Media.Brushes.Black;
if (p.Y < center.Y - r / 2 || p.Y > center.Y + r / 2 )
{
if (flag == 1 && p.Y < center.Y - r / 2 ){ellipse.Fill = Brushes.Yellow;}
else if (flag == 4 && p.Y > center.Y + r / 2 ) { ellipse.Fill = Brushes.Red; }

}
else
{
ellipse.Fill
= System.Windows.Media.Brushes.Chocolate;
}
Canvas.SetTop(ellipse, p.Y
- EllipseR);
Canvas.SetLeft(ellipse, p.X
- EllipseR);
ellipse.Width
= 2 * EllipseR;
ellipse.Height
= 2 * EllipseR;
ellipse.MouseLeftButtonDown
+= new MouseButtonEventHandler(ellipse_MouseLeftButtonDown);
ellipse.MouseRightButtonDown
+= new MouseButtonEventHandler(ellipse_MouseRightButtonDown);
mainPanel.Children.Add(ellipse);
}


/// <summary>
/// when you press on one ellipse, will trigger this handler.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void ellipse_MouseLeftButtonDown( object sender, MouseButtonEventArgs e)
{
Ellipse ellipse
= sender as Ellipse;
if (choise.IsChoosing())
{
// you have pressed a ellipse,then your action reprensent that you are moving a chess
// so we need to determine the valitity of your action.
Point SelectP = new Point(Canvas.GetLeft(ellipse), Canvas.GetTop(ellipse));
Point OriginalP
= choise.GetChoise();
double ratio = clacNorm(SelectP,OriginalP);
// MessageBox.Show(ratio.ToString());
if (ellipse.Fill == Brushes.Chocolate)
{
UIElementCollection iter
= mainPanel.Children;
Ellipse OriginalEllipse
= new Ellipse();
Point OriginallEllipsePoint
= new Point();
for ( int i = 0 ; i < iter.Count; i ++ )
{
if (iter[i] is Ellipse)
{
OriginalEllipse
= iter[i] as Ellipse;
OriginallEllipsePoint
= new Point(Canvas.GetLeft(OriginalEllipse), Canvas.GetTop(OriginalEllipse));
if (clacNorm(OriginalP, OriginallEllipsePoint) < 0.001 )
{
break ;
}
}
}
if (Math.Abs(ratio - 1 ) < 0.001 )
{
// this is ok,have no chess on the it.
// MessageBox.Show(ratio.ToString());
OriginalEllipse.Fill = Brushes.Chocolate;
ellipse.Fill
= choise.GetBrush();
choise.SetChoosing(
false );
clacResult(SelectP.Y,OriginalP.Y);
choise.setFlagOfPlayer(
- choise.GetFlagOfPlayer());
}
else
{
int FLagOfMove = 0 ;
for ( int i = 0 ; i < iter.Count; i ++ )
{
if (iter[i] is Ellipse)
{
Ellipse MiddleEllipse
= iter[i] as Ellipse;
Point MiddleP
= new Point(Canvas.GetLeft(MiddleEllipse), Canvas.GetTop(MiddleEllipse));
double SM = Math.Abs(clacNorm(SelectP, MiddleP));
double OM = Math.Abs(clacNorm(OriginallEllipsePoint, MiddleP));
if (Math.Abs(OM + SM - ratio) < 0.001 && OM > 0.001 && SM > 0.001 )
{
// MessageBox.Show();
if (MiddleEllipse.Fill == Brushes.Chocolate)
{
FLagOfMove
= 0 ;
break ;
}
else
{
FLagOfMove
+= 1 ;
}
}
// MessageBox.Show(FLagOfMove.ToString());
}
}
// MessageBox.Show((FLagOfMove-ratio+1).ToString());
if (Math.Abs(FLagOfMove - ratio + 1 ) < 0.001 )
{
OriginalEllipse.Fill
= Brushes.Chocolate;
ellipse.Fill
= choise.GetBrush();
choise.SetChoosing(
false );
clacResult(SelectP.Y, OriginalP.Y);
choise.setFlagOfPlayer(
- choise.GetFlagOfPlayer());
}
}
}
}
else if ( ! choise.IsChoosing() && ellipse.Fill != Brushes.Chocolate)
{
// you don't choose any ellipse
if (choise.GetFlagOfPlayer() == APlayer)
{
if (ellipse.Fill != Brushes.Yellow)
{
MessageBox.Show(
" please wait,it is not your turn. " );
return ;
}
}
else
{
if (ellipse.Fill != Brushes.Red)
{
MessageBox.Show(
" please wait,it is not your turn. " );
return ;
}
}
choise.SetChoosing(
true );
choise.SetChoise(
new Point(Canvas.GetLeft(ellipse),Canvas.GetTop(ellipse)));
choise.setBrush(ellipse.Fill);
ellipse.Fill
= Brushes.DarkOrchid;
}
}

void ellipse_MouseRightButtonDown( object sender, MouseButtonEventArgs e)
{
Ellipse ellipse
= sender as Ellipse;
Point p
= new Point(Canvas.GetLeft(ellipse),Canvas.GetTop(ellipse));
// MessageBox.Show(clacNorm(choise.GetChoise(), p).ToString());
if (choise.IsChoosing() && clacNorm(choise.GetChoise(),p) == 0 && ellipse.Fill == Brushes.DarkOrchid)
{
// you have choose a ellipse,use this method to cancel this choice.
choise.SetChoosing( false );
ellipse.Fill
= choise.GetBrush();
}
}

public void clacResult( double NewY, double OldY)
{
if (choise.GetFlagOfPlayer() == APlayer && NewY > center.Y + r / 2 && OldY < center.Y + r / 2 )
{
AEnterZoon
++ ;
if (AEnterZoon == TotalChess)
{
MessageBox.Show(
" Game Over! " );
}
}
else if (choise.GetFlagOfPlayer() == BPlayer && NewY < center.Y - r / 2 && OldY > center.Y - r / 2 )
{
BEnterZoon
++ ;
if (BEnterZoon == TotalChess)
{
MessageBox.Show(
" Game Over! " );
}
}
}

public double clacNorm(Point p1,Point p2)
{
return Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y)) / choise.r;
}
}
public class Choise
{
private bool isChoosing;
private Point choise;
private Brush brush;
public double r;
int FlagOfplayer;
public Choise()
{
isChoosing
= false ;
FlagOfplayer
= 1 ;
}
public int GetFlagOfPlayer()
{
return FlagOfplayer;
}
public void setFlagOfPlayer( int flag)
{
if (FlagOfplayer != 1 && FlagOfplayer != - 1 )
{
MessageBox.Show(
" Error! " );
}
FlagOfplayer
= flag;
}
public void setBrush(Brush brush)
{
this .brush = brush;
}
public Brush GetBrush()
{
return brush;
}
public bool IsChoosing()
{
return isChoosing;
}
public void SetChoosing( bool choosing)
{
isChoosing
= choosing;
}
public Point GetChoise()
{
return choise;
}
public void SetChoise(Point p)
{
choise
= p;
}
}
}

 

如果要运行上面的程序,只需要建立一个新的WPF应用程序,名字时WPF3,然后把MainWindow.xaml.cs中的源程序直接用上面的程序替了就行。

 现在只有红黄两方是可以游戏的,也就是你只能动黄的和红的棋子,并且是黄的先行。用的左键选中一个棋子,如果去取消,使用右键在点一下。然后用左键点你要去的位置就OK了。

你可能感兴趣的:(WPF)