• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

samsmithnz / PuzzleSolver / 4219702133

pending completion
4219702133

Pull #42

github

GitHub
Merge 7f70bc7b1 into d250e254c
Pull Request #42: Path finding increase

867 of 920 branches covered (94.24%)

Branch coverage included in aggregate %.

83 of 83 new or added lines in 3 files covered. (100.0%)

1398 of 1418 relevant lines covered (98.59%)

1074771.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.48
/src/PuzzleSolver/Board.cs
1
using PuzzleSolver.Images;
2
using PuzzleSolver.Map;
3
using SixLabors.ImageSharp.PixelFormats;
4
using System;
5
using System.Collections.Generic;
6
using System.Diagnostics;
7
using System.Linq;
8
using System.Numerics;
9

10
namespace PuzzleSolver
11
{
12
    public class Board
13
    {
14
        public string[,] Map { get; set; }
48✔
15

16
        //Color Palette
17
        public List<Rgb24> ColorPalette { get; set; }
8✔
18

19
        //Pieces
20
        public Vector2 UnsortedPiecesLocation { get; set; }
14✔
21
        public Queue<Piece> UnsortedPieces { get; set; }
62✔
22
        public List<Piece> SortedPieces { get; set; }
26✔
23
        public List<SortedDropZone> SortedDropZones { get; set; }
77✔
24

25
        //Characters
26
        public Robot Robot { get; set; }
152✔
27

28
        //Constructor
29
        public Board(string[,] map,
4✔
30
            Vector2 unsortedPiecesLocation,
4✔
31
            List<Rgb24> colorPalette,
4✔
32
            List<Piece> unsortedPieceList,
4✔
33
            List<SortedDropZone> sortedDropZones,
4✔
34
            Robot robot)
4✔
35
        {
4✔
36
            Map = map;
4✔
37
            UnsortedPiecesLocation = unsortedPiecesLocation;
4✔
38
            ColorPalette = colorPalette;
4✔
39
            UnsortedPieces = new Queue<Piece>();
4✔
40
            ImageColorGroups imageProcessing = new ImageColorGroups(ColorPalette);
4✔
41
            for (int i = 0; i < unsortedPieceList.Count; i++)
52✔
42
            {
22✔
43
                Piece piece = unsortedPieceList[i];
22✔
44
                piece.ImageStats = imageProcessing.ProcessStatsForImage(null, piece.Image);
22✔
45
                UnsortedPieces.Enqueue(piece);
22✔
46
            }
22✔
47
            SortedDropZones = sortedDropZones;
4✔
48
            SortedPieces = new List<Piece>();
4✔
49
            Robot = robot;
4✔
50
        }
4✔
51

52
        //Function to calculate the robot moves
53
        public Queue<RobotAction> RunRobot()
54
        {
2✔
55
            Queue<RobotAction> results = new Queue<RobotAction>();
2✔
56

57
            //Get the pickup location
58
            Vector2 PickUpLocation = UnsortedPiecesLocation;
2✔
59
            if (UnsortedPiecesLocation.Y > 0)
2✔
60
            {
2✔
61
                PickUpLocation = new Vector2(UnsortedPiecesLocation.X, UnsortedPiecesLocation.Y - 1);
2✔
62
            }
2✔
63
            Vector2 currentRobotLocation = Robot.Location;
2✔
64

65
            //Loop through the queue of unsorted pieces
66
            while (UnsortedPieces.Count > 0)
16✔
67
            {
14✔
68
                RobotAction robotAction = new RobotAction();
14✔
69

70
                // Move to unsorted pile
71
                robotAction.RobotPickupStartingLocation = currentRobotLocation;
14✔
72
                if (currentRobotLocation != PickUpLocation)
14✔
73
                {
12✔
74
                    PathFindingResult pathFindingResultForPickup = PathFinding.FindPath(Map, currentRobotLocation, PickUpLocation);
12✔
75
                    if (pathFindingResultForPickup != null && pathFindingResultForPickup.Path.Any())
12!
76
                    {
12✔
77
                        //Move robot
78
                        robotAction.PathToPickup = pathFindingResultForPickup;
12✔
79
                        currentRobotLocation = pathFindingResultForPickup.Path.Last();
12✔
80
                    }
12✔
81
                }
12✔
82
                robotAction.RobotPickupEndingLocation = currentRobotLocation;
14✔
83

84
                // Pickup an unsorted piece from the unsorted pile
85
                Robot.Piece = UnsortedPieces.Dequeue();
14✔
86
                robotAction.PieceId = Robot.Piece.Id;
14✔
87
                robotAction.PickupAction = new ObjectInteraction()
14✔
88
                {
14✔
89
                    Location = PickUpLocation
14✔
90
                };
14✔
91

92
                // Process the unsorted piece to work out where it goes
93
                Vector2? destinationLocation = null;
14✔
94
                foreach (SortedDropZone sortedDropZone in SortedDropZones)
186✔
95
                {
72✔
96
                    if (sortedDropZone.Color == Robot.Piece.ImageStats.TopColorGroupColor)
72✔
97
                    {
14✔
98
                        destinationLocation = sortedDropZone.Location;
14✔
99
                    }
14✔
100
                }
72✔
101

102
                //Get the best adjacent location to the destination
103
                Vector2? pathDestinationLocation = destinationLocation;
14✔
104
                if (destinationLocation != null)
14✔
105
                {
14✔
106
                    Vector2? adjacentLocation = GetAdjacentLocation((Vector2)destinationLocation, Map, SortedDropZones);
14✔
107
                    if (adjacentLocation != null)
14✔
108
                    {
14✔
109
                        pathDestinationLocation = (Vector2)adjacentLocation;
14✔
110
                    }
14✔
111
                }
14✔
112

113
                // Move the sorted piece to the correct pile
114
                robotAction.RobotDropoffStartingLocation = currentRobotLocation;
14✔
115
                if (destinationLocation != null && pathDestinationLocation != null)
14!
116
                {
14✔
117

118
                    //now find the path
119
                    PathFindingResult pathFindingResultForDropoff = PathFinding.FindPath(Map, currentRobotLocation, (Vector2)pathDestinationLocation);
14✔
120
                    if (pathFindingResultForDropoff != null && pathFindingResultForDropoff.Path.Any())
14!
121
                    {
14✔
122
                        //Move robot
123
                        robotAction.PathToDropoff = pathFindingResultForDropoff;
14✔
124
                        robotAction.DropoffAction = new ObjectInteraction()
14✔
125
                        {
14✔
126
                            Location = (Vector2)destinationLocation
14✔
127
                        };
14✔
128
                        //Move the piece from the robot to the sorted pile
129
                        Robot.Piece.Location = robotAction.DropoffAction.Location;
14✔
130
                        SortedPieces.Add(Robot.Piece);
14✔
131
                        foreach (SortedDropZone sortedDropZone in SortedDropZones)
96✔
132
                        {
34✔
133
                            if (sortedDropZone.Location == destinationLocation)
34!
134
                            {
14✔
135
                                sortedDropZone.Count++;
14✔
136
                                break;
14✔
137
                            }
138
                        }
20✔
139
                        Robot.Piece = null;
14✔
140
                        robotAction.DropoffPieceCount = GetPieceCount(robotAction.DropoffAction.Location);
14✔
141
                        currentRobotLocation = pathFindingResultForDropoff.Path.Last();
14✔
142
                    }
14✔
143
                }
14✔
144
                robotAction.RobotDropoffEndingLocation = currentRobotLocation;
14✔
145

146
                // Add to queue
147
                results.Enqueue(robotAction);
14✔
148
            }
14✔
149

150
            //Add last action to return to the starting point
151
            RobotAction robotActionReset = new RobotAction();
2✔
152
            robotActionReset.RobotPickupStartingLocation = currentRobotLocation;
2✔
153
            if (currentRobotLocation != PickUpLocation)
2✔
154
            {
2✔
155
                PathFindingResult pathFindingResultForPickup = PathFinding.FindPath(Map, currentRobotLocation, PickUpLocation);
2✔
156
                if (pathFindingResultForPickup != null && pathFindingResultForPickup.Path.Any())
2!
157
                {
2✔
158
                    //Move robot
159
                    robotActionReset.PathToPickup = pathFindingResultForPickup;
2✔
160
                    currentRobotLocation = pathFindingResultForPickup.Path.Last();
2✔
161
                }
2✔
162
            }
2✔
163
            robotActionReset.RobotPickupEndingLocation = currentRobotLocation;
2✔
164
            results.Enqueue(robotActionReset);
2✔
165

166
            return results;
2✔
167
        }
2✔
168

169
        public int GetPieceCount(Vector2 dropOfflocation)
170
        {
16✔
171
            int pieceCount = 0;
16✔
172

173
            foreach (SortedDropZone sortedDropZone in SortedDropZones)
104✔
174
            {
36✔
175
                if (sortedDropZone.Location == dropOfflocation)
36✔
176
                {
16✔
177
                    pieceCount = sortedDropZone.Count;
16✔
178
                    break;
16✔
179
                }
180
            }
20✔
181

182
            return pieceCount;
16✔
183
        }
16✔
184

185
        private Vector2? GetAdjacentLocation(Vector2 destinationLocation, string[,] map, List<SortedDropZone> sortedDropZones)
186
        {
14✔
187
            Vector2? adjacentLocation = null;
14✔
188
            if (destinationLocation != null)
14✔
189
            {
14✔
190
                Vector2 topLocation = new Vector2((int)destinationLocation.X, (int)destinationLocation.Y + 1);
14✔
191
                Vector2 bottomLocation = new Vector2((int)destinationLocation.X, (int)destinationLocation.Y - 1);
14✔
192
                Vector2 rightLocation = new Vector2((int)destinationLocation.X + 1, (int)destinationLocation.Y);
14✔
193
                Vector2 leftLocation = new Vector2((int)destinationLocation.X - 1, (int)destinationLocation.Y);
14✔
194

195
                //Check if I can deliver from the top first
196
                if (CheckLocationIsValid(topLocation, map, sortedDropZones))
14✔
197
                {
4✔
198
                    return topLocation;
4✔
199
                }
200
                //Then check the bottom
201
                else if (CheckLocationIsValid(bottomLocation, map, sortedDropZones))
10✔
202
                {
7✔
203
                    return bottomLocation;
7✔
204
                }
205
                //Then check the right
206
                else if (CheckLocationIsValid(rightLocation, map, sortedDropZones))
3✔
207
                {
2✔
208
                    return rightLocation;
2✔
209
                }
210
                //Finally check the left
211
                else if (CheckLocationIsValid(leftLocation, map, sortedDropZones))
1!
212
                {
1✔
213
                    return leftLocation;
1✔
214
                }
215
                else
216
                {
×
217
                    return destinationLocation;
×
218
                }
219
                //if (topTile.X > 0 && topTile.Y > 0 &&
220
                //    topTile.X < map.GetUpperBound(0) &&
221
                //    topTile.Y < map.GetUpperBound(1) &&
222
                //    map[(int)topTile.X, (int)topTile.Y] == "" &&
223
                //    sortedDropZones.Find(d => d.Location == topTile) == null)
224
                //{
225
                //    return topTile;
226
                //}
227
                //else
228
                //{
229
                //    return destinationLocation;
230
                //}
231

232
                ////Get the adjacent tiles
233
                //List<Vector2> adjacentTiles = new List<Vector2>();
234
                //adjacentTiles.Add(new Vector2(destinationLocation.X - 1, destinationLocation.Y));
235
                //adjacentTiles.Add(new Vector2(destinationLocation.X + 1, destinationLocation.Y));
236
                //adjacentTiles.Add(new Vector2(destinationLocation.X, destinationLocation.Y - 1));
237
                //adjacentTiles.Add(new Vector2(destinationLocation.X, destinationLocation.Y + 1));
238

239
                ////Loop through the adjacent tiles and find the first one that is not a wall
240
                //foreach (Vector2 item in adjacentTiles)
241
                //{
242
                //    if ((int)item.X > 0 || (int)item.Y > 0 ||
243
                //        (int)item.X < map.GetUpperBound(0) ||
244
                //        (int)item.Y < map.GetUpperBound(1))
245
                //    {
246
                //        adjacentTile = item;
247
                //        break;
248
                //    }
249
                //}
250
            }
251
            return adjacentLocation;
252
        }
14✔
253

254
        private bool CheckLocationIsValid(Vector2 location, string[,] map, List<SortedDropZone> sortedDropZones)
255
        {
28✔
256
            if (location.X >= 0 &&
28✔
257
                location.Y >= 0 &&
28✔
258
                location.X <= map.GetUpperBound(0) &&
28✔
259
                location.Y <= map.GetUpperBound(1) &&
28✔
260
                map[(int)location.X, (int)location.Y] == "" &&
28✔
261
                sortedDropZones.Find(d => d.Location == location) == null)
135✔
262
            {
14✔
263
                return true;
14✔
264
            }
265
            else
266
            {
14✔
267
                return false;
14✔
268
            }
269
        }       
28✔
270

271
    }
272
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc