当前位置: 首页 > wzjs >正文

农村电商平台简介潍坊seo推广

农村电商平台简介,潍坊seo推广,网站建设从入门到精通 网盘,中小企业营销型网站建设Unity版本2022.3 场景布置 其中可以通过给Board对象添加Grid Layout Group,然后设置每个子物体所占宽高快速排整齐。用完删掉。每个落子的方格ChessBox都是一个Button。 根据Board的宽高除以三即可。 然后隐藏按钮,通过设置alpha值实现。 将ChessBox的…

Unity版本2022.3

场景布置

在这里插入图片描述
其中可以通过给Board对象添加Grid Layout Group,然后设置每个子物体所占宽高快速排整齐。用完删掉。每个落子的方格ChessBox都是一个Button。

在这里插入图片描述

根据Board的宽高除以三即可。

然后隐藏按钮,通过设置alpha值实现。

在这里插入图片描述

将ChessBox的Alpha值设置为1,如果是0-1的格式,设置为0.1即可,后续在代码里控制alpha值,让落子可以被看到。

看心情摆一摆就好了,然后是写代码放引用。

代码编写

棋子种类

public enum Chess 
{None,X,O,
}

落子的九宫格

每个落子的方格都是一个Button,实现被点击的效果。可以加标识符拒绝再次点击,或者关闭button的交互。都行。

using UnityEngine;
using UnityEngine.UI;public class ChessBox : MonoBehaviour
{public Button currentButton;    // 当前脚本所在的按钮的引用public Image currentImage;      // 当前脚本所在的图片的引用public Chess chess;             // 当前格子的棋子public bool isChessed;          // 当前格子是否落子// Start is called before the first frame updatevoid Start(){currentButton = GetComponent<Button>();currentButton.onClick.AddListener(DrawChess);currentImage = GetComponent<Image>();isChessed = false;}
}

其中CurrentButton和CurrentImage是预防需要反复getComponent写的,实际可以去掉,然后代码中用到的位置都用GetComponent。此处两个字段是引用,而非值类型,所以可以直接修改这两个字段实现修改组件内部的属性,避免使用Sprite sprite来控制Image的Sprite。如果通过保存Image的Sprite作为字段,此处sprite是值类型,不是引用,对它的修改不会应用到Image组件的Sprite参数。

Sprite sprite;void Start(){sprite = GetComponent<Image>().sprite;}

这样后续修改sprite是无效的。

然后实现其中的落子函数,通过isChessed作为标识符判断是否可以落子,或者直接关闭按钮的交互,因为它是按钮。因为原本按钮是被设置为几乎不可见,所以落子后要重新设置alpha值,让他可见,R,G,B,A参数范围是0-1。

// 落子
public void DrawChess()
{// 落子或游戏结束,直接返回,不处理if (isChessed || GameManager.Instance.isGameOver) return;if(GameManager.Instance.isPlayerTurn){currentImage.sprite = GameManager.Instance.playerChessSprite;currentImage.color = new Color(1,1,1,1);chess = GameManager.Instance.playerChess;}else{currentImage.sprite = GameManager.Instance.aiChessSprite;currentImage.color = new Color(1, 1, 1, 1);chess = GameManager.Instance.aiChess;}isChessed = true;// 不用isChessed的话// currentButton.interactable = false;Board board = GetComponentInParent<Board>();board.OnChessBoxClicked(this);
}

落子后要让棋盘知道,所以这里使用的 GetComponentInParent<Board>()的方式。也可以给每个格子都像CurentButton那样保存对棋盘的引用。

这里暂时到这里。

棋盘

然后是棋盘的代码,判断游戏的进展之类的,还有重开。

实现格子落子时执行的棋盘的函数。

using TMPro;
using UnityEngine;
using UnityEngine.UI;public class Board : MonoBehaviour
{// 九个落子的格子public ChessBox[] chessBoxes = new ChessBox[9];// 获胜文本框public TextMeshProUGUI text_Winner;// 胜者public string winner;// 重开按钮public Button restartButton;// 落子数量public int chessCount;void Start(){chessCount = 0;chessBoxes = GetComponentsInChildren<ChessBox>();restartButton.onClick.AddListener(ReStart);}// 落子时调用public void OnChessBoxClicked(ChessBox chessBox){chessCount++;if (CheckIfWin()){GameOver();return;}else if( chessCount == 9)   // 没赢但是满了{winner = "Nobody";GameOver();return;}GameManager.Instance.SwitchTurn();}
}

此处的pulic字段其实都应使用private,毕竟其他地方也不用,然后通过其他方式赋初值,写在Awake函数中,或者序列化私有字段。

就像这样。

[SerializeField]private TextMeshProUGUI text_Winner;

这样可以在Unity中通过拖拽赋值,但是其他脚本访问不到。

每次落子后都要判断谁赢了或者是不是平局。

井字棋的获胜方式只有八种,即三行三列两个对角。
所以判断八种情况下的棋子有哪一种情况是相同的棋子,并且必须是其中一方的棋子,要避开初始情况下棋子全是None。

// 检查是否获胜
public bool CheckIfWin()
{return ChessMatch(0, 1, 2) || ChessMatch(3, 4, 5) || ChessMatch(6, 7, 8) ||ChessMatch(0, 3, 6) || ChessMatch(1, 4, 7) || ChessMatch(2, 5, 8) ||ChessMatch(0, 4, 8) || ChessMatch(2, 4, 6);
}
// 棋子匹配检查,是否三连子
bool ChessMatch(int i, int j, int k)
{if(chessBoxes[i].chess == chessBoxes[j].chess && chessBoxes[j].chess == chessBoxes[k].chess ){if(chessBoxes[k].chess == GameManager.Instance.playerChess){winner = "player";return true;}else if(chessBoxes[k].chess == GameManager.Instance.aiChess){winner = "ai";return true;}}return false;
}

接下来是落子后如果游戏结束,显示文本和不允许落子即可。

// 结束游戏,显示胜者
public void GameOver()
{text_Winner.text = $"{winner} is win!";GameManager.Instance.isGameOver = true;for (int i = 0; i < chessBoxes.Length; i++){// 禁止所有格子落子chessBoxes[i].isChessed = true;// 不用isChessed的话// chessBoxes[i].GetComponent<Button>().interactable = false;// chessBoxes[i].currentButton.interactable = false;}
}

重新开始

让所有格子重置,所以棋盘上写:

    // 清空棋盘状态,将上局最后一手设置为后手public void ReStart(){GameManager.Instance.isGameOver = false;for (int i = 0; i < chessBoxes.Length; i++){chessBoxes[i].ReStart();}text_Winner.text = "gaming";GameManager.Instance.SwitchTurn();}

重置状态,alpha值要设置的小一些,不然会显示null的sprite是纯白的,会挡住背景,但不要设置为0,如果是0就点不到了。格子按钮上写:

    public void ReStart(){isChessed = false;chess = Chess.None;currentImage.sprite = null;// 不用isChessed的话// GetComponent<Button>().interactable = true;currentImage.color = new Color(1, 1, 1, 0.01f);}

GameManager

存一堆到处用的东西?大概吧。

public class GameManager : MonoBehaviour
{public bool isPlayerTurn;   // 是否是玩家回合public Chess playerChess;   // 玩家棋子public Chess aiChess;       // ai棋子public Sprite playerChessSprite;    // 玩家的棋子精灵public Sprite aiChessSprite;        // ai的棋子精灵public bool isGameOver;             // 游戏是否已结束public Board board;     // 棋盘引用public static GameManager Instance { get; private set; }private void Awake(){// 不切换场景,这样就够了if (Instance == null){Instance = this;}// 初始化状态isPlayerTurn = true;isGameOver = false;board = FindObjectOfType<Board>();}

在Inspector中给了Board引用后,其中的 FindObjectOfType<Board>()可以删除。

切换回合,很简单,如果不写AI行为,那AI其实算是P2。

// 切换回合
public void SwitchTurn()
{isPlayerTurn = !isPlayerTurn;// 如果是 AI 的回合,调用 AI 落子逻辑if (!isPlayerTurn && !isGameOver){AIPlay();}
}

AI行为–基于规则的AI

由于井字棋很简单,所以AI的逻辑也很简单,如果玩家能赢,那就堵,如果AI能赢,那就填,不然随便放,也可以加一步,如果AI先手,即场上全空,那优先抢中间。

    // 获取没落子的空位置private ChessBox[] GetEmptyChessBoxes(){// 获取所有 ChessBoxChessBox[] allBoxes = FindObjectsOfType<ChessBox>();// 过滤出空的 ChessBoxList<ChessBox> emptyBoxes = new List<ChessBox>();foreach (ChessBox box in allBoxes){if (box.chess == Chess.None){emptyBoxes.Add(box);}}return emptyBoxes.ToArray();}// AI行为private void AIPlay(){ChessBox[] emptyBoxes = GetEmptyChessBoxes();//if(emptyBoxes.Length == 9)//{//    Board board = FindObjectOfType<Board>();//    board.chessBoxes[4].DrawChess();//    return;//}if (emptyBoxes.Length > 0){// 检查是否有可以立即获胜的位置ChessBox winningBox = FindWinningBox(aiChess, emptyBoxes);if (winningBox != null){winningBox.DrawChess();return;}// 检查玩家是否有即将获胜的位置ChessBox blockingBox = FindWinningBox(playerChess, emptyBoxes);if (blockingBox != null){blockingBox.DrawChess();return;}// 随机选择一个空的位置int randomIndex = Random.Range(0, emptyBoxes.Length);ChessBox selectedBox = emptyBoxes[randomIndex];selectedBox.DrawChess();}}// 寻找可以获胜的格子private ChessBox FindWinningBox(Chess targetChess, ChessBox[] emptyBoxes){foreach (ChessBox box in emptyBoxes){// 模拟落子box.chess = targetChess;// 检查是否获胜if (board.CheckIfWin()){// 恢复 ChessBox 状态box.chess = Chess.None;return box;}// 恢复 ChessBox 状态box.chess = Chess.None;}return null;}

最后

在每次重开后,切换回合是为了避免上一局最后是玩家,那么玩家落子后就是AI了,而没有写AI先手。

可以改为重置为玩家回合,或者给Restart里写如果是AI那就执行一次AIplay。

直接执行切换回合,不仅使上一局最后一手为后手,还同时检测了是谁,如果是AI那就落子,如果是玩家那就玩家落子,同时做到了开局可以是玩家也可以是AI。

其实反正小东西,无脑public的好处是写得少,还能直接在Inspector里看情况,如果真需要调用,不用回来重新改private为public。

最后一点截图,场景中的引用

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

参考链接

Unity tutorial - How to make Tic Tac Toe game [ Part 1 ]

Unity tutorial - How to make Tic Tac Toe game [ Part 2 ]

仓库链接

MapleInori/JingZiQi: 学习记录 (github.com)

http://www.dtcms.com/wzjs/253291.html

相关文章:

  • 三亚旅游网站建设抖音seo搜索优化
  • 新闻聚合网站开发 技术北京百度网讯人工客服电话
  • 宁波网站网站建设站优云seo优化
  • 央企 网站建设 公司韩国seocaso
  • 做网站需要知道的问题谷歌搜索优化
  • 悟空crm官网百度seo关键词排名查询工具
  • 海门市政府投资项目工程建设中心网站短视频seo询盘获客系统
  • 网络空间的竞争归根结底是百度seo排名优化助手
  • 国家品牌网上海优化关键词的公司
  • 做网站主机云服务器
  • 武汉做网站找互赢网络百度seo教程
  • 优惠券的网站制作baike seotl
  • 深圳最新政策网站seo搜索引擎优化案例
  • php做网站后台语言太原好的网站制作排名
  • 做的比较好的旅行网站网上营销的平台有哪些
  • 如何做销售网站地推团队如何收费
  • 公司是否可以做多个网站草根seo视频大全
  • 池州网站制作优化网络营销比较好的企业
  • 绿色大气网站模板seo实战教程
  • 东莞樟木头网站建设百度关键词优化大师
  • 建设网站方法有哪些营销100个引流方案
  • 大连网站推广优化百度推广话术全流程
  • asp 做网站的缺点百度客服人工在线咨询电话
  • 网站代码验证优化网站做什么的
  • 网站建设教程自学网友情链接在线观看
  • 网站上图片的链接怎么做首页优化公司
  • 做网站有陪标现象吗广州网络seo公司
  • 龙岩市企业网厦门seo屈兴东
  • 外网设计灵感网站seo模拟点击
  • 公众号电脑版登陆入口刷网站seo排名软件