前提・実現したいこと
現在Unityを使ってBlokusというボードゲームを製作しております。
Blokusというゲームについて
盤面、盤面上のピースはタイルマップによって描画されています。画像右側の手持ちのピースはスプライトによって描画されています。画像の通り、手持ちのピースをドラッグして盤面にゲームルール(同じ色の斜めにしか置けずとなりに同じ色があったら置けない)の通りに設置するところまでは実装できました。
ここで本題ですが、あるプレイヤーの番になったときに盤面でこれ以上置けるところがない場合、そのプレイヤーのターンを強制的にパスさせることや、置ける場所がないためゲーム終了、といった具合に詰みの状態の判定方法がこの先必須となっております。ただ、21個のピースはすべて形が違く、回転もできるように実装したので、恥ずかしながら詰みの判定の実装方法がよくわからず困っております。実装の方針やアイデアなどをご教授いただければ幸いです。
発生している問題・エラーメッセージ
詰みの状態の判定方法を知りたい
現在実装しているピース設置時の判定
C#
1public void onDragEnd() 2 { 3 Debug.Log("EndDrag"); 4 if (isPutable()) 5 { 6 Debug.Log("Putable!"); 7 8 switch (gameManager_Script.turn) 9 { 10 case "red": 11 drawTile = redTile; 12 13 break; 14 case "blue": 15 drawTile = blueTile; 16 17 break; 18 19 case "green": 20 drawTile = greenTile; 21 22 break; 23 24 case "yellow": 25 drawTile = yellowTile; 26 break; 27 } 28 29 30 for (int i = 0; i < this.transform.childCount; i++) //親オブジェクトが持っている子オブジェクトの数 回 31 { 32 position = this.transform.GetChild(i).gameObject.transform.position; //子オブジェクトのポジションを代入 33 //position = transform.localPosition; //このスクリプトがアタッチされたオブジェクトのローカル座標 34 Vector3Int cellPos = tileManager.tilemap.WorldToCell(position); //positionと被っているタイルのベクトル取得 35 tileManager.drawTile(cellPos, drawTile); //tileManager.csのメソッド 36 //Destroy(this.gameObject); //gameobject削除 37 38 } 39 gameObject.SetActive(false); 40 switch (gameManager_Script.turn) 41 { 42 case "red": 43 redPlayer_Script.SetIsUsed(GetNumberOfArray(), true); 44 45 46 gameManager_Script.turn = "blue"; 47 break; 48 case "blue": 49 bluePlayer_Script.SetIsUsed(GetNumberOfArray(), true); 50 51 52 gameManager_Script.turn = "green"; 53 break; 54 case "green": 55 greenPlayer_Script.SetIsUsed(GetNumberOfArray(), true); 56 57 58 gameManager_Script.turn = "yellow"; 59 break; 60 61 case "yellow": 62 yellowPlayer_Script.SetIsUsed(GetNumberOfArray(), true); 63 64 65 66 gameManager_Script.turn = "red"; 67 break; 68 } 69 gameManager_Script.turnChanged = true; 70 }else //置けなかったら 71 { 72 this.transform.position = gameManager_Script.prefabPos[GetNumberOfArray()] + tileManager.tilemap.transform.position; 73 } 74 75 uiManager_Script.rotateRightBtn.gameObject.SetActive(false); 76 uiManager_Script.rotateLeftBtn.gameObject.SetActive(false); 77 } 78 79public bool isPutable() 80 { 81 int childAmount = this.transform.childCount; 82 int decider = childAmount; 83 Vector3Int[] positions = new Vector3Int[childAmount]; 84 for(int i = 0; i < childAmount; i++) 85 { 86 position = this.transform.GetChild(i).gameObject.transform.position; //子オブジェクトのポジションを代入 87 positions[i] = tileManager.tilemap.WorldToCell(position); //positionと被っているタイルのベクトルを配列に格納 88 } 89 90 for(int i = 0; i < childAmount; i++) 91 { 92 if (isPutbableChecker(positions[i]) == true) 93 { 94 decider -= 1; 95 } 96 //一つ一つのタイルについて回りを調べ 97 //おけるようならchildAmount - 1 をしていく 98 //最終的にchildAmountが0になったらtrueをreturnする 99 } 100 101 if(decider == 0 && isSlantingSame == true) 102 { 103 Debug.Log(isSlantingSame); 104 isSlantingSame = false; 105 return true; 106 107 } 108 109 return false; 110 } 111 112 public bool isPutbableChecker(Vector3Int pos) //一つのタイルについておくことができるかを確認 第一引数:おこうとしているタイルのpos 113 { 114 if (tileManager.tilemap.GetSprite(pos) == sprite_background) //posの位置のタイルのスプライトが背景のだったら 115 { 116 Debug.Log("背景だった"); 117 if(tileManager.tilemap.GetSprite(pos + up) != this.transform.GetChild(0).gameObject.GetComponent<SpriteRenderer>().sprite //posの一つ上のタイルがおこうとしているタイルと違うなら 118 && tileManager.tilemap.GetSprite(pos + down) != this.transform.GetChild(0).gameObject.GetComponent<SpriteRenderer>().sprite 119 && tileManager.tilemap.GetSprite(pos + right) != this.transform.GetChild(0).gameObject.GetComponent<SpriteRenderer>().sprite 120 && tileManager.tilemap.GetSprite(pos + left) != this.transform.GetChild(0).gameObject.GetComponent<SpriteRenderer>().sprite 121 ) //上下左右に同じスプライトのタイルがなかったら進む 122 { 123 Debug.Log("隣に同じタイルはなかった"); 124 if(tileManager.tilemap.GetSprite(pos + up + right) == this.transform.GetChild(0).gameObject.GetComponent<SpriteRenderer>().sprite 125 || tileManager.tilemap.GetSprite(pos + up + left) == this.transform.GetChild(0).gameObject.GetComponent<SpriteRenderer>().sprite 126 || tileManager.tilemap.GetSprite(pos + down + right) == this.transform.GetChild(0).gameObject.GetComponent<SpriteRenderer>().sprite 127 || tileManager.tilemap.GetSprite(pos + down + left) == this.transform.GetChild(0).gameObject.GetComponent<SpriteRenderer>().sprite 128 ) //ななめにあるスプライトが同じなら進む 129 { 130 Debug.Log("斜めに同じスプライトがあった"); 131 isSlantingSame = true; 132 } 133 134 135 return true; //斜めは関係なしに上下左右に同じスプライトがないところまで進めたらtrueを返す 136 } 137 } 138 139 140 return false; //条件を満たさなかった 141 }
試したこと
パスするボタンを設置してユーザーにパスさせるということも考えましたが、それでは、パソコンでやるメリットが減ってしまったり、これから先敵AIを作成する際に詰まると思いやめました。
補足情報(FW/ツールのバージョンなど)
Unityのバージョンは2018.3.0f2です。
回答2件
あなたの回答
tips
プレビュー