Unity3d制作一个简单粗暴的五子棋项目工程源码
Unity3d制作一个简单粗暴的五子棋
最终效果
效果是这样的gif动图展示
项目源码
先把源码贴这
https://download.csdn.net/download/qq_33789001/15743651
绘制棋盘
绘制构思
先定一个白色背景,然后盘由黑色的线绘制,
15*15的棋盘 就需要15条横着的线,和15条竖着的线构成。
预制两条横竖的线,那么这两条线的两边分别画7条线。
一个7次的for循环就搞定了。
还有五个点,这个就预制好改一下位置就完成。
绘制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class QiPanCreateor : MonoBehaviour
{
public GameObject LineMH,LineMV;
public GameObject Pnt1, Pnt2, Pnt3, Pnt4;
float width = 40;
void Start()
{
CreatorQiPan();
}
void CreatorQiPan() {
Pnt1.transform.localPosition = new Vector3(-width * 4, -width * 4, 0);
Pnt2.transform.localPosition = new Vector3(width * 4, -width * 4, 0);
Pnt3.transform.localPosition = new Vector3(-width * 4, width * 4, 0);
Pnt4.transform.localPosition = new Vector3(width * 4, width * 4, 0);
for (int i = 0; i < 7; i++)
{
GameObject H1 = GameObject.Instantiate<GameObject>(LineMH);
GameObject H2 = GameObject.Instantiate<GameObject>(LineMH);
GameObject V1 = GameObject.Instantiate<GameObject>(LineMV);
GameObject V2 = GameObject.Instantiate<GameObject>(LineMV);
H1.transform.SetParent(this.transform);
H1.transform.localScale = Vector3.one;
H1.transform.localPosition = new Vector3(0, width * (i + 1), 0);
H2.transform.SetParent(this.transform);
H2.transform.localScale = Vector3.one;
H2.transform.localPosition = new Vector3(0, -width * (i + 1), 0);
V1.transform.SetParent(this.transform);
V1.transform.localScale = Vector3.one;
V1.transform.localPosition = new Vector3(width * (i + 1), 0, 0);
V2.transform.SetParent(this.transform);
V2.transform.localScale = Vector3.one;
V2.transform.localPosition = new Vector3(-width * (i + 1), 0, 0);
}
}
}
效果图
绘制的效果如下图:
今天就花这小点时间弄个棋盘,后续慢慢写!
放置棋子
功能和效果
功能
主要是实现一下这些功能:按下鼠标并移动,新棋子会跟随移动;松开鼠标,放置棋子;自动修正放置的位置在格子交叉处;不可在棋盘外和已放置的位置放置;黑白棋子交替放置。
效果
制作棋子
先预制两个棋子对象,用默认的Image组件,图片设置为内置的“Knob”。
定义类和类型
棋子类型
//定义棋子类型
public enum QiType {
none = 0,
white = 1, //白
black = 2, //黑
}
这个就是简单明了,两种类型的棋子,黑白。
棋盘格类
这个类主要用于记录每个格子内的信息,便于后面进行格子相关的逻辑判断。
// 盘格类
public class QPGrid {
public bool isPlace = false; //是否放置
public QiType QiTp = QiType.none; //类型
public Vector3 Pos; //位置
public GameObject Node = null; //对象节点
}
实现功能
初始棋盘格数据
void InitQiPanArray() {
for (int i = 0; i < 15; i++)
for (int j = 0; j < 15; j++) {
QPGrid temp = new QPGrid();
temp.Pos = new Vector3((i - 7) * width, (7 - j) * width, 0); //只用计算位置,其他默认
QiPanArray[i, j] = temp;
}
}
共有15*15个格子,我们对每个进行初始化,并赋值位置数据;位置数据通过格子大小计算出,用于放棋子位置修正。
创建棋子
//创建下一棋子
void CreateNextQi() {
if (NextQiType == QiType.white)
{
GameObject go = GameObject.Instantiate<GameObject>(WhiteQi);
go.transform.SetParent(WhiteQi.transform.parent);
go.transform.localPosition = Vector3.zero;
go.transform.localScale = Vector3.zero;
NowQi = go;
}
else if (NextQiType == QiType.black)
{
GameObject go = GameObject.Instantiate<GameObject>(BlackQi);
go.transform.SetParent(BlackQi.transform.parent);
go.transform.localPosition = Vector3.zero;
go.transform.localScale = Vector3.zero;
NowQi = go;
}
}
这个是通过复制之前预制的黑白棋对象实现,根据接下来的棋子类型来复制。
实时同步棋子位置
//同步当前棋子位置
void SyncNowQiPos(float x,float y) {
if (NowQi == null)
{
CreateNextQi();
}
else
{
NowQi.transform.localScale = Vector3.one;
NowQi.transform.localPosition = new Vector3(x, y, 0);
}
}
当鼠标按下并移动时,根据鼠标位置更新棋子的位置。
放置棋子
//尝试放置当前棋子
void TryPlaceNowQi(float x, float y) {
if ((x < 7.5f * width && x > -7.5f * width) && (y < 7.5f * width && y > -7.5f * width))
{//在棋盘范围内
int xidx = (int)Math.Round(x / width + 7, 0);
int yidx = (int)Math.Round(7 - y / width, 0);
if (!QiPanArray[xidx, yidx].isPlace)
{
QiPanArray[xidx, yidx].isPlace = true;
QiPanArray[xidx, yidx].QiTp = NextQiType;
QiPanArray[xidx, yidx].Node = NowQi;
NowQi.transform.localPosition = QiPanArray[xidx, yidx].Pos;
if (NextQiType == QiType.white)
NextQiType = QiType.black;
else
NextQiType = QiType.white;
NowQi = null;
}
else
{
NowQi.transform.localScale = Vector3.zero;
}
}
else
{
NowQi.transform.localScale = Vector3.zero;
}
}
当鼠标松开时调用该函数,会根据鼠标位置设置放置位置,会有放置不成功的情况。
现在我们的游戏数据和操作功能有了,交替放黑白棋的功能也有了,接下来就是实现游戏结束的判断逻辑了。
结束判定
这输赢的判定就是率在八个方向的连续的五颗子即为赢。
判定分析
因为这的输赢判定简单,是最后落下的一颗棋子代表的一方有可能赢,就是最后落下的子能决定胜负,只用判定以它为中心关联的条线上的棋子是否构成五颗连续同颜色即可。
上图中四条不同颜色的线代表需要判定的方向,按这个思路,就是写几个for循环的事了。
结束判定实现
public bool CheckGameOver(int posx,int posy) {
int count = 1; //连续棋子数
//上下方向检测
for (int i = posy + 1; i < 15; i++) {
if (QiPanArray[posx, posy].QiTp == QiPanArray[posx, i].QiTp) {
if (++count >= 5)
return true;
}
else
break;
}
for (int i = posy - 1; i >= 0; i--) {
if (QiPanArray[posx, posy].QiTp == QiPanArray[posx, i].QiTp)
{
if (++count >= 5)
return true;
}
else
break;
}
count = 1;
//左右方向检测
for (int i = posx + 1; i < 15; i++)
{
if (QiPanArray[posx, posy].QiTp == QiPanArray[i, posy].QiTp)
{
if (++count >= 5)
return true;
}
else
break;
}
for (int i = posx - 1; i >= 0; i--)
{
if (QiPanArray[posx, posy].QiTp == QiPanArray[i, posy].QiTp)
{
if (++count >= 5)
return true;
}
else
break;
}
count = 1;
//右上方向检测
for (int i = posx + 1, j = posy + 1; i < 15 && j < 15; i++,j++)
{
if (QiPanArray[posx, posy].QiTp == QiPanArray[i, j].QiTp)
{
if (++count >= 5)
return true;
}
else
break;
}
//左下方向检测
for (int i = posx - 1, j = posy - 1; i >= 0 && j >= 0; i--,j--)
{
if (QiPanArray[posx, posy].QiTp == QiPanArray[i, j].QiTp)
{
if (++count >= 5)
return true;
}
else
break;
}
count = 1;
//右下方向检测
for (int i = posx + 1, j = posy - 1; i < 15 && j >= 0; i++, j--)
{
if (QiPanArray[posx, posy].QiTp == QiPanArray[i, j].QiTp)
{
if (++count >= 5)
return true;
}
else
break;
}
//左上方向检测
for (int i = posx - 1, j = posy + 1; i >= 0 && j < 15; i--, j++)
{
if (QiPanArray[posx, posy].QiTp == QiPanArray[i, j].QiTp)
{
if (++count >= 5)
return true;
}
else
break;
}
return false;
}
这里的两个参数即int posx,int posy,是最后落下棋子所在的格子的下标。
完善工程
新增UI
这里新增的两个UI分别是开始UI和结束UI,都是自带的按钮组件和图片组件构成。
开始UI
结束UI
完善代码
这里主要实现几个按钮的点击功能,已经场景的切换。
点击函数
自己看代码吧:
//开始游戏
public void Play()
{
StartPanel.SetActive(false);
BackBtn.SetActive(true);
isGaming = true;
}
//重新开始
public void RePlay()
{
StartPanel.SetActive(false);
OverPanel.SetActive(false);
BackBtn.SetActive(true);
for (int i = 0; i < 15; i++)
for (int j = 0; j < 15; j++)
{
QiPanArray[i, j].isPlace = false;
QiPanArray[i, j].QiTp = QiType.none;
if (QiPanArray[i, j].Node != null)
{
Destroy(QiPanArray[i, j].Node);
QiPanArray[i, j].Node = null;
}
}
isGaming = true;
}
//返回大厅
public void BackHall()
{
isGaming = false;
StartPanel.SetActive(true);
OverPanel.SetActive(false);
for (int i = 0; i < 15; i++)
for (int j = 0; j < 15; j++) {
QiPanArray[i, j].isPlace = false;
QiPanArray[i, j].QiTp = QiType.none;
if (QiPanArray[i, j].Node != null) {
Destroy(QiPanArray[i, j].Node);
QiPanArray[i, j].Node = null;
}
}
BackBtn.SetActive(false);
}
结束操作
public void GameOver()
{
isGaming = false;
OverPanel.SetActive(true);
WinSide.text = NextQiType == QiType.white ? "白棋获胜!" : "黑棋获胜!";
}
总结
这个实现的比较快,不过只是实现了核心的玩法功能,其实可以延申开发的地方比较多,可以有兴趣写个人机对战的,还有平手的判定等这些都没有加。源码接近17KB,代码包含300多行,将就这看吧。
相关文章
- 【Kaggle项目实战记录】狗的品种识别
- Eclipse中web项目部署至Tomcat步骤
- vue项目接入sentry错误日志采集
- 软件测试 之Web项目实战解析(附全套实战项目教程+视频+源码)
- Aes加密/解密示例项目
- 转: 如何快速学习一个开源项目源码?
- iOS上线项目源码分享
- idea导入(import)项目和打开(open)项目的区别
- 黑马程序员 Python学习笔记之多文件项目的演练
- 【项目精选】springboot职称评审管理系统(论文+源码)
- 【项目精选】网络考试系统的设计与实现(源码+视频+论文)
- 【项目精选】动漫论坛的设计与实现(论文+视频+源码)
- 【项目精选】城市公交查询系统(论文+视频+源码)
- 【项目精选】javaEE土地档案管理系统(源码+论文+视频)
- 【项目精选】基于JAVA的机场航班起降与协调管理系统(论文+视频+源码)
- 如何将Vue项目打包丢入虚拟机CentOS 7中运行
- Unity3d UGUI以鼠标位置点为中心缩放图片(含项目源码)
- 软件测试项目去哪里找?我都给你整理好了【源码+操作视频】
- 项目重构,从零开始搭建一套新的后台管理系统
- 实时即未来,大数据项目车联网之驾驶行程采样入库【十五】
- 商业级项目——基金客户端的架构设计与开发(下)(附源码)
- 如何快速学习一个开源项目源码?
- Unity huatuo示例项目源码分析与启发
- 客快物流大数据项目(六十六):车辆主题
- MFC-GetItemCount获取项目总数
- Wagon部署springboot项目读取配置文件错误问题
- Egg.js 源码分析-项目启动