说到五子棋,想必大家都会很熟悉,谁先连成五颗谁就胜利。
今天我想说一下游戏编程思想概述,游戏并不是你所看见的GDI绘图中看到的那些,那只能算游戏中的一些元素,一个游戏除了表面视图,还有它实质的东西--内核(游戏算法)。
那么游戏的核心是怎么和图形链接起来的呢?用户的操作信息在核心中进行,再把响应后的游戏数据反馈给游戏界面,这就是一个完整的游戏。在游戏中游戏的内核是一直在变化的,知识有的时候并没有反馈在界面而已。
本游戏的制作分为两大部分,游戏界面和游戏核心。游戏的设计可以先设计界面再设计核心,或者先设计核心 在设计界面,这两种方法各有千秋。先设计界面感觉更加直观,更加容易理解。先设计核心不容易乱和丢失功能。
本文是先设计界面再设计核心。
对于框架的建立也就是界面,最好要了解五子棋的规格大小,国际棋牌是15X15。
由于写的充忙,所以界面略显粗糙,后面可以根据自己的需要更改。
首先是建立一个winform窗体(本棋盘没使用其他控件)
在 private void Form1_Paint(object sender, PaintEventArgs e)事件中利用GDI绘图画出一个棋盘(也可根据自己需要找个棋盘图填充进去,本文不详讲)
棋盘代码再看棋盘代码前,不知道各位了解显示器上的坐标系不,windows上的坐标系基于设备坐标,屏幕上的点通过X,Y坐标描述。X坐标从你当前窗口的左上角从左到右递增,Y坐标从上往下递增。这样能使你更好的理解上诉代码,棋盘的构造。
棋盘棋盘构造成功出来了,我们又该构造什么了?可能屏幕前的你脱口而出--棋子。
对,就是棋子。构造棋子的话是不是应该是先画出一个圆,然后在将圆形填充。
首先构造一直笔Pen pens = new Pen(Color.Black, 2);表示黑子;然后在构造一个填充刷 Brush b = new LinearGradientBrush(new Point(0, 10), new Point(10, 10), Color.Black, Color.Black);填充刷的颜色与笔颜色一样。然后构造该棋子所在的位置和大小Rectangle r = new Rectangle(newX, newY, 10, 10);最后构造一个GDI绘图对象 Graphics gra = this.CreateGraphics(); 先画出一个圆gra.DrawEllipse(pens, r);在填充该圆gra.FillEllipse(b, r);
棋子代码此时界面已经构造完成。
下面就是游戏的内核,
首先定义两个存储棋子的数组
img这些你应该考虑为什么会定义一个int型二维数组,我所点击的坐标不是随机嘛,不是double型么,为什么?首先当你下棋时,屏幕获取到你的点击位置Location,此时你应该考虑的是怎么样让棋子落子格子的正中间而不是指哪里就那里,怎么智能识别棋子想要落的位置,在我这里就是这样写的
落子代码这样就获取到了棋子想要落取的位置,然后判断该落子情况,在这落子的地方是不是已经落子了,没落子该怎么储存,我写了一个判断落子情况函数MyChess
img首先获取到落子的坐标然后通过除以棋盘间隔获取到落子的位置,首先该数组全部为0,如果落子成功就变成1表示该位置有落子,然后通过该数组来判断输赢情况。
现在落子情况已经有了,就该判断下棋过程输赢情况了,五子棋连成线无非四种情况,横,竖,斜,反斜四种情况。只要满足其中一种情况就获胜。
img判断横线输赢
img竖线输赢
img斜线情况是利用利用数学公式 y=kx+b来判断的
img反斜线情况
img此时游戏核心已经完成。
下面就是一些效果图
img img源码:
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 wuziqi
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 用来标识鼠标点击事件是否可用
/// </summary>
bool bTemp = false;
/// <summary>
/// 棋盘长度
/// </summary>
int nLength = 290;
/// <summary>
/// 棋盘间隔
/// </summary>
int nJg = 20;
/// <summary>
/// 当前是黑方还是白方下棋
/// </summary>
bool bUser = true;
/// <summary>
/// 黑方二维数组
/// </summary>
int[,] myBlack = new int[15, 15];
/// <summary>
/// 白方二维数组
/// </summary>
int[,] myWhite = new int[15, 15];
/// <summary>
/// 棋盘规格
/// </summary>
int nSize = 15;
/// <summary>
/// 游戏加载界面
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
{
labelControl1.Text = "游戏未开始";
simpleButton3.Enabled = false;
}
/// <summary>
/// 棋盘
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.AliceBlue);//背景色;
Pen pen = new Pen(Color.Red, 2);//笔的颜色与粗细
for (int i = 30; i <= 310; i = i + 20)//步长20
{
Point point = new Point(i, 30);
Point point1 = new Point(i, 310);
e.Graphics.DrawLine(pen, point, point1);//画竖线
Point point2 = new Point(30, i);
Point point3 = new Point(310, i);
e.Graphics.DrawLine(pen, point2, point3);//画横线
}
}
/// <summary>
/// 游戏开始按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void simpleButton2_Click(object sender, EventArgs e)
{
labelControl1.Text = "游戏开始,黑方下棋";
bTemp = true;
simpleButton2.Enabled = false;
simpleButton3.Enabled = true;
}
/// <summary>
/// 鼠标点击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
int n = nLength / nJg + 1;
if(bTemp)
{
if (bUser)//因为后面是落子情况所以只能把该谁下写在这里
{
labelControl1.Text = "游戏开始,白方下棋";
}
else
{
labelControl1.Text = "游戏开始,黑方下棋";
}
if (e.Button == MouseButtons.Left)
{
Point p = e.Location;
int X = p.X;
int Y = p.Y;
int newX = (int)((X + nJg / 2) / nJg) * nJg - 10 / 2 - 10;
int newY = (int)((Y + nJg / 2) / nJg) * nJg - 10 / 2 - 10;
bool bMyChess = MyChess(newX, newY);
if (!bMyChess)
{
return;
}
if(bUser)
{
Pen pens = new Pen(Color.Black, 2);
Brush b = new LinearGradientBrush(new Point(0, 10), new Point(10, 10), Color.Black, Color.Black);
Rectangle r = new Rectangle(newX, newY, 10, 10);//标识圆的大小(x坐标,y坐标,大小)
Graphics gra = this.CreateGraphics();
gra.DrawEllipse(pens, r);
gra.FillEllipse(b, r);
gra.Dispose();
bool bPing = MyPin();//判断是否平局
if(bPing)
{
labelControl1.Text = "平局,请点击重开";
MessageBox.Show("平局");
bTemp = false;
return;
}
bool bWin = MyWin();//判断输赢;
if (bWin)
{
labelControl1.Text = "黑方赢,请点击重开";
MessageBox.Show("黑方赢");
bTemp = false;
return;
}
bUser = false;
}
else
{
Pen pens = new Pen(Color.White, 2);
Brush b = new LinearGradientBrush(new Point(0, 10), new Point(10, 10), Color.White, Color.White);
Rectangle r = new Rectangle(newX, newY, 10, 10);//标识圆的大小(x坐标,y坐标,大小)
Graphics gra = this.CreateGraphics();
gra.DrawEllipse(pens, r);
gra.FillEllipse(b, r);
gra.Dispose();
bool bPing = MyPin();//判断是否平局
bool bWin = MyWin();//判断输赢;
if (bPing)
{
labelControl1.Text = "平局,请点击重开";
MessageBox.Show("平局");
bTemp = false;
return;
}
if (bWin)
{
labelControl1.Text = "白方赢,请点击重开";
MessageBox.Show("白方赢");
bTemp = false;
return;
}
bUser = true;
}
}
}
}
/// <summary>
/// 平局情况,一般不会出现,还是写下表示尊敬
/// </summary>
/// <returns></returns>
public bool MyPin()
{
int nTemp=0;
for (int i = 0; i < nSize; i++)
{
for (int j = 0; j < nSize; j++)
{
if (myBlack[i, j] == 1 || myWhite[i, j] == 1)
{
nTemp++;
}
}
}
if(nTemp==225)
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 判断落子情况
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public bool MyChess(int x,int y)
{
int m;
int n;
m=x/nJg-1;
n = y / nJg-1;
if (m >= nSize || n >= nSize || m < 0 || n < 0)//超出数组索引
{
return false;
}
if (myBlack[m, n] == 0 && myWhite[m, n] == 0)
{
if(bUser)
{
myBlack[m, n] = 1;
}
else
{
myWhite[m, n] = 1;
}
}
else
{
return false;
}
return true;
}
/// <summary>
/// 输赢情况
/// </summary>
/// <returns></returns>
public bool MyWin()
{
bool bMyHorizontal = MyHorizontal();//横线
bool bMyVerTical = MyVerTical();//竖线
bool bMyOblique = MyOblique();//斜线
bool bMyBackslash = MyBackslash();//反斜线
if(bMyHorizontal||bMyVerTical||bMyOblique||bMyBackslash)
{
return true;
}
return false;
}
/// <summary>
/// 横排情况
/// </summary>
public bool MyHorizontal()
{
for(int i=0;i<nSize-4;i++)
{
for (int j = 0; j < nSize;j++ )
{
if (bUser)
{
if(myBlack[i,j]==1&&myBlack[i+1,j]==1&&myBlack[i+2,j]==1&&myBlack[i+3,j]==1&&myBlack[i+4,j]==1)
{
return true;
}
}
else
{
if (myWhite[i, j] == 1 && myWhite[i + 1, j] == 1 && myWhite[i + 2, j] == 1 && myWhite[i + 3, j] == 1 && myWhite[i + 4, j] == 1)
{
return true;
}
}
}
}
return false;
}
/// <summary>
/// 竖排情况
/// </summary>
public bool MyVerTical()
{
for (int i = 0; i < nSize ; i++)
{
for (int j = 0; j < nSize-4; j++)
{
if (bUser)
{
if (myBlack[i, j] == 1 && myBlack[i , j+1] == 1 && myBlack[i , j+2] == 1 && myBlack[i, j+3] == 1 && myBlack[i, j+4] == 1)
{
return true;
}
}
else
{
if (myWhite[i, j] == 1 && myWhite[i, j + 1] == 1 && myWhite[i, j + 2] == 1 && myWhite[i, j + 3] == 1 && myWhite[i, j + 4] == 1)
{
return true;
}
}
}
}
return false;
}
/// <summary>
/// 斜线情况 利用数学公式 y=kx+b
/// </summary>
public bool MyOblique()
{
for (int i = 0; i < nSize - 4; i++)
{
for (int j = 0; j < nSize-4; j++)
{
if (bUser)
{
if (myBlack[i, j] == 1 && myBlack[i + 1, j+1] == 1 && myBlack[i + 2, j+2] == 1 && myBlack[i + 3, j+3] == 1 && myBlack[i + 4, j+4] == 1)
{
return true;
}
}
else
{
if (myWhite[i, j] == 1 && myWhite[i + 1, j+1] == 1 && myWhite[i + 2, j+2] == 1 && myWhite[i + 3, j+3] == 1 && myWhite[i + 4, j+4] == 1)
{
return true;
}
}
}
}
return false;
}
/// <summary>
/// 反斜线情况
/// </summary>
public bool MyBackslash()
{
for (int i = nSize-1; i >= 4; i--)
{
for (int j = 0; j < nSize-4; j++)
{
if (bUser)
{
//j-(i-1)
if (myBlack[i, j ] == 1 && myBlack[i - 1, j + 1] == 1 && myBlack[i -2, j + 2] == 1 && myBlack[i- 3, j + 3] == 1 && myBlack[i - 4, j + 4] == 1)
{
return true;
}
}
else
{
if (myWhite[i, j] == 1 && myWhite[i - 1, j + 1] == 1 && myWhite[i - 2, j + 2] == 1 && myWhite[i - 3, j + 3] == 1 && myWhite[ i - 4, j + 4] == 1)
{
return true;
}
}
}
}
return false;
}
/// <summary>
/// 重开游戏
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void simpleButton3_Click(object sender, EventArgs e)
{
this.Refresh();
Graphics gra = this.CreateGraphics();
gra.Clear(Color.AliceBlue);
Pen pen = new Pen(Color.Red, 2);
for (int i = 30; i <= 310; i = i + 20)//步长20
{
Point point = new Point(i, 30);
Point point1 = new Point(i, 310);
gra.DrawLine(pen, point, point1);//画竖线
Point point2 = new Point(30, i);
Point point3 = new Point(310, i);
gra.DrawLine(pen, point2, point3);//画横线
}
}
}
}
网友评论