Unity3D实现简易五子棋源码
作者:lijiao 发布时间:2021-08-15 15:57:04
标签:Unity3D,五子棋
本文实例为大家分享了Unity3d简易五子棋源码,供大家参考,具体内容如下
Unity3d部分
对C#源码进行了改写简化:
using UnityEngine;
using System.Collections;
public class chess : MonoBehaviour
{
//四个锚点位置,用于计算棋子落点
public GameObject LeftTop;
public GameObject RightTop;
public GameObject LeftBottom;
public GameObject RightBottom;
//主摄像机
public Camera cam;
//锚点在屏幕上的映射位置
Vector3 LTPos;
Vector3 RTPos;
Vector3 LBPos;
Vector3 RBPos;
Vector3 PointPos;//当前点选的位置
float gridWidth = 1; //棋盘网格宽度
float gridHeight = 1; //棋盘网格高度
float minGridDis; //网格宽和高中较小的一个
Vector2[,] chessPos; //存储棋盘上所有可以落子的位置
int[,] chessState; //存储棋盘位置上的落子状态
enum turn { black, white };
turn chessTurn; //落子顺序
public Texture2D white; //白棋子
public Texture2D black; //黑棋子
public Texture2D blackWin; //白子获胜提示图
public Texture2D whiteWin; //黑子获胜提示图
int winner = 0; //获胜方,1为黑子,-1为白子
bool isPlaying = true; //是否处于对弈状态
void Start()
{
chessPos = new Vector2[15, 15];
chessState = new int[17, 16];/*原来定义是new int[15, 15],这里将原来数组chessState上、下和右边各加一排数据,
也就相当于在棋盘的上、下和右边各填加一排隐形的棋道。原因后面解释*/
chessTurn = turn.black;
//计算锚点位置
LTPos = cam.WorldToScreenPoint(LeftTop.transform.position);
RTPos = cam.WorldToScreenPoint(RightTop.transform.position);
LBPos = cam.WorldToScreenPoint(LeftBottom.transform.position);
RBPos = cam.WorldToScreenPoint(RightBottom.transform.position);
//计算网格宽度
gridWidth = (RTPos.x - LTPos.x) / 14;
gridHeight = (LTPos.y - LBPos.y) / 14;
minGridDis = gridWidth < gridHeight ? gridWidth : gridHeight;
//计算落子点位置
for (int i = 0; i < 15; i++)
{
for (int j = 0; j < 15; j++)
{
chessPos[i, j] = new Vector2(LBPos.x + gridWidth * j, LBPos.y + gridHeight * i);//这里和源程序定义稍有不同,这里i定位行,j为列
}
}
}
void Update()
{
//检测鼠标输入并确定落子状态
if (isPlaying && Input.GetMouseButtonDown(0))
{
PointPos = Input.mousePosition;
for (int i = 0; i < 15; i++)
{
for (int j = 0; j < 15; j++)
{
//找到最接近鼠标点击位置的落子点,如果空则落子
if (Dis(PointPos, chessPos[i, j]) < minGridDis / 2 && chessState[i + 1, j] == 0)/*这里chessState行要加1,
因为上、下和右边各多加了一排,要空出来,chessPos的i行对应chessState的i+1行*/
{
//根据下棋顺序确定落子颜色
chessState[i + 1, j] = chessTurn == turn.black ? 1 : -1;//同理
//落子成功,更换下棋顺序
chessTurn = chessTurn == turn.black ? turn.white : turn.black;
}
}
}
//调用判断函数,确定是否有获胜方
int re = result();
if (re == 1)
{
Debug.Log("黑棋胜");
winner = 1;
isPlaying = false;
}
else if (re == -1)
{
Debug.Log("白棋胜");
winner = -1;
isPlaying = false;
}
}
//按下空格重新开始游戏
if (Input.GetKeyDown(KeyCode.Space))
{
for (int i = 0; i < 15; i++)
{
for (int j = 0; j < 15; j++)
{
chessState[i + 1, j] = 0;//同理
}
}
isPlaying = true;
chessTurn = turn.black;
winner = 0;
}
}
//计算平面距离函数
float Dis(Vector3 mPos, Vector2 gridPos)
{
return Mathf.Sqrt(Mathf.Pow(mPos.x - gridPos.x, 2) + Mathf.Pow(mPos.y - gridPos.y, 2));
}
void OnGUI()
{
//绘制棋子
for (int i = 0; i < 15; i++)
{
for (int j = 0; j < 15; j++)
{
if (chessState[i + 1, j] == 1)//同理
{
GUI.DrawTexture(new Rect(chessPos[i, j].x - gridWidth / 2, Screen.height - chessPos[i, j].y - gridHeight / 2, gridWidth, gridHeight), black);
}
if (chessState[i + 1, j] == -1)//同理
{
GUI.DrawTexture(new Rect(chessPos[i, j].x - gridWidth / 2, Screen.height - chessPos[i, j].y - gridHeight / 2, gridWidth, gridHeight), white);
}
}
}
//根据获胜状态,弹出相应的胜利图片
if (winner == 1)
{
GUI.DrawTexture(new Rect(Screen.width * 0.25f, Screen.height * 0.25f, Screen.width * 0.5f, Screen.height * 0.25f), blackWin);
}
if (winner == -1)
GUI.DrawTexture(new Rect(Screen.width * 0.25f, Screen.height * 0.25f, Screen.width * 0.5f, Screen.height * 0.25f), whiteWin);
}
//改写result函数
/*解释:C语言中,这样的表达式:chessState[i]&&chessState[i+1]&&chessState[i+2]&&chessState[i+3]&&chessState[i+4],如果
* chessState[i]为False,则不管B是真是假或者是异常都不会运行,利用这一点,在chessState的右边、上边和下边各加一行为0的数据,
* 这样在判断连续五个棋子的状态时,就不用担心chessState数组的索引值超出范围。例如:chessState[i+4]的索引值i+4刚好超出范围,
* 通过在原来数组chessState的上、下和右边个添加一排为0的数,这样chessState[i+3]==0,于是就可以避免引起异常,从而简化代码*/
int result()
{
int flag = 0;
if (chessTurn == turn.white)
{
for (int i = 1; i <= 15; i++)//这里的i从1开始
{
for (int j = 0; j <= 14; j++)//j不用变
{
if ((chessState[i, j] == 1 && chessState[i, j + 1] == 1 && chessState[i, j + 2] == 1 && chessState[i, j + 3] == 1 && chessState[i, j + 4] == 1)//向右横向
|| (chessState[i, j] == 1 && chessState[i + 1, j] == 1 && chessState[i + 2, j] == 1 && chessState[i + 3, j] == 1 && chessState[i + 4, j] == 1)//向上横向
|| (chessState[i, j] == 1 && chessState[i + 1, j + 1] == 1 && chessState[i + 2, j + 2] == 1 && chessState[i + 3, j + 3] == 1 && chessState[i + 4, j + 4] == 1)//向右上斜向
|| (chessState[i, j] == 1 && chessState[i - 1, j + 1] == 1 && chessState[i - 2, j + 2] == 1 && chessState[i - 3, j + 3] == 1 && chessState[i - 4, j + 4] == 1))//向右下斜向
{
flag = 1;
}
}
}
}
else if (chessTurn == turn.black)
{
for (int i = 1; i <= 15; i++)//这里的i从1开始
{
for (int j = 0; j <= 14; j++)
{
if ((chessState[i, j] == -1 && chessState[i, j + 1] == -1 && chessState[i, j + 2] == -1 && chessState[i, j + 3] == -1 && chessState[i, j + 4] == -1)
|| (chessState[i, j] == -1 && chessState[i + 1, j] == -1 && chessState[i + 2, j] == -1 && chessState[i + 3, j] == -1 && chessState[i + 4, j] == -1)
|| (chessState[i, j] == -1 && chessState[i + 1, j + 1] == -1 && chessState[i + 2, j + 2] == -1 && chessState[i + 3, j + 3] == -1 && chessState[i + 4, j + 4] == -1)
|| (chessState[i, j] == -1 && chessState[i - 1, j + 1] == -1 && chessState[i - 2, j + 2] == -1 && chessState[i - 3, j + 3] == -1 && chessState[i - 4, j + 4] == -1))
{
flag = -1;
}
}
}
}
return flag;
}
}
来源:https://blog.csdn.net/qq_30816923/article/details/97284445


猜你喜欢
- 目录前言asyncawait从以往知识推导创建异步任务创建异步任务并返回Task异步改同步说说 await Task说说 async Tas
- 本文实例讲述了java取两个字符串的最大交集的实现方法,分享给大家供大家参考。具体实现方法如下:package com.itheima.ne
- 前言今天遇到一个需求,需要对word模板进行替换制定的变量在网上找了很多方案,做了很多的demo,下面就把我觉得比较简单的一种分享给大家本次
- 最近做项目,ORM 使用的是 MyBatis,为了偷懒,我自然而然的想到了使用 MyBatis Generator(MBG)来生成数据库表对
- 一、前言在编码过程中,常常需要写打印日志语句,我们期望的是同一个业务的日志都在一块,在出问题的时候好根据日志来排查问题。而现实是在应用运行中
- 使用C#进行WinForm开发时,经常需要从WinForm窗体中获取用户输入数据。如果是字符串,那很好办,直接使用“控件名.Text”即可。
- 通过VideoView播放视频的步骤:1、在界面布局文件中定义VideoView组件,或在程序中创建VideoView组件2、调用Video
- 序列化简介Java 的对象序列化将那些实现 Serializable 接口的对象转换成一个字节序列,并能在之后将这个字节序列完全恢复为原来的
- Android读取资源文件的方法1、放入到资源文件夹里面,也就是所创建android工程的res下面。
- using System; using System.IO; public class FileApp { &nbs
- CountDownLatch 是一个同步工具类,用来协调多个线程之间的同步,它能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。
- 1.什么是灰度发布?灰度发布又称金丝雀发布,是在系统升级的时候能够平滑过渡的一种发布方式。在其上可以进行A/B测试,即让一部分用户继续用产品
- 一、概述我们对于这个图片肯定会非常熟悉,这两幅图片我们都可以看做是一个文件结构,对于这样的结构我们称之为树形结构。在数据结构中我们了解到可以
- 1.概述:C语言中的单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始。链表中最简单的一种
- 前言在上一篇中,我们介绍了使用位运算实现加法和减法运算,接下来本文主要介绍如何用位运算实现乘法运算,在实现乘法时要用位运算实现,并且不能出现
- 前面文章介绍了如何使用JAVA的反射机制来调用蓝牙的隐藏API,本文继续来练习JAVA的反射机制,探秘TelephonyManager在Fr
- using System.Drawing;using System.Drawing.Imaging;using System;using S
- C#的MVC寻找对应的控制器首先是寻找当前域的如果找不到就会寻找备用的..但是有些时候我们是不想他去寻找备用的控制器.这里就涉及到了一个Da
- 在同一个类中: 对于静态方法,其他的静态或非静态方法都可以直接调用它。而对于非静态方法,其他的非静态方法是可以直接调用它的。但是其他静态方法
- //while和for循环可以相互转换,以下为简单格式;for(1;2;3) A;//等价于