Robert
Robert

Reputation: 6226

Game Board Algorithm

I get a dictionary of a bunch of game pieces with the three properties:

Address = Location in a game piece
Offset = Offset from the left of where the game piece is connected
Width = Width of the game piece (One, Two or Three wide)

The gameboard itself is 6 wide and 5 high (A total of 30 possible positions)

25 26 27 28 29 30
19 20 21 22 23 24
13 14 15 16 17 18
07 08 09 10 11 12
01 02 03 04 05 06

Each number is the corresponding address on the board.

I would like to be able to add all these pieces to a collection like ObservableCollection<GameRow> GameRows where

public class GameRow
{
    public ObservableCollection<GamePiece> Row { get; set; }

    public GameRow(ArrayList<GamePiece> gamePieces)
    {
        Row = new ObservableCollection<GamePiece>();

        foreach (GamePiece gamePiece in gamePieces)
        {
            Row.Add(gamePiece);
        }
    }
}

and

public class GamePiece
{
    public string Width { get; set; }  
    public string Color { get; set; }
    public int Address {get; set}
}

I also need to create a gamepiece for any unused area on the board that is a single width and a color gray (the other game pieces should have a color of yellow).

Here is what the game pieces look like:

One wide:
X (offset = 0)

Two Wide:
0X (offset = 1)

Three Wide
0X0 (offset = 1)

X = What is reported as the address for that piece
0 = The empty space it occupies.

I'm trying to come up with a way to parse that dictionary of game pieces I receive into GameRows.

Example:

Lets say I get three pieces. {Address=2, Width = 1, Offset = 0},{Address=12, Width = 2, Offset = 1}, {Address=23, Width = 3, Offset = 1}

I know the address 2 piece will be on the first row and take position 02 and the rest of the game pieces for that board should be blank gamepieces with a width of 1. The piece that is address 12 will be in the second row and take positions 11 and 12. The piece that is address 23 will be in the 4th row and take positions 22, 23, 24. The ObservableCollection GameRows will have five GameRow objects in it. The GameRow object for row 4 will contain 4 objects in the Row collection. The first 3 being blank pieces will be {Width = 1, Color = Gray} and the last piece will be a {Width = 3, Color = Yellow}

Upvotes: 4

Views: 2270

Answers (2)

Ray Henry
Ray Henry

Reputation: 905

Basically create a board with the empty, or Gray, pieces. Process the dictionary, removing the gray pieces that are no longer needed and adding the yellow pieces. Then process the board row by row to return an array of rows. Unit tests are included for your test cases. Modify ROWS and COLS to accomodate any size board.

    public class UnitTest1
{
    int ROWS = 5;
    int COLS = 6;

    public class GamePiece
    {
        public int Width;
        public string Color;
        public int Address;
        public int Offset;

    }
    public class GameRow
    {
        public List<GamePiece> Row = new List<GamePiece>();

    }

    private void initializeBoard(GamePiece[] board) {
        for(int i = 1; i < board.Length; i++) board[i] = EmptyPiece(i);
    }

    private GamePiece EmptyPiece(int address)
    {
        return new GamePiece
        {
            Address = address,
            Width = 1,
            Color = "Gray",
            Offset = 0
        };
    }

    private int ComputeRow(int address)
    {
        return ((address - 1) / COLS);
    }

    private void processDictionary(GamePiece[] board, Dictionary<int,GamePiece> d)
    {
        foreach (var piece in d.Values)
        {
            for (int i = 0; i < piece.Width; i++)
            {
                board[piece.Address - piece.Offset + i] = null;
            }
            board[piece.Address] = piece;
        }
    }

    private GameRow[] convertBoardtoRows(GamePiece[] board)
    {
        var rows = new GameRow[ROWS];
        for (int i = 0; i < rows.Length; i++) rows[i] = new GameRow();
        for (int i = 1; i < board.Length; i++)
        {
            if (board[i] != null)
            {
                rows[ComputeRow(i)].Row.Add(board[i]);
            }
        }
        return rows;
    }

    public GameRow[] ProcessPieces(Dictionary<int, GamePiece> dictionary)
    {
        GamePiece[] board = new GamePiece[ROWS*COLS+1];
        initializeBoard(board);
        processDictionary(board, dictionary);
        return convertBoardtoRows(board);
    }
    [TestMethod]
    public void TestMethod1()
    {
        var dictionary = new Dictionary<int, GamePiece>();
        dictionary.Add(1, new GamePiece { Address = 2, Width = 1, Offset = 0, Color = "Yellow" });
        dictionary.Add(2, new GamePiece { Address = 12, Width = 2, Offset = 1, Color = "Yellow" });
        dictionary.Add(3, new GamePiece { Address = 23, Width = 3, Offset = 1, Color = "Yellow" });

        var rows = ProcessPieces(dictionary);

        Assert.IsTrue(rows[0].Row.Count == 6);
        Assert.IsTrue(rows[0].Row.Where(p => p.Color == "Yellow").Count() == 1);
        Assert.IsTrue(rows[0].Row.Where(p => p.Color == "Gray").Count() == 5);
        var piece = rows[0].Row.Where(p => p.Color == "Yellow").First();
        Assert.IsTrue(piece.Address == 2);

        Assert.IsTrue(rows[1].Row.Count == 5);
        Assert.IsTrue(rows[1].Row.Where(p => p.Color == "Yellow").Count() == 1);
        Assert.IsTrue(rows[1].Row.Where(p => p.Color == "Gray").Count() == 4);
        Assert.IsTrue(rows[1].Row.Where(p => p.Address == 11).Count() == 0);
        piece = rows[1].Row.Where(p => p.Color == "Yellow").First();
        Assert.IsTrue(piece.Address == 12);

        Assert.IsTrue(rows[2].Row.Count == 6);
        Assert.IsTrue(rows[2].Row.Where(p => p.Color == "Yellow").Count() == 0);
        Assert.IsTrue(rows[2].Row.Where(p => p.Color == "Gray").Count() == 6);

        Assert.IsTrue(rows[3].Row.Count == 4);
        Assert.IsTrue(rows[3].Row.Where(p => p.Color == "Yellow").Count() == 1);
        Assert.IsTrue(rows[3].Row.Where(p => p.Color == "Gray").Count() == 3);

        Assert.IsTrue(rows[4].Row.Count == 6);
        Assert.IsTrue(rows[4].Row.Where(p => p.Color == "Yellow").Count() == 0);
        Assert.IsTrue(rows[4].Row.Where(p => p.Color == "Gray").Count() == 6);
    }
}

Upvotes: 2

Hobo Spider
Hobo Spider

Reputation: 280

I'm including Offset to the GamePiece class for the sake of brevity.

public class GamePiece
{
    public string Width { get; set; }  
    public string Color { get; set; }
    public int Address {get; set}
    public int Offset {get; set }
}

I'm also leaving out the details of function CreateOccupiedPiece referenced below:

var d = new Dictionary<int, string>();

int rowWidth;
int curCol;
int address;
string value;
GamePiece curPiece;

for (int rowNum=1; rowNum<=6; rowNum++)
{
   rowWidth = 0;
   curCol = 1;
   while (rowWidth < 6) && (curCol <=6)
   {
      address = 6*(RowNum-1) + (curCol)

      if (d.TryGetValue(address, out value))
      {
         // CreateOccupiedPiece returns New Populated GamePiece
         curPiece = CreateOccupiedPiece(value);

         // Offset value will be tell us how many previous GamePieces to delete
         // as well as how much to adjust our rowWidth             
         if (curPiece.Offset > 0)
         {
            list.RemoveRange((curCol - curPiece.Offset - 1), curPiece.Offset);
            rowWidth = rowWidth - curPiece.Offset;
         }            
      }
      else
      {
         // Just add an empty space (gray, 1-width piece, at location)
         curPiece = new GamePiece("Gray", "1", address); 
      } 
      Row.Add(curPiece);
      curCol++;
      rowWidth = rowWidth + Convert.ToInt32(curPiece.Width);
   }
}

Upvotes: 0

Related Questions