01-处理蛇身的生成

将Sh贪吃蛇头更名为SnakeHead,新建Image更名为SnakeBody

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SnakeHead : MonoBehaviour
{public List<Transform> bodyList = new List<Transform>();//存储身体的位置public float velocity=0.35f;//每隔多久要调用,实际就相当于速度public int step;//小蛇每一步要走的路private int x;//x和Y都是移动的增量private int y;private Vector3 HeadPos;//记录头的位置private Transform canvas;public GameObject bodyPrefab;//蛇身预制体public Sprite[] bodySprites = new Sprite[2];void Start(){InvokeRepeating("Move",0,velocity);x = 0;//刚开始的时候,贪吃蛇就会往上走y =step;}void Update(){if (Input.GetKeyDown(KeyCode.Space))//CancelInvoke()取消当前的Invoke{CancelInvoke();InvokeRepeating("Move", 0, velocity-0.2f);//跑快}if (Input.GetKeyUp(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move", 0, velocity);//减速就是回到正常速度}if (Input.GetKey(KeyCode.W)&&y!=-step)//y!=-step加这句是蛇头向下的时候不是直接向下的{gameObject.transform.localRotation = Quaternion.Euler(0,0,0);//将Float值转换成四元数x = 0;y = step;}if (Input.GetKey(KeyCode.S)&&y != step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);//将Float值转换成四元数x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x != step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);//将Float值转换成四元数x = -step;y = 0;}if (Input.GetKey(KeyCode.D) && x != -step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);//将Float值转换成四元数x = step;y = 0;}}/// <summary>/// 头部的移动/// </summary>void Move(){HeadPos = gameObject.transform.localPosition;gameObject.transform.localPosition = new Vector3(HeadPos.x + x,HeadPos.y+y,HeadPos.z);}/// <summary>/// 生成蛇身/// </summary>void Grow(){int index=(bodyList.Count%2==0)?0:1;GameObject body = Instantiate(bodyPrefab);body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas,false);bodyList.Add(body.transform);}private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.CompareTag("Food"))//也可以写成collision.tag == "Food"{Destroy(collision.gameObject);FoodMaker.Instance.MakeFood();}}
}

02-处理蛇身的移动之方法一

用移动方法二,这个不适合双色蛇身

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
public class SnakeHead : MonoBehaviour
{public List<Transform> bodyList = new List<Transform>();//存储身体的位置public float velocity=0.35f;//每隔多久要调用,实际就相当于速度public int step;//小蛇每一步要走的路private int x;//x和Y都是移动的增量private int y;private Vector3 HeadPos;//记录头的位置private Transform canvas;public GameObject bodyPrefab;//蛇身预制体public Sprite[] bodySprites = new Sprite[2];private void Awake(){canvas = GameObject.Find("Canvas").transform;}void Start(){InvokeRepeating("Move",0,velocity);x = 0;//刚开始的时候,贪吃蛇就会往上走y =step;}void Update(){if (Input.GetKeyDown(KeyCode.Space))//CancelInvoke()取消当前的Invoke{CancelInvoke();InvokeRepeating("Move", 0, velocity-0.2f);//跑快}if (Input.GetKeyUp(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move", 0, velocity);//减速就是回到正常速度}if (Input.GetKey(KeyCode.W)&&y!=-step)//y!=-step加这句是蛇头向下的时候不是直接向下的{gameObject.transform.localRotation = Quaternion.Euler(0,0,0);//将Float值转换成四元数x = 0;y = step;}if (Input.GetKey(KeyCode.S)&&y != step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);//将Float值转换成四元数x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x != step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);//将Float值转换成四元数x = -step;y = 0;}if (Input.GetKey(KeyCode.D) && x != -step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);//将Float值转换成四元数x = step;y = 0;}}/// <summary>/// 头部的移动/// </summary>void Move(){HeadPos = gameObject.transform.localPosition;gameObject.transform.localPosition = new Vector3(HeadPos.x + x,HeadPos.y+y,HeadPos.z);//Grow();//如果放在这里还来不及显示,就被下面的代码排了位置,但是要列出标识位,管一下开关if (bodyList.Count > 0){bodyList.Last().localPosition = HeadPos;//直接返回最后一个元素bodyList.Insert(0, bodyList.Last());bodyList.RemoveAt(bodyList.Count - 1);}}/// <summary>/// 生成蛇身/// </summary>void Grow(){int index=(bodyList.Count%2==0)?0:1;GameObject body = Instantiate(bodyPrefab,new Vector3(2000,2000,0),Quaternion.identity);//new Vector3(2000,2000,0)生成的时候放在看不到的位置,这样就不会显示在中间了body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas,false);bodyList.Add(body.transform);}private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.CompareTag("Food"))//也可以写成collision.tag == "Food"{Destroy(collision.gameObject);Grow();//吃了食物之后立马调用FoodMaker.Instance.MakeFood();}}
}

03-处理蛇身的移动之方法二

using System.Collections;
using System.Collections.Generic;
//using System.Linq;
using UnityEngine;
using UnityEngine.UI;
public class SnakeHead : MonoBehaviour
{public List<Transform> bodyList = new List<Transform>();//存储身体的位置public float velocity=0.35f;//每隔多久要调用,实际就相当于速度public int step;//小蛇每一步要走的路private int x;//x和Y都是移动的增量private int y;private Vector3 HeadPos;//记录头的位置private Transform canvas;public GameObject bodyPrefab;//蛇身预制体public Sprite[] bodySprites = new Sprite[2];private void Awake(){canvas = GameObject.Find("Canvas").transform;}void Start(){InvokeRepeating("Move",0,velocity);x = 0;//刚开始的时候,贪吃蛇就会往上走y =step;}void Update(){if (Input.GetKeyDown(KeyCode.Space))//CancelInvoke()取消当前的Invoke{CancelInvoke();InvokeRepeating("Move", 0, velocity-0.2f);//跑快}if (Input.GetKeyUp(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move", 0, velocity);//减速就是回到正常速度}if (Input.GetKey(KeyCode.W)&&y!=-step)//y!=-step加这句是蛇头向下的时候不是直接向下的{gameObject.transform.localRotation = Quaternion.Euler(0,0,0);//将Float值转换成四元数x = 0;y = step;}if (Input.GetKey(KeyCode.S)&&y != step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);//将Float值转换成四元数x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x != step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);//将Float值转换成四元数x = -step;y = 0;}if (Input.GetKey(KeyCode.D) && x != -step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);//将Float值转换成四元数x = step;y = 0;}}/// <summary>/// 头部的移动/// </summary>void Move(){HeadPos = gameObject.transform.localPosition;//保存下来蛇头移动前的位置gameObject.transform.localPosition = new Vector3(HeadPos.x + x,HeadPos.y+y,HeadPos.z);//蛇头向期望位置移动//Grow();//如果放在这里还来不及显示,就被下面的代码排了位置,但是要列出标识位,管一下开关if (bodyList.Count > 0){//由于我们是双色蛇身,此方法弃用//bodyList.Last().localPosition = HeadPos;//直接返回最后一个元素//将蛇尾移动到蛇头移动前的位置//bodyList.Insert(0, bodyList.Last());//将蛇尾在List中的位置更新到最前//bodyList.RemoveAt(bodyList.Count - 1);//移除List最末尾的蛇尾引用//由于我们是双色蛇身,使用此方法达到显示目的for (int i = bodyList.Count-2; i>=0; i--)//是从后往前开始移动的蛇身 i = bodyList.Count-2{bodyList[i + 1].localPosition = bodyList[i].localPosition;//每一个蛇身都移动到他前面一个节点的位置}bodyList[0].localPosition = HeadPos;//第一个蛇身移动到蛇头移动前的位置}}/// <summary>/// 生成蛇身/// </summary>void Grow(){int index=(bodyList.Count%2==0)?0:1;刚开始时候bodyList.Count为0,GameObject body = Instantiate(bodyPrefab,new Vector3(2000,2000,0),Quaternion.identity);//new Vector3(2000,2000,0)生成的时候放在看不到的位置,这样就不会显示在中间了body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas,false);bodyList.Add(body.transform);}private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.CompareTag("Food"))//也可以写成collision.tag == "Food"{Destroy(collision.gameObject);Grow();//吃了食物之后立马调用FoodMaker.Instance.MakeFood();}}
}

04-让蛇可以通过边界进行传送

给SnakeBody添加标签Body,以便于识别撞到自己的时候会死亡。

using System.Collections;
using System.Collections.Generic;
//using System.Linq;
using UnityEngine;
using UnityEngine.UI;
public class SnakeHead : MonoBehaviour
{public List<Transform> bodyList = new List<Transform>();//存储身体的位置public float velocity=0.35f;//每隔多久要调用,实际就相当于速度public int step;//小蛇每一步要走的路private int x;//x和Y都是移动的增量private int y;private Vector3 HeadPos;//记录头的位置private Transform canvas;public GameObject bodyPrefab;//蛇身预制体public Sprite[] bodySprites = new Sprite[2];private void Awake(){canvas = GameObject.Find("Canvas").transform;}void Start(){InvokeRepeating("Move",0,velocity);x = 0;//刚开始的时候,贪吃蛇就会往上走y =step;}void Update(){if (Input.GetKeyDown(KeyCode.Space))//CancelInvoke()取消当前的Invoke{CancelInvoke();InvokeRepeating("Move", 0, velocity-0.2f);//跑快}if (Input.GetKeyUp(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move", 0, velocity);//减速就是回到正常速度}if (Input.GetKey(KeyCode.W)&&y!=-step)//y!=-step加这句是蛇头向下的时候不是直接向下的{gameObject.transform.localRotation = Quaternion.Euler(0,0,0);//将Float值转换成四元数x = 0;y = step;}if (Input.GetKey(KeyCode.S)&&y != step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);//将Float值转换成四元数x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x != step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);//将Float值转换成四元数x = -step;y = 0;}if (Input.GetKey(KeyCode.D) && x != -step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);//将Float值转换成四元数x = step;y = 0;}}/// <summary>/// 头部的移动/// </summary>void Move(){HeadPos = gameObject.transform.localPosition;//保存下来蛇头移动前的位置gameObject.transform.localPosition = new Vector3(HeadPos.x + x,HeadPos.y+y,HeadPos.z);//蛇头向期望位置移动//Grow();//如果放在这里还来不及显示,就被下面的代码排了位置,但是要列出标识位,管一下开关if (bodyList.Count > 0){//由于我们是双色蛇身,此方法弃用//bodyList.Last().localPosition = HeadPos;//直接返回最后一个元素//将蛇尾移动到蛇头移动前的位置//bodyList.Insert(0, bodyList.Last());//将蛇尾在List中的位置更新到最前//bodyList.RemoveAt(bodyList.Count - 1);//移除List最末尾的蛇尾引用//由于我们是双色蛇身,使用此方法达到显示目的for (int i = bodyList.Count-2; i>=0; i--)//是从后往前开始移动的蛇身 i = bodyList.Count-2{bodyList[i + 1].localPosition = bodyList[i].localPosition;//每一个蛇身都移动到他前面一个节点的位置}bodyList[0].localPosition = HeadPos;//第一个蛇身移动到蛇头移动前的位置}}/// <summary>/// 生成蛇身/// </summary>void Grow(){int index=(bodyList.Count%2==0)?0:1;GameObject body = Instantiate(bodyPrefab,new Vector3(2000,2000,0),Quaternion.identity);//new Vector3(2000,2000,0)生成的时候放在看不到的位置,这样就不会显示在中间了body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas,false);bodyList.Add(body.transform);}private void OnTriggerEnter2D(Collider2D collision){//食物 if (collision.gameObject.CompareTag("Food"))//也可以写成collision.tag == "Food"{Destroy(collision.gameObject);Grow();//吃了食物之后立马调用FoodMaker.Instance.MakeFood();}else if (collision.gameObject.CompareTag("Body")){Debug.Log("Die");}else {switch (collision.gameObject.name){case "Up":transform.localPosition = new Vector3(transform.localPosition.x,-transform.localPosition.y+30,transform.localPosition.z);break;case "Down":transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y-30, transform.localPosition.z);break;case "Left":transform.localPosition = new Vector3(-transform.localPosition.x+180, transform.localPosition.y, transform.localPosition.z);//因为左右不对称,这样加180才能从右边边缘出来break;case "Right":transform.localPosition = new Vector3(-transform.localPosition.x + 240, transform.localPosition.y, transform.localPosition.z);break;}Debug.Log("Die");}}
}

05-奖励目标的生成与获取

在Canvas下新建Image更名为Reward并拖入到Prefabs文件夹下。修改其Tag值为Reward

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class FoodMaker : MonoBehaviour
{private static FoodMaker _instance;public static FoodMaker Instance{get{return _instance;}}public int xlimit=21;public int ylimit = 11;public int xoffset = 7;public GameObject foodPrefab;public Sprite[] foodSprites;private Transform foodHolder;public GameObject rewardPrefab;private void Awake(){_instance = this;}private void Start(){foodHolder = GameObject.Find("FoodHolder").transform;MakeFood(false);}/// <summary>/// 生成食物/// </summary>public void MakeFood(bool isReward){int index = Random.Range(0,foodSprites.Length);GameObject food = Instantiate(foodPrefab);food.GetComponent<Image>().sprite = foodSprites[index];food.transform.SetParent(foodHolder,false);//false是否保持世界坐标,不转换坐标int x = Random.Range(-xlimit+xoffset,xlimit);int y = Random.Range(-ylimit,ylimit);food.transform.localPosition = new Vector3(x*30,y*30,0);if (isReward){GameObject reward = Instantiate(rewardPrefab);reward.transform.SetParent(foodHolder, false);//false是否保持世界坐标,不转换坐标x = Random.Range(-xlimit + xoffset, xlimit);y = Random.Range(-ylimit, ylimit);reward.transform.localPosition = new Vector3(x * 30, y * 30, 0);}}
}
using System.Collections;
using System.Collections.Generic;
//using System.Linq;
using UnityEngine;
using UnityEngine.UI;
public class SnakeHead : MonoBehaviour
{public List<Transform> bodyList = new List<Transform>();//存储身体的位置public float velocity=0.35f;//每隔多久要调用,实际就相当于速度public int step;//小蛇每一步要走的路private int x;//x和Y都是移动的增量private int y;private Vector3 HeadPos;//记录头的位置private Transform canvas;public GameObject bodyPrefab;//蛇身预制体public Sprite[] bodySprites = new Sprite[2];private void Awake(){canvas = GameObject.Find("Canvas").transform;}void Start(){InvokeRepeating("Move",0,velocity);x = 0;//刚开始的时候,贪吃蛇就会往上走y =step;}void Update(){if (Input.GetKeyDown(KeyCode.Space))//CancelInvoke()取消当前的Invoke{CancelInvoke();InvokeRepeating("Move", 0, velocity-0.2f);//跑快}if (Input.GetKeyUp(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move", 0, velocity);//减速就是回到正常速度}if (Input.GetKey(KeyCode.W)&&y!=-step)//y!=-step加这句是蛇头向下的时候不是直接向下的{gameObject.transform.localRotation = Quaternion.Euler(0,0,0);//将Float值转换成四元数x = 0;y = step;}if (Input.GetKey(KeyCode.S)&&y != step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);//将Float值转换成四元数x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x != step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);//将Float值转换成四元数x = -step;y = 0;}if (Input.GetKey(KeyCode.D) && x != -step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);//将Float值转换成四元数x = step;y = 0;}}/// <summary>/// 头部的移动/// </summary>void Move(){HeadPos = gameObject.transform.localPosition;//保存下来蛇头移动前的位置gameObject.transform.localPosition = new Vector3(HeadPos.x + x,HeadPos.y+y,HeadPos.z);//蛇头向期望位置移动//Grow();//如果放在这里还来不及显示,就被下面的代码排了位置,但是要列出标识位,管一下开关if (bodyList.Count > 0){//由于我们是双色蛇身,此方法弃用//bodyList.Last().localPosition = HeadPos;//直接返回最后一个元素//将蛇尾移动到蛇头移动前的位置//bodyList.Insert(0, bodyList.Last());//将蛇尾在List中的位置更新到最前//bodyList.RemoveAt(bodyList.Count - 1);//移除List最末尾的蛇尾引用//由于我们是双色蛇身,使用此方法达到显示目的for (int i = bodyList.Count-2; i>=0; i--)//是从后往前开始移动的蛇身 i = bodyList.Count-2{bodyList[i + 1].localPosition = bodyList[i].localPosition;//每一个蛇身都移动到他前面一个节点的位置}bodyList[0].localPosition = HeadPos;//第一个蛇身移动到蛇头移动前的位置}}/// <summary>/// 生成蛇身/// </summary>void Grow(){int index=(bodyList.Count%2==0)?0:1;GameObject body = Instantiate(bodyPrefab,new Vector3(2000,2000,0),Quaternion.identity);//new Vector3(2000,2000,0)生成的时候放在看不到的位置,这样就不会显示在中间了body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas,false);bodyList.Add(body.transform);}private void OnTriggerEnter2D(Collider2D collision){//食物 if (collision.gameObject.CompareTag("Food"))//也可以写成collision.tag == "Food"{Destroy(collision.gameObject);Grow();//吃了食物之后立马调用FoodMaker.Instance.MakeFood((Random.Range(0, 100) < 20) ? true : false);}else if (collision.gameObject.CompareTag("Reward")){Destroy(collision.gameObject);Grow();}else if (collision.gameObject.CompareTag("Body")){Debug.Log("Die");}else{switch (collision.gameObject.name){case "Up":transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y + 30, transform.localPosition.z);break;case "Down":transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y - 30, transform.localPosition.z);break;case "Left":transform.localPosition = new Vector3(-transform.localPosition.x + 180, transform.localPosition.y, transform.localPosition.z);//因为左右不对称,这样加180才能从右边边缘出来break;case "Right":transform.localPosition = new Vector3(-transform.localPosition.x + 240, transform.localPosition.y, transform.localPosition.z);break;}Debug.Log("Die");}}
}

SIKI学习——贪吃蛇案例05相关推荐

  1. 【无标题】学习贪吃蛇代码

    学习贪吃蛇代码

  2. javascript学习-贪吃蛇

    贪吃蛇的例子: 在此例子中,利用snake数组的第0个元素和direction对象中的x值和y值做加法,算出蛇的下一个位置.利用间隔函数,不停的修改类名来进行渲染操作,感觉是一个很灵活的例子. sty ...

  3. GUI编程 含贪吃蛇案例

    GUI编程 含贪吃蛇案例 组件: 窗口 弹窗 面板 文本框 列表框 按钮 图片 监听事件 鼠标事件 键盘事件 1.简介 GUI 的核心技术:Swing,AWT 为什么现在不流行了? 界面不美观 需要j ...

  4. TS练习 贪吃蛇案例

    文章目录 TS练习 贪吃蛇案例 环境配置 ts编译文件tsconfig.json webpack配置文件webpack.config.js babel 处理兼容问题 编写ts代码 界面 食物类 Foo ...

  5. Web前端学习笔记——JavaScript之面向对象游戏案例:贪吃蛇

    面向对象游戏案例:贪吃蛇 案例相关源码以上传到 GitHub :https://github.com/lipengzhou/new-snake 案例介绍 游戏演示 在线演示地址:贪吃蛇 案例目标 游戏 ...

  6. Unity3D初级案例-经典贪吃蛇一

    引言:小生今日分享的是经典贪吃蛇案例,特别感谢Siki学院的老师们. 这里附上原视频链接: http://www.sikiedu.com/my/course/89 可以搭配起来学习哦! 小生会根据自己 ...

  7. Unity3D初级案例-经典贪吃蛇二

    引言:承接上一篇贪吃蛇案例!喜欢我的就关注我啊,不然没有继续写的动力啦!!! 开发版本:unity 2017.1.1f1 适合人群:初学Unity者 源文件链接请见文末! 开启学习之旅吧! 07 边界 ...

  8. Unity学习笔记(1)-经典贪吃蛇2d

    第一次写博客,想想还是挺激动的.学习Unity3d也有一段时间了,现在分享下用Unity实现<经典贪吃蛇>游戏的一些心得,希望对爱好游戏开发的朋友们有所帮助.(也希望大佬们指点) 相信大家 ...

  9. JavaScript 面向对象游戏案例:贪吃蛇

    面向对象游戏案例:贪吃蛇 案例相关源码以上传到 GitHub :https://github.com/sunna1/snake 案例介绍 案例目标 游戏的目的是用来体会js高级语法的使用 不需要具备抽 ...

最新文章

  1. AndroidManifest.xml文件详解
  2. 快速在PowerPoint文档中添加图表
  3. SoftReference的用法
  4. 缓存之EHCache(二)
  5. Opportunity creation case in Firebug
  6. GoLang语言多版本管理工具--GVM入门介绍
  7. innobackupex参数之 --throttle 限速这个值设置多少合理 原创
  8. Ubuntu 11.10搭建和配置Nagios
  9. mysql timeout expired处理
  10. 零基础如何自学Java?
  11. Proteus中ADC0808的使用注意事项
  12. 2021信息安全工程师学习笔记(二十四)
  13. 2021年,中国程序员前景一片灰暗,真的是这样吗?
  14. 使用Java语言打印一个爱心图案
  15. 按快捷键进不去bios问题解决
  16. 基于javaweb+mysql的校园招聘平台招聘管理系统(平台、企业、用户)
  17. CUMT2022密码学考试
  18. 【2022最新爬虫】JS逆向之采集某某海关进出口信用平台数据
  19. 大家来说说大数据时代与真正跨平台应用,如何结合的更好
  20. 中国大数据产业全景图谱(2022年) 附下载

热门文章

  1. 实现库房批次管理,先进先出原则(一次难忘的找bug经历)
  2. 产品经理和项目经理的差异
  3. 根据IP地址划分子网
  4. 深度学习中FLOPs计算
  5. 线性代数库 Armadillo 学习笔记
  6. ijkplayer播放器
  7. SAP云集成 SAP Integration Suite启用过程,踩坑记
  8. 《灵飞经》3·印神无双 第十一章 力挽狂澜
  9. GB2312的中文编码表
  10. Kerberos双跳变通办法