public park Clone() { park clone = new park(); clone.width = width; clone.height = height; clone.count = count; clone.pos = new int[count]; clone.alignment = new int[count]; clone.length = new int[count]; clone.occupancy = new int[width * height]; for (int i = 0; i < count; i++) { clone.pos[i] = pos[i]; clone.alignment[i] = alignment[i]; clone.length[i] = length[i]; } for (int i = 0; i < width * height; i++) { clone.occupancy[i] = occupancy[i]; } return(clone); }
static public park makeMove2(park p, int car, int dir) { // clearing old car occupancy if (p.alignment[car] == 0) { for (int i = 0; i < p.length[car]; i++) { p.occupancy[p.pos[car] + i] = 0; } p.pos[car] += dir; for (int i = 0; i < p.length[car]; i++) { p.occupancy[p.pos[car] + i] = car + 1; } } else { for (int i = 0; i < p.length[car]; i++) { p.occupancy[p.pos[car] + i * p.width] = 0; } p.pos[car] += dir * p.width; for (int i = 0; i < p.length[car]; i++) { p.occupancy[p.pos[car] + i * p.width] = car + 1; } } return(p); }
static public bool checkMove(park p, int car, int dir) { movesList l = parkLogic.generateMoves2(p); for (int i = 0; i < l.count; i++) { if ((car == l.car_ind[i]) && (dir == l.dir[i])) { return(true); } } return(false); }
static public movesList generateMoves2(park p) { bool ONEBLOCK_MOVES_ONLY = false; movesList L = new movesList(); for (int i = 0; i < p.count; i++) { if (p.alignment[i] == 0) { // horizontal car for (int k = 0; k < p.width; k++) { if ((p.pos[i] % p.width) + p.length[i] + k < p.width) { if (p.occupancy[p.pos[i] + p.length[i] + k] == 0) { int j = L.count; L.car_ind[j] = i; L.dir[j] = 1 + k; L.count++; if (ONEBLOCK_MOVES_ONLY) { if (Math.Abs(L.dir [j]) > 1) { L.count--; } } } else { break; } } else { break; } } for (int k = 0; k > -p.width; k--) { if ((p.pos[i] % p.width) + k > 0) { if (p.occupancy[p.pos[i] - 1 + k] == 0) { int j = L.count; L.car_ind[j] = i; L.dir[j] = -1 + k; L.count++; if (ONEBLOCK_MOVES_ONLY) { if (Math.Abs(L.dir[j]) > 1) { L.count--; } } } else { break; } } else { break; } } } else { // vertical car for (int k = 0; k < p.height; k++) { if (p.pos[i] + p.length[i] * (p.width) + k * p.width < (p.width * p.height)) { if (p.occupancy[p.pos[i] + p.length[i] * (p.width) + k * p.width] == 0) { int j = L.count; L.car_ind[j] = i; L.dir[j] = 1 + k; L.count++; if (ONEBLOCK_MOVES_ONLY) { if (Math.Abs(L.dir[j]) > 1) { L.count--; } } } else { break; } } else { break; } } for (int k = 0; k > -p.height; k--) { if (p.pos[i] + k * p.width > p.width - 1) { if (p.occupancy[p.pos[i] - p.width + k * p.width] == 0) { int j = L.count; L.car_ind[j] = i; L.dir[j] = -1 + k; L.count++; if (ONEBLOCK_MOVES_ONLY) { if (Math.Abs(L.dir[j]) > 1) { L.count--; } } } else { break; } } else { break; } } } } return(L); }
static public park generatePark(int w, int h, int c) { park res = new park(); Random R = new Random(); res.width = w; res.height = h; res.pos = new int[c]; res.alignment = new int[c]; res.length = new int[c]; res.occupancy = new int[w * h]; // creating primary car (car #1) res.alignment[0] = 0; res.length[0] = 2; res.pos[0] = w * 2; res.occupancy[w * 2 + 1] = res.occupancy[w * 2] = 1; res.count++; int iters = 0; int MAX_iters = 100; int lower_limit = w * 2; int upper_limit = w * 3 - 1; // creating other cars while (res.count < c) { int pos = R.Next(w * h); int alignment = R.Next(2); int length = 2 + R.Next(2); if (alignment == 0) { if (pos <= upper_limit) { if (pos >= lower_limit) { continue; // prevent horizontal blocks within [lower_limit, upper_limit] } } } bool valid_pos = true; int current_pos = pos; for (int i = 0; i < length; i++) { if ((alignment == 0) && (w - (pos % w) < length)) { valid_pos = false; break; } // checking if horizontal cars aren't too close to the right edge if (current_pos >= res.occupancy.Length) { valid_pos = false; break; } if (res.occupancy[current_pos] > 0) { valid_pos = false; break; } if (alignment == 1) { current_pos += w; } else { current_pos++; } } if (valid_pos) { int j = res.count++; res.pos[j] = pos; res.alignment[j] = alignment; res.length[j] = length; current_pos = pos; for (int i = 0; i < length; i++) { res.occupancy[current_pos] = j + 1; if (alignment == 1) { current_pos += w; } else { current_pos++; } } } iters++; if (iters > MAX_iters) { // MessageBox.Show("Unable to position required number of cars within park space!", "Error"); break; } } return(res); }
static public searchResults SpaceSearch2(Queue <park> current) { Queue <park> neighbours = new Queue <park>(); Queue <park> solutions = new Queue <park>(); Dictionary <int, int> D = new Dictionary <int, int>(); int distance_counter = 0; bool has_nodes = false; park lastNode = null; while (current.Count > 0) // exit loop when current nodes are empty (graph is fully searched) { neighbours = new Queue <park>(); has_nodes = false; while (current.Count > 0) // iterating through current nodes { park node = current.Dequeue(); int node_hash = node.GetHashCode(); if (D.ContainsKey(node_hash)) { continue; // bail if node was searched before } lastNode = node; has_nodes = true; D.Add(node_hash, distance_counter); if (node.pos[0] == (node.width * 3 - 2)) { solutions.Enqueue(node); } // end of state checking movesList L = parkLogic.generateMoves2(node); for (int i = 0; i < L.count; i++) { park clone = node.Clone(); park next_node = parkLogic.makeMove2(clone, L.car_ind[i], L.dir[i]); neighbours.Enqueue(next_node); if (D.Count > 20000) { if (false) { // state graph too large, bailing ... searchResults r = new searchResults(); r.states = -1; r.solutions = solutions; return(r); } } } } current = neighbours; if (has_nodes) { distance_counter++; } } searchResults r2 = new searchResults(); r2.states = D.Count; r2.solutions = solutions; r2.lastNode = lastNode; r2.distance_counter = distance_counter; r2.D = D; return(r2); }