2021-09-23

unity实现井字棋小游戏

前言

这是中山大学2021年3D游戏编程与设计的第一次作业

游戏简介

井字棋游戏,有pvp和pve两种模式供选择,并带有背景音乐

游戏截图

在这里插入图片描述

实现过程

Reset():
棋盘初始化函数,将棋盘所有格恢复为初始状态。

void Reset () {
		turn = 1;
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				Chessboard [i] [j] = 0;
			}
		}	
		audioSource.Play ();
	}

check():
用于判断游戏状态
行获胜

		for (int i = 0; i < 3; i++) {
			if (Chessboard[i][0] != 0 && Chessboard[i][0] == Chessboard[i][1] && Chessboard[i][1] == Chessboard[i][2]) {
				return Chessboard[i][0];
			}
		}

列获胜

		for (int i = 0; i < 3; i++) {
			if (Chessboard[0][i] != 0 && Chessboard[0][i] == Chessboard[1][i] && Chessboard[1][i] == Chessboard[2][i]) {
				return Chessboard[0][i];
			}
		}

斜线获胜

   	if (Chessboard[1][1] != 0 &&
   	    Chessboard[0][0]== Chessboard[1][1] && Chessboard[2][2] == Chessboard[1][1] ||
   	    Chessboard[0][2] == Chessboard[1][1] && Chessboard[2][0] == Chessboard[1][1]) {
   		return Chessboard[1][1];
   	}

对局继续

  	for (int i = 0; i < 3; ++i) {
  		for (int j = 0; j < 3; ++j) {
  			if (Chessboard[i][j] == 0) return 0;
  		}
  	}

平局

  	return 0;

pvp():
先绘制已经下好的棋子,再判断游戏是否结束,若没结束则根据turn的值进行本次点击,更改多维数组的值

	void pvp(){
		int result = check();
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				if (Chessboard [i][j] == 1)
					GUI.Button (new Rect (5 + 60 * i, 20 + 60*j, 60, 60), img1);
				if (Chessboard [i][j] == 2)
					GUI.Button (new Rect (5 + 60 * i, 20 + 60*j, 60, 60), img2);
				if (GUI.Button (new Rect (5 + 60 * i, 20 + 60*j, 60, 60), "")){
					/* 按下按钮,切换玩家*/
					if(result == 0){
						if (turn == 1){
							Chessboard[i][j] = 1;
							turn = 2;
						}
						else{
							Chessboard[i][j] = 2;
							turn = 1;
						}
					}
				}
			}
		}
	}

pve():
PVE对抗函数,逻辑与PVP相似,只是在AI回合时会调用AITurn()进行落子。

	void pve(){
		int result = check();
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				if (Chessboard [i][j] == 1)
					GUI.Button (new Rect (5 + 60 * i, 20 + 60*j, 60, 60), img1);
				if (Chessboard [i][j] == 2)
					GUI.Button (new Rect (5 + 60 * i, 20 + 60*j, 60, 60), img2);
				if (GUI.Button (new Rect (5 + 60 * i, 20 + 60*j, 60, 60), "")){
					/* 按下按钮,切换玩家*/
					if(result == 0){
						if (turn == 1){
							Chessboard[i][j] = 1;
							turn = 2;
						}
						else{
							ai_turn();
							turn = 1;
						}
					}
				}
			}
		}
	}

AITurn():
AI落子函数,在这个函数中AI会比较简单的选择局部最优的选择,选择逻辑如下。

  1. 能够获胜则直接落子
    对每个空白格进行检测,判断落子后是否可以获胜,若可以,则直接落子。

  2. 若不能获胜,且玩家已将军,则进行防守
    判断玩家是否将军,若将军,则记录应该防守的位置
    若所有空白格检测完毕后,不能获胜,则选择记下的位置进行落子。

  3. 如果既不能获胜,玩家也没有将军,则随机选择一个空白格
    在遍历时加入一个变量count,记录空白格的数量;一个多维数组ept[][],来记录空白格的位置

	void ai_turn() {
		//如果没有在运行中则不进行下一步
		if (check() != 0)
			return;
		//使用交错数组存储空白位置
		int[][] ept = new int[9][] {new int [2], new int [2],new int [2],new int [2],new int [2],new int [2],new int [2],new int [2],new int [2]};
		//分别代表将军的横纵zuobiao
		int lose_x = -1;
		int lose_y = -1;
		int count = 0;
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				if (Chessboard [i][j] == 0) {
					//判断是否能赢
					Chessboard [i][j] = 2;
					if (check () == 2)
						return;

					//判断是否被将军
					Chessboard [i][j] = 1;
					if (check () == 1) {
						lose_x = i;
						lose_y = j;
					}
					//恢复chessboard的值
					Chessboard [i][j] = 0;
					ept[i,j] = count;
					count++;
				}
			}
		}
		//若将军则落子
		if(lose_x != -1)
			Chessboard[lose_x][lose_y] = 2;
			return;

		//无法直接获胜也没被将军则随机在空白格落子
		int rd = (int)Random.Range(0, count);
		int i1 = ept[rd][0];
    	int j1 = ept[rd][1];
   		Chessboard[i1][j1] = 2; 

audiosource
设置AudioSource组件
首先选择Add component
在这里插入图片描述

而后选择Audio Sourse
在这里插入图片描述

最后选择素材就ok了~在这里插入图片描述

private void Awake() {
		audioSource= this.gameObject.GetComponent<AudioSource>();
		audioSource.loop = false;
		audioSource.volume = 1.0f;
		audioSource.clip = audio;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值