MENU

【C#】ペントミノ2Dパズルを解く(4)棚クラスを作る

今回は棚クラスです。クラスの概要はこの連載の「(1)はじめに」を参考にしてください。

・クラス宣言

クラスの名前は "Shelf" です。

internal class Shelf

・プロパティ:名前 Name

棚の名前です。中に入れる部品の名前をそのまま使います。解の表示で使用します。

public string Name { get; private set; }

・プロパティ:表示色 Color

解の表示で背景色として使用します。

public Color Color { get; private set; }

・プロパティ:部品集 Pieces

部品コレクション。回転や裏返しをしたものをあらかじめ入れておきます。

public List<Piece> Pieces { get; private set; }

・プロパティ:ボードに置いた部品 SelectedPiece

部品集から部品を選択して箱に置いたときの部品と置いた座標。選択していないときはともにNothing

Public Piece? PlacedPiece;     //ボードに置いた部品
public Coord? PlacedCoord;     //PlacedPieceを置いた場所

・初期化

引数のうち name と color はそのままプロパティに、expressionは部品集(Pieces)をつくるための文字列です。

public Shelf(string name, Color color, string expression)
{
    Name = name;
    Color = color;
    Pieces = new List<Piece>();
    PlacedPiece = null; 
    PlacedCoord = null;
    Piece piece = new Piece(expression);

    for(int i = 0; i <= 7; i++)
    {
        Piece p = piece.Clone();
        if (i > 3)
        {
            p.HorizontalReverse();
        }
        p.AntiClockWiseRotate(i % 4);
        p.ShiftToOrigin();
        if (Pieces.Any(s => s == p) == false)
        {
            Pieces.Add(p);
        }
        //シノニム除外("F","N","L","Y","P"のどれかで設定)
        if (Name == "F" && i == 1)
        {
            break;  
        }
    }
}

//=====(例)=====
Piece piece = New Piece("RDRdL") ;       //部品"F"を作成します

コード中の "シノニム" とはボード全体を180度回転させたり裏返したりするとぴったり重なる解となるものをいいます。パズルのルールではシノニムは同一解となります。シノニムを除外するにはどうしたらいいでしょうか?


図では8通りの解のうち6通りが シノニム となってしまいますが、部品集に原因となる6個を除外した2個(図の①と②)のみを登録すればシノニムはできなくなります。コードの「シノニム除外」のところで部品"F"について①と②以外が部品集に登録されるのを防いでいます。あとはどのように部品を配置してもシノニムができる心配はありません。
なおこの処理ができるのは8種類の向きがある部品("F", "N", "L", "Y", "P")に限ります。


以上が「棚クラス」です。クラス全体のソースは以下のとおりです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ペントミノソルバー2D
{
    internal class Shelf
    {
    //********************************************
    //*          Shelf  (部品棚クラス) 
    //********************************************

        public string Name { get; private set; }          //名前
        public Color Color { get; private set; }          //表示色    
        public List<Piece> Pieces { get; private set; }   //向きや裏返し別のコレクション(同じ形は含まない)

        public Piece? PlacedPiece;     //ボードに置いた部品
        public Coord? PlacedCoord;     //PlacedPieceを置いた場所

        public Shelf(string name, Color color, string expression)
        {
            Name = name;
            Color = color;
            Pieces = new List<Piece>();
            PlacedPiece = null; 
            PlacedCoord = null;
            Piece piece = new Piece(expression);

            for(int i = 0; i <= 7; i++)
            {
                Piece p = piece.Clone();
                if (i > 3)
                {
                    p.HorizontalReverse();
                }
                p.AntiClockWiseRotate(i % 4);
                p.ShiftToOrigin();
                if (Pieces.Any(s => s == p) == false)
                {
                    Pieces.Add(p);
                }
                //シノニム除外("F","N","L","Y","P"のどれかで設定)
                if (Name == "F" && i == 1)
                {
                    break;  
                }
            }
        }

     }
}

次は「箱クラス」です。