首先呢,想编写这个程序的同学一定是要下过象棋的(国际的,中国的都可以),就算没下过,也应该看别人下过吧。 好吧..你也没见别人下过,那你至少应该知道象棋长什么样子吧...
首先选择自己的武器,如果你觉得自己够牛的话,那我建议你选择C语言,编译环境为turboC. 然后拥有超强的记忆力记下一大堆的API函数..然后开始动工.. 最后在花上远远多过编写代码所用时间的时间来调试自己的程序(你也就不用再看这篇日志了)
或者说,你觉得自己一般牛B,选择MFC来编写这个程序,虽然说武器是先进了一些,但是依然无法从根本上解决API函数的复杂性。
如果你想用VB6来编写类似于这样的一个Windows程序,可以是可以。但是你永远无法学习到OOP的真正价值所在。VB6不允许程序员在类与类之间建立“is a”的关系. 对于象棋这样的小型程序尚罢..
废话不说了.. 这次的例子我选择了基于.net framew 2.0以上的平台,C#语言来编写这样一个程序。 现在开始动工吧!
首先,你应该明确这是一个Windows Form程序, 而不是一个Console程序..(这一点应该都清楚吧) 所以在这个程序中会使用许多的资源,例如棋盘,棋子图形等等..所以第一步,你需要打开你的Photoshop, 开始绘制这些图片。
棋子的图片如下:
棋盘图片如下:
大家可以根据自己的不同爱好来制作自己的图片,本人一向没有什么审美能力,所以能有这样的图片已经是很尽力了..
准备工作做完后,现在开始编码:
首先打开VS2008 ,新建一个Windows Form Project, 在Projrect中添加第一个类ChessPiece。IDE会自动帮你生成一个ChessPiece.cs文件 和一个Form1.cs文件
现在删除IDE自动在ChessPiece.cs这个文件中的代码,开始自己编写代码:
using System;
using System.Drawing;
// 创建一个棋子类
class ChessPiece
{
public enum Types //这是一个枚举类新,表示所有的棋子种类
{
KING,//国王
QUEEN,//王后
BISHOP,//象
KNIGHT,//马
ROOK,//车
PAWN//卒
}
private int currentType; // 当前类型,用于后台控制当前应该绘制的图像
private Bitmap pieceImage; // 用来储存当前图像当前图像
// 初始化一个矩形区域,这个矩形区域就是以后棋盘的边缘,用于放置整个棋盘和棋盘上的棋子
private Rectangle targetRectangle =
new Rectangle( 0, 0, 75, 75 );
// 构造函数
public ChessPiece( int type, int xLocation,
int yLocation, Bitmap sourceImage )
{
currentType = type; // 设置棋子类型
targetRectangle.X = xLocation; // 设置X坐标
targetRectangle.Y = yLocation; // 设置Y坐标
// 将棋子的子图从大图资源中切割下来
pieceImage = sourceImage.Clone(
new Rectangle( type * 75, 0, 75, 75 ),
System.Drawing.Imaging.PixelFormat.DontCare );
}
// 绘制棋子
public void Draw( Graphics graphicsObject )
{
graphicsObject.DrawImage( pieceImage, targetRectangle );
}
// 获得当前棋子坐标
public Rectangle GetBounds()
{
return targetRectangle;
}
// 设置当前棋子坐标
public void SetLocation( int xLocation, int yLocation )
{
targetRectangle.X = xLocation;
targetRectangle.Y = yLocation;
}
}
好了,这个棋子类已经写完。那应该如何让这些“死”代码活灵活现的呈现在大家面前呢?
我们还需要一个前台呈现类,也就是我们常说的UI类,或者叫Interface。
现在,将刚才在PS中绘制好的图片放置在bin/Release/images目录下
将之前IDE自动生成的Form1.cs改名为ChessGame.cs (不改也可以)
删除IDE自动生成的代码,然后自己编码:
// ChessGame.cs
//该文件实现棋盘和棋子的初始化,部署,和在窗口和面板上的绘制,移动,刷新等工作
using System;
using System.Collections;
using System.Drawing;
using System.Windows.Forms;
public partial class ChessGame : Form
{
private ArrayList chessTile = new ArrayList(); // 创建一个动态数组储存棋盘的图片
private ArrayList chessPieces = new ArrayList(); // 创建一个动态数组储存棋子的图片
private int selectedIndex = -1; // 所选图片的索引
private int[ , ] board = new int[ 8, 8 ]; // 将棋盘用一个 8 * 8 的数组来表示
private const int TILESIZE = 75; // 将每个图片快定义为 75 像素
// 初始化构造函数
public ChessGame()
{
// 对主窗口进行生成
InitializeComponent();
}
// 将棋盘的4种图片快存入动态数组chessTile中并对棋子进行部署
private void ChessGame_Load( object sender, EventArgs e )
{
chessTile.Add( Bitmap.FromFile( @"images\lightTile1.png" ) );
chessTile.Add( Bitmap.FromFile( @"images\lightTile2.png" ) );
chessTile.Add( Bitmap.FromFile( @"images\darkTile1.png" ) );
chessTile.Add( Bitmap.FromFile( @"images\darkTile2.png" ) );
ResetBoard(); //对棋盘上棋子进行部署
Invalidate(); // 刷新主窗口
}
// 具体实现对棋盘的部署
private void ResetBoard()
{
int current = -1;
ChessPiece piece;
Random random = new Random();
bool light = false;
int type;
chessPieces.Clear(); // 确保此时棋子的动态数组为空
// 将白方棋子大图放入临时变量whitePieces中
Bitmap whitePieces =
( Bitmap ) Image.FromFile( @"images\whitePieces.png" );
// 将黑方棋子大图放入临时变量blackPieces中
Bitmap blackPieces =
( Bitmap ) Image.FromFile( @"images\blackPieces.png" );
// 从上到下先部署白色棋子
Bitmap selected = whitePieces;
// 遍历棋盘的行
for ( int row = 0; row <= board.GetUpperBound( 0 ); row++ )
{
// 当到达第 6 行时开始部署黑色棋子
if ( row > 5 )
selected = blackPieces;
// 第二层遍历 遍历棋盘的列
for ( int column = 0;
column <= board.GetUpperBound( 1 ); column++ )
{
// 部署第一行和最后一行上的棋子
if ( row == 0 || row == 7 )
{
switch ( column )
{
case 0:
case 7: // 部署车
current = ( int ) ChessPiece.Types.ROOK;
break;
case 1:
case 6: // 部署马
current = ( int ) ChessPiece.Types.KNIGHT;
break;
case 2:
case 5: // 部署象
current = ( int ) ChessPiece.Types.BISHOP;
break;
case 3: // 部署国王
current = ( int ) ChessPiece.Types.KING;
break;
case 4: // 部署王后
current = ( int ) ChessPiece.Types.QUEEN;
break;
}
// 确定当前棋子的信息
piece = new ChessPiece( current,
column * TILESIZE, row * TILESIZE, selected );
chessPieces.Add( piece ); // 将子图存入动态数组中
} // end if
// 当遍历到第二行和倒数第二行
if ( row == 1 || row == 6 )
{
piece = new ChessPiece(
( int ) ChessPiece.Types.PAWN,
column * TILESIZE, row * TILESIZE, selected );
chessPieces.Add( piece ); // 将卒的子图存入动态数组
}
type = random.Next( 0, 2 ); // 随即决定棋盘的格式
if ( light ) // 设置亮棋盘
{
board[ row, column ] = type;
light = false;
}
else // 设置暗棋盘
{
board[ row, column ] = type + 2;
light = true;
}
}
light = !light; // 让亮色和暗色棋盘交替出现
}
}
// 在主窗口中绘制棋盘
private void ChessGame_Paint( object sender, PaintEventArgs e )
{
Graphics graphicsObject = e.Graphics; // 实例化一个图形对象
graphicsObject.TranslateTransform( 0, 28 ); // 将棋盘整体下沿一定的距离,防止菜单栏挡住棋盘
for ( int row = 0; row <= board.GetUpperBound( 0 ); row++ )
{
for ( int column = 0;
column <= board.GetUpperBound( 1 ); column++)
{
// 绘制棋盘
graphicsObject.DrawImage(
( Image ) chessTile[ board[ row, column ] ],
new Point( TILESIZE * column, ( TILESIZE * row ) ) );
}
}
}
// 绘制棋盘上的棋子
private void pieceBox_Paint(
object sender, System.Windows.Forms.PaintEventArgs e )
{
// 便利整个动态数组
for ( int i = 0; i < chessPieces.Count; i++ )
GetPiece( i ).Draw( e.Graphics );
}
//检测鼠标点击区域是否有棋子
private int CheckBounds( Point point, int exclude )
{
Rectangle rectangle; // current bounding rectangle
for ( int i = 0; i < chessPieces.Count; i++ )
{
// 获得鼠标区域坐标信息
rectangle = GetPiece( i ).GetBounds();
if ( rectangle.Contains( point ) && i != exclude )
return i;
}
return -1;
}
// 鼠标点击左键产生事件
private void pieceBox_MouseDown(
object sender, System.Windows.Forms.MouseEventArgs e )
{
// 获得点击棋子的索引号
selectedIndex = CheckBounds( new Point( e.X, e.Y ), -1 );
}
// 如果选中棋子,移动产生事件
private void pieceBox_MouseMove(
object sender, System.Windows.Forms.MouseEventArgs e )
{
if ( selectedIndex > -1 )
{
Rectangle region = new Rectangle(
e.X - TILESIZE * 2, e.Y - TILESIZE * 2,
TILESIZE * 4, TILESIZE * 4 );
// 将图片中心设置为鼠标所在区域
GetPiece( selectedIndex ).SetLocation(
e.X - TILESIZE / 2, e.Y - TILESIZE / 2 );
pieceBox.Invalidate( region ); // 局部刷新棋子移动后的棋盘
}
}
// 将棋子放下时产生的事件
private void pieceBox_MouseUp( object sender, MouseEventArgs e )
{
int remove = -1;
// 如果棋子被选中
if ( selectedIndex > -1 )
{
Point current = new Point( e.X, e.Y );
//调整棋子放下时的位置
Point newPoint = new Point(
current.X - ( current.X % TILESIZE ),
current.Y - ( current.Y % TILESIZE ) );
// 检查该位置是否具有其他棋子
remove = CheckBounds( current, selectedIndex );
// 将新棋子放在新位置上
GetPiece( selectedIndex ).SetLocation( newPoint.X, newPoint.Y );
selectedIndex = -1; // 将棋子索引还原为-1,为下一次移动做准备
//如果有棋子,将其移除并换上新棋子
if ( remove > -1 )
chessPieces.RemoveAt( remove );
}
pieceBox.Invalidate(); // 刷新棋盘
}
//获得棋子
private ChessPiece GetPiece( int i )
{
return ( ChessPiece ) chessPieces[ i ];
}
//点击New Game重新开始游戏
private void newGameItem_Click(
object sender, System.EventArgs e )
{
ResetBoard(); // 重新部署棋盘
Invalidate(); // 刷新主窗口
}
}
ok!大功告成了~运行结果看看吧:
如果有兴趣,你还可以为自己的象棋添加AI,让电脑自动下棋。 不过这就不属于这个例子的范围之类了。
总之,对于那些刚刚从控制台程序转向Windwos程序的同学来说,初次这个程序可能稍微
有些困难,不过只要你能硬着头皮看下去,认真对待每一行代码,相信对你的编程能力会有提高的。
分享到:
相关推荐
手把手教你单片机程序框架---吴坚鸿doc,手把手教你单片机程序框架---吴坚鸿
注意:本书因上传大小限制被压缩成2个部分,要都下载才能解压缩,请点我的用户名进我的资源来下载完整的2部分。 以实践为主线,以生动短小的实例为灵魂,穿插介绍C语言的语法及其针对单片机的特别定义,使理论与...
第2章 学习AVR单片机C程序设计所用的软件及实验器材介绍 2.1 IAR Enlbedded Workbench IDE C语言编译器 2.2 AVR Studio集成开发环境 2.3 PonyProg2000下载软件及SL—ISP下载软件 2.4 AVR DEM0单片机综合实验板 ...
手把手教你学AVR单片机C程序设计实验程序 手把手教你学AVR单片机C程序设计实验程序
123手把手教你学单片机的C语言程序设计
手把手教你单片机程序框架 手把手教你单片机程序框架 手把手教你单片机程序框架
这本电子书资料整理的是吴老师另一个连载贴——从业将近十年!手把手教你单片机程序框架。这篇帖子连 载了近两年,一共有 90 个章节,着实耗费了吴老师很多心血。这里同样是为了方便大家观看帖子内容而做的资 料整理...
《手把手教你学单片机的C程序设计》实验程序 光盘资料
自己买的开发板的配套教程就是《手把手教你学单片机的C程序设计》这本书,现在把所有程序送上。所有源码均在开发板上跑过,完全没有问题。
手把手教你用C#制作RPG游戏__罗培羽著是一本很好的国内开发RPG游戏的书籍,可以教会读者如何学会C#做游戏,而Unity3D网络游戏实战游戏开发与设计技术丛书 是在C#基础上,利用Unity引擎开发网络实战游戏,这两本书...
手把手教你汉化程序动画教程,只有动画演示教程。
非常详细的单片机程序框架教程,对学单片机学习者非常有用的教程!
手把手教你学DSP:基于TMS320F28335 手把手教你学DSP:基于TMS320F28335 手把手教你学DSP:基于TMS320F28335 手把手教你学DSP:基于TMS320F28335 手把手教你学DSP:基于TMS320F28335 手把手教你学DSP:基于TMS320F...
手把手教你学2812,很全面的一本书。电子版,适合初学者学习,
手把手教你学单片机程序框架
手把手教你学AVR单片机C程序设计附件
手把手教你写au3程序 和 从批处理(bat)转到Au3教程 网吧;宾馆系统;POS机; 网众、锐起、易游、深度、VND、方格子、网络维护、服务器、软路由等
手把手教你设计FIR数字滤波器最新版-手把手教你设计FIR数字滤波器.docx 本帖最后由 leo_silverbulle 于 2015-4-22 09:38 编辑 上次发的帖忘了上传附件,楼主的锅,这是我这段时间设计FIR滤波器的过程中自己...