三目並べ(まるばつゲーム)を作成。Part3.ランダム位置に自動でマーク|Unityゲーム制作

Unity2Dで「三目並べ(まるばつゲーム)」を作成。Part3では自動でランダムにマークするAIを実装していきます。

はじめに

part1は下記から。

今回やる事

Part1ではUIとマークを付けるのを作成、Part2で交互にマークをセット、勝利判定を実装しました、Part3ではランダムなAIの実装をしていきます。(ランダムにマークするのでAIとは言えないですが、「自動でマークする相手」を分かりやすいようにAIとしています)

実装開始

はじめに、勝利した後もゲームが続くので勝利した場合はマークできないようにしてから、ランダムにマークするAIを実装します。

スクリプトの作成

下記は「ゲーム終了フラグ」と「マーク数をカウント」する部分です。スクリプトに追加しておきます。

    private bool isGameFinished;
    private int marksCount;

    public void OnButtonClick(Button btn)
    {
        if (isGameFinished == true) return;

        marksCount++;

        if (IsWinner(img.sprite))
        {
            Debug.Log(isPlayer ? "X Win" : "O Win");
            isGameFinished = true;
        }

        if (marksCount == 9)
        {
            Debug.Log("Draw");
            isGameFinished = true;
            return;
        }
    }

ランダムにマークする

次にランダムにマークするのを実装します。下記スクリプトがランダムにマークする部分のスクリプトです。Nomarksにマークされていない場所を格納して、空き場所をランダムに選択してマークします。

    private List<int> Nomarks = new List<int>();

    private void RandomChoice()
    {
        Nomarks.Clear();
        for (int i = 0; i < buttons.Length; i++)
        {
            if (buttons[i].interactable == true)
                Nomarks.Add(i);
        }

        int RandomIndex = Nomarks[Random.Range(0, Nomarks.Count)];
        Button button = buttons[RandomIndex];
        OnButtonClick(button);

    }

最終的な全体のスクリプトは下記になります。

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameManager : MonoBehaviour
{
    [SerializeField] private Sprite spriteX;
    [SerializeField] private Sprite spriteO;
    [SerializeField] private Color colorX;
    [SerializeField] private Color colorO;

    [SerializeField] private Button[] buttons;
    [SerializeField] private bool isAImode;
    [SerializeField] private bool isAIplayer;

    private bool isPlayer;
    private bool isGameFinished;
    private int marksCount;
    private List<int> Nomarks = new List<int>();

    private void Awake()
    {
        isPlayer = true;
        isGameFinished = false;
        marksCount = 0;
    }
    private void Start()
    {
        if (isAImode && IsAIplay())
            RandomChoice();
    }
    public void OnButtonClick(Button btn)
    {
        if (isGameFinished == true) return;

        Image img = btn.GetComponent<Image>();
        img.sprite = isPlayer ? spriteX : spriteO;
        img.color = isPlayer ? colorX : colorO;

        btn.interactable = false;
        marksCount++;

        if (IsWinner(img.sprite))
        {
            Debug.Log(isPlayer ? "X Win" : "O Win");
            isGameFinished = true;
        }

        if (marksCount == 9)
        {
            Debug.Log("Draw");
            isGameFinished = true;
            return;
        }

        isPlayer = !isPlayer;

        if (isAImode && IsAIplay())
            RandomChoice();
    }
    private bool IsAIplay()
    {
        return (isPlayer && isAIplayer) || (!isPlayer && !isAIplayer);
    }

    private void RandomChoice()
    {
        Nomarks.Clear();
        for (int i = 0; i < buttons.Length; i++)
        {
            if (buttons[i].interactable == true)
                Nomarks.Add(i);
        }

        int RandomIndex = Nomarks[Random.Range(0, Nomarks.Count)];
        Button button = buttons[RandomIndex];
        OnButtonClick(button);

    }

    private bool IsWinner(Sprite sprite)
    {

        if (IsMatched(0, 1, 2, sprite)
            || IsMatched(3, 4, 5, sprite)
            || IsMatched(6, 7, 8, sprite)
            || IsMatched(0, 3, 6, sprite)
            || IsMatched(1, 4, 7, sprite)
            || IsMatched(2, 5, 8, sprite)
            || IsMatched(0, 4, 8, sprite)
            || IsMatched(6, 4, 2, sprite))
        {
            return true;
        }
        return false;
    }

    private bool IsMatched(int i, int j, int k, Sprite sprite)
    {
        Image img1 = buttons[i].GetComponent<Image>();
        Image img2 = buttons[j].GetComponent<Image>();
        Image img3 = buttons[k].GetComponent<Image>();

        bool matched = (img1.sprite == sprite
                    && img2.sprite == sprite
                    && img3.sprite == sprite);

        return matched;
    }
}

「isAImode」にチェックを入れるとランダムにマークするモードになります。isAIplayerで先手か、後手かをセットできます。下記のようにセットすると自分が先手、AIが後手です。

実行すると下記のような感じになります。

ランダムにマークするので、一人対戦モードの相手が弱いという感じですね。

タイトルとURLをコピーしました