first game in main 🎉

master
Adam BONAFOS 4 months ago
parent 1fde20ecd5
commit 57283d55e5

@ -5,6 +5,6 @@
location = "group:Model">
</FileRef>
<FileRef
location = "group:../Connect4_CLI/Connect4_CLI.xcodeproj">
location = "group:Connect4_CLI/Connect4_CLI.xcodeproj">
</FileRef>
</Workspace>

@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */
90BAEDC82D34F75500C6B480 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90BAEDC72D34F75500C6B480 /* main.swift */; };
90C8428D2D50D02200DDFF08 /* Model in Frameworks */ = {isa = PBXBuildFile; productRef = 90C8428C2D50D02200DDFF08 /* Model */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -25,7 +26,6 @@
/* Begin PBXFileReference section */
90BAEDC42D34F75500C6B480 /* Connect4_CLI */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Connect4_CLI; sourceTree = BUILT_PRODUCTS_DIR; };
90BAEDC72D34F75500C6B480 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
90BAEDCE2D34F78600C6B480 /* Model */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Model; path = ../Model; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -33,6 +33,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
90C8428D2D50D02200DDFF08 /* Model in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -42,9 +43,9 @@
90BAEDBB2D34F75500C6B480 = {
isa = PBXGroup;
children = (
90BAEDCE2D34F78600C6B480 /* Model */,
90BAEDC62D34F75500C6B480 /* Connect4_CLI */,
90BAEDC52D34F75500C6B480 /* Products */,
90C8428B2D50D02200DDFF08 /* Frameworks */,
);
sourceTree = "<group>";
};
@ -64,6 +65,13 @@
path = Connect4_CLI;
sourceTree = "<group>";
};
90C8428B2D50D02200DDFF08 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -80,6 +88,9 @@
dependencies = (
);
name = Connect4_CLI;
packageProductDependencies = (
90C8428C2D50D02200DDFF08 /* Model */,
);
productName = Connect4_CLI;
productReference = 90BAEDC42D34F75500C6B480 /* Connect4_CLI */;
productType = "com.apple.product-type.tool";
@ -282,6 +293,13 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCSwiftPackageProductDependency section */
90C8428C2D50D02200DDFF08 /* Model */ = {
isa = XCSwiftPackageProductDependency;
productName = Model;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 90BAEDBC2D34F75500C6B480 /* Project object */;
}

@ -6,6 +6,30 @@
//
import Foundation
import Model
print("Hello, World!")
print("Connect4")
func read(question: String) -> String {
print(question)
let answer = readLine()
if let answer {
return answer
} else {
return ""
}
}
var board = Board(rowsNb: 6, columnsNb: 7)
var rules = Connect4Rules(piecesToAlign: 4)
var player1: Player = HumanPlayer(rules: rules, color: .red, name: "player1", CLI: read)
var player2: Player = HumanPlayer(rules: rules, color: .yellow, name: "player2", CLI: read)
while rules.isGameOver(board: board).0 != true {
var move = player1.play()
while rules.possibleMoves(board: board).contains(move) != true {
print("Move invalide en choisir un autre")
move = player1.play()
}
board[move.row, move.column] = player1.color
}

@ -18,7 +18,7 @@ public struct Board {
grid = Array(repeating: Array(repeating: Token.empty, count: columnsNb), count: rowsNb)
}
subscript(row: Int, column: Int) -> Token {
public subscript(row: Int, column: Int) -> Token {
get {
guard row >= 0 && row < rowNb && column >= 0 && column < columnNb else {
fatalError("Out of board")

@ -96,14 +96,14 @@ public struct Connect4Rules : Rules {
return true
}
func possibleMoves(board: Board) -> [(row: Int, column: Int)] {
var possibleMoves: [(Int, Int)] = []
public func possibleMoves(board: Board) -> [Move] {
var possibleMoves: [Move] = []
for column in 0..<board.columnNb {
// Trouver la première case vide en partant du bas de la colonne
for row in (0..<board.rowNb).reversed() {
for row in (0..<board.rowNb) {
if board[row, column] == Token.empty {
possibleMoves.append((row, column)) // Ajouter la position (row, column)
possibleMoves.append(Move(row: row, column: column)) // Ajouter la position (row, column)
break // Une fois trouvé, on passe à la colonne suivante
}
}

@ -0,0 +1,18 @@
//
// File.swift
//
//
// Created by Adam BONAFOS on 03/02/2025.
//
import Foundation
public struct Move: Equatable {
public let row: Int
public let column: Int
public init(row: Int, column: Int) {
self.row = row
self.column = column
}
}

@ -6,17 +6,17 @@
//
import Foundation
class HumanPlayer : Player {
public class HumanPlayer : Player {
// Propriété CLI de type closure
var CLI: ((String) -> String)?
private var CLI: ((String) -> String)?
// Initialisation avec la closure CLI
init(CLI: @escaping (String) -> String) {
public init(rules: Rules, color: Token, name: String, CLI: @escaping (String) -> String) {
self.CLI = CLI
super.init()
super.init(rules: rules, color: color, name: name)
}
override func play() -> (row: Int, column: Int) {
public override func play() -> Move {
// Demande la colonne à l'utilisateur
let columnInput = CLI!("Entrez le numéro de la colonne : ")
guard let column = Int(columnInput) else {
@ -27,6 +27,6 @@ class HumanPlayer : Player {
guard let row = Int(rowInput) else {
fatalError("Entrée invalide pour la ligne.")
}
return (row, column)
return Move(row: row, column: column)
}
}

@ -6,16 +6,16 @@
//
import Foundation
class Player {
public class Player {
var name: String
var color: Token
public let color: Token
var rules: Rules
init(rules: Rules, color: Token, name: String){
public init(rules: Rules, color: Token, name: String){
self.name = name
self.color = color
self.rules = rules
}
func play() -> (row: Int, column: Int){
public func play() -> Move {
fatalError("Must override in subclass")
}
}

@ -7,7 +7,7 @@
import Foundation
class RandomPlayer : AIPlayer {
override func play() -> (row: Int, column: Int) {
return (0, 0)
override func play() -> Move {
return Move(row: 0, column: 0)
}
}

@ -6,9 +6,10 @@
//
import Foundation
protocol Rules {
public protocol Rules {
func add(board: inout Board, position pos: (row: Int, column: Int), token: Token) -> Bool
func isGameOver(board: Board) -> (result: Bool, winner: Token)
func possibleMoves(board: Board) -> [(row: Int, column: Int)]
func possibleMoves(board: Board) -> [Move]
}

@ -8,13 +8,13 @@
import Foundation
public struct TicTacToeRules: Rules {
func possibleMoves(board: Board) -> [(row: Int, column: Int)] {
var possibleMoves: [(Int, Int)] = []
public func possibleMoves(board: Board) -> [Move] {
var possibleMoves: [Move] = []
for column in 0..<board.columnNb {
for row in 0..<board.rowNb {
if board[row, column] == Token.empty {
possibleMoves.append((row, column)) // Ajouter la position (row, column)
possibleMoves.append(Move(row: row, column: column)) // Ajouter la position (row, column)
}
}
}
@ -22,7 +22,7 @@ public struct TicTacToeRules: Rules {
return possibleMoves
}
func add(board: inout Board, position pos: (row: Int, column: Int), token: Token) -> Bool {
public func add(board: inout Board, position pos: (row: Int, column: Int), token: Token) -> Bool {
if board[pos.0, pos.1] == .empty {
board[pos.0, pos.1] = token
return true
@ -30,7 +30,7 @@ public struct TicTacToeRules: Rules {
return false
}
func isGameOver(board: Board) -> (result: Bool, winner: Token) {
public func isGameOver(board: Board) -> (result: Bool, winner: Token) {
// Need to be complete
// TODO
return (false, Token.empty)

Loading…
Cancel
Save