// // TileModel.swift // assign3 // // Created by Jason Kim on 4/7/22. // import Foundation struct Tile: Equatable { var val : Int var id : Int var row: Int // recommended var col: Int // recommended } struct Score: Hashable { var score: Int var time: Date func hash(into hasher: inout Hasher) { hasher.combine(time) } init(score: Int, time: Date) { self.score = score self.time = time } } enum Tdirection { //find how to make an enum case left case right case up case down } class TTriples: ObservableObject { @Published var board: [[Tile?]] = [] @Published var score: Int = 0 var seededGenerator: SeededGenerator var tile = Tile(val: 0, id: 0, row: 0, col: 0) @Published var scores:[Score] = [Score(score: 300, time: Date.now), Score(score: 400, time: Date.now)] init(){ board = [[Tile(val: 0, id: 0, row: 0, col: 0), Tile(val: 0, id: 1, row: 0, col: 1), Tile(val: 0, id: 2, row: 0, col: 2), Tile(val: 0, id: 3, row: 0, col: 3)], [Tile(val: 0, id: 4, row: 1, col: 0), Tile(val: 0, id: 5, row: 1, col: 1), Tile(val: 0, id: 6, row: 1, col: 2),Tile(val: 0, id: 7, row: 1, col: 3)], [Tile(val: 0, id: 8, row: 2, col: 0), Tile(val: 0, id: 9, row: 2, col: 1), Tile(val: 0, id: 10, row: 2, col: 2), Tile(val: 0, id: 11, row: 2, col: 3)], [Tile(val: 0, id: 12, row: 3, col: 0),Tile(val: 0, id: 13, row: 3, col: 1),Tile(val: 0, id: 14, row: 3, col: 2), Tile(val: 0, id: 15, row: 3, col: 3) ]] seededGenerator = SeededGenerator(seed: 14) score = 0 } func newgame(rand: Bool){ if rand{ //randomized for i in 0..<board.count{ for j in 0..<board.count{ board[i][j]?.val = 0 } } score = 0 seededGenerator = SeededGenerator(seed: UInt64(Int.random(in:1...1000))) } else { //deterministic for i in 0..<board.count{ for j in 0..<board.count{ board[i][j]?.val = 0 } } score = 0 seededGenerator = SeededGenerator(seed: 14) } } func spawn() { let newval = Int.random(in: 1...2, using: &seededGenerator) var open: [[Int]] = [] let len = board.count for row in 0..<len{ for col in 0..<len{ if board[row][col]?.val == 0 { open.append([row, col]) } } } if open.count != 0{ //board is not full let loc:Int = Int.random(in: 0..<open.count, using: &seededGenerator) //randomly choose which idx to spawn let row = open[loc][0] let col = open[loc][1] board[row][col]?.val = newval score += newval } else { //board is full } } func rotate() { board = Trotate2DInts(input: board) } // rotate a square 2D Int array clockwise func shift() { let n = board.count for row in 0..<n { for cell in 0..<n - 1 { if board[row][cell]?.val == 0{ //if cell is 0 for cell2 in cell..<n - 1{ board[row][cell2] = board[row][cell2 + 1] //shift them up by one } board[row][n-1]?.val = 0 //insert 0 at the end break } else if board[row][cell]?.val == 1 || board[row][cell]?.val == 2 { if board[row][cell+1]?.val == 1 || board[row][cell+1]?.val == 2{ if board[row][cell+1]?.val == 2 && board[row][cell]?.val == 1{ board[row][cell]?.val = 3 let id = board[row][cell]?.id score += 3 for cell3 in cell+1..<n - 1{ board[row][cell3] = board[row][cell3 + 1] // board[row][cell3 + 1]?.id = ((board[row][cell3 + 1]?.id ?? 0) - 1) } board[row][n-1]?.val = 0 //insert 0 at the end board[row][n-1]?.id = id ?? 0 break } else if board[row][cell+1]?.val == 1 && board[row][cell]?.val == 2{ board[row][cell]?.val = 3 let id = board[row][cell]?.id score += 3 for cell3 in cell+1..<n - 1{ board[row][cell3] = board[row][cell3 + 1] // board[row][cell3 + 1]?.id = ((board[row][cell3 + 1]?.id ?? 0) - 1) } board[row][n-1]?.val = 0 //insert 0 at the end board[row][n-1]?.id = id ?? 0 break } } } else { if board[row][cell]?.val == board[row][cell + 1]?.val { //if number in the cell is >= 3 and the next number == curr board[row][cell]?.val = (board[row][cell]?.val ?? 0) * 2 //add them score += board[row][cell]?.val ?? 0 let id = board[row][cell]?.id for cell4 in cell+1..<n - 1{ board[row][cell4] = board[row][cell4 + 1] //pull the rest of the board by 1 // board[row][cell4 + 1]?.id = ((board[row][cell4 + 1]?.id ?? 0) - 1) } board[row][n-1]?.val = 0 //insert 0 at the end board[row][n-1]?.id = id ?? 0 break } } } } } // collapse to the left //this func returns true if it moved func collapse(dir: Tdirection) -> Bool { let copy = TTriples() copy.board = self.board if dir == Tdirection.left { self.shift() if copy.board == self.board { return false } else { return true } } else if dir == Tdirection.right { self.rotate() self.rotate() self.shift() self.rotate() self.rotate() if copy.board == self.board { return false } else { return true } } else if dir == Tdirection.up { self.rotate() self.rotate() self.rotate() self.shift() self.rotate() if copy.board == self.board { return false } else { return true } } else { self.rotate() self.shift() self.rotate() self.rotate() self.rotate() if copy.board == self.board { return false } else { return true } } }// collapse in specified direction using shift() and rotate() } //end of class Triples // class-less function that will return of any square 2D Int array rotated clockwise func Trotate2DInts(input: [[Tile?]]) -> [[Tile?]] { let n = input.count let tile = Tile(val: 0, id: 0, row: 0, col: 0) var newArr:[[Tile?]] = Array(repeating: Array(repeating: tile, count: n), count: n) for i in 0..<input.count { for j in 0..<input[0].count{ let newRow = j+n % n let newCol = (n-1)-i; newArr[newRow][newCol] = input[i][j] } } return newArr } /* func Trotate2D<T> (input: [[T]]) -> [[T]] { let n = 4 var newArr = input for i in 0..<n { for j in 0..<input[0].count{ let newRow = j+n % n let newCol = (n-1)-i; newArr[newRow][newCol] = input[i][j] newArr[newRow][newCol]?.id = ((newRow * 4) + newCol) } } return newArr } */