Skip to content

Commit

Permalink
Merge pull request #69 from omochi/ttt
Browse files Browse the repository at this point in the history
三目並べの実装
  • Loading branch information
omochi authored Apr 19, 2024
2 parents 16b518e + 429ac19 commit aeea532
Show file tree
Hide file tree
Showing 13 changed files with 213 additions and 11 deletions.
15 changes: 10 additions & 5 deletions BrowserTests/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import PackageDescription
var products: [Product] = []
var targets: [Target] = []

func addPage(name: String) {
func addPage(name: String, resources: [String]? = nil) {
targets.append(
.executableTarget(
name: name,
dependencies: [
.product(name: "React", package: "swift-react"),
.target(name: "BRTSupport")
]
],
resources: resources?.map { .copy($0) }
)
)
products.append(
Expand All @@ -22,12 +23,13 @@ func addPage(name: String) {

addPage(name: "QSComponents")
addPage(name: "QSMarkup")
addPage(name: "QSDisplayingData")
addPage(name: "QSDisplayingData", resources: ["styles.css"])
addPage(name: "QSConditional")
addPage(name: "QSLists")
addPage(name: "QSEvents")
addPage(name: "QSUpdating")
addPage(name: "QSSharing")
addPage(name: "QSUpdating", resources: ["styles.css"])
addPage(name: "QSSharing", resources: ["styles.css"])
addPage(name: "TicTacToe", resources: ["styles.css"])

let package = Package(
name: "BrowserTests",
Expand All @@ -43,6 +45,9 @@ let package = Package(
name: "BRTSupport",
dependencies: [
.product(name: "React", package: "swift-react")
],
resources: [
.copy("common.css")
]
)
] + targets + [
Expand Down
2 changes: 1 addition & 1 deletion BrowserTests/Sources/BRTSupport/CSS.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public func addCSS(path: String) throws {
try tag.setAttributes([
"rel": "stylesheet",
"type": "text/css",
"href": path
"href": "/.build/wasm32-unknown-wasi/debug/" + path
])
try head.appendChild(tag)
}
2 changes: 1 addition & 1 deletion BrowserTests/Sources/GenPagesModule/GenPages.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public struct GenPages {

private static func pages(rootDir: URL) throws -> [String] {
let packageCode = try String(contentsOf: rootDir.appending(components: "Package.swift"))
let pageRegex = /addPage\(name: "(\w*)"\)/
let pageRegex = /addPage\(name: "(\w*)"/
return packageCode.matches(of: pageRegex).map { String($0.output.1) }
}

Expand Down
2 changes: 1 addition & 1 deletion BrowserTests/Sources/QSDisplayingData/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ struct Profile: Component {
}
}

try addCSS(path: "/Sources/QSDisplayingData/styles.css")
try addCSS(path: "BrowserTests_QSDisplayingData.resources/styles.css")
try renderRoot(component: Profile())
2 changes: 1 addition & 1 deletion BrowserTests/Sources/QSSharing/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct MyApp: Component {
}
}

try addCSS(path: "/Sources/QSSharing/styles.css")
try addCSS(path: "BrowserTests_QSSharing.resources/styles.css")
try renderRoot(component: MyApp())


2 changes: 1 addition & 1 deletion BrowserTests/Sources/QSUpdating/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ struct MyApp: Component {
}
}

try addCSS(path: "/Sources/QSUpdating/styles.css")
try addCSS(path: "BrowserTests_QSUpdating.resources/styles.css")
try renderRoot(component: MyApp())


143 changes: 143 additions & 0 deletions BrowserTests/Sources/TicTacToe/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import React
import JavaScriptKit
import SRTDOM
import BRTSupport

// https://ja.react.dev/learn/tutorial-tic-tac-toe

func calculateWinner(squares: [String?]) -> String? {
let lines: [[Int]] = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
]
for line in lines {
let (a, b, c) = (line[0], line[1], line[2])

if let x = squares[a],
squares[b] == x,
squares[c] == x {
return x
}
}
return nil
}

struct Square: Component {
var value: String?
var onSquareClick: EventListener

func render() -> Node {
return button(
attributes: ["class": "square"],
listeners: ["click": onSquareClick]
) {
value
}
}
}

struct Board: Component {
var xIsNext: Bool = true
var squares: [String?] = Array(repeating: nil, count: 9)
var onPlay: Function<Void, [String?]>

func handleClick(index: Int) {
if squares[index] != nil ||
calculateWinner(squares: squares) != nil { return }

var squares = self.squares

if xIsNext {
squares[index] = "X"
} else {
squares[index] = "O"
}

onPlay(squares)
}

func render() -> Node {
let winner = calculateWinner(squares: squares)
let status: String
if let winner {
status = "Winner: " + winner;
} else {
status = "Next player: " + (xIsNext ? "X" : "O")
}

return Fragment {
div(attributes: ["class": "status"]) { status }
div(attributes: ["class": "board-row"]) {
Square(value: squares[0], onSquareClick: EventListener { (_) in handleClick(index: 0) })
Square(value: squares[1], onSquareClick: EventListener { (_) in handleClick(index: 1) })
Square(value: squares[2], onSquareClick: EventListener { (_) in handleClick(index: 2) })
}
div(attributes: ["class": "board-row"]) {
Square(value: squares[3], onSquareClick: EventListener { (_) in handleClick(index: 3) })
Square(value: squares[4], onSquareClick: EventListener { (_) in handleClick(index: 4) })
Square(value: squares[5], onSquareClick: EventListener { (_) in handleClick(index: 5) })
}
div(attributes: ["class": "board-row"]) {
Square(value: squares[6], onSquareClick: EventListener { (_) in handleClick(index: 6) })
Square(value: squares[7], onSquareClick: EventListener { (_) in handleClick(index: 7) })
Square(value: squares[8], onSquareClick: EventListener { (_) in handleClick(index: 8) })
}
}
}
}

struct Game: Component {
@State var history: [[String?]] = [Array(repeating: nil, count: 9)]
@State var currentMove: Int = 0

func render() -> Node {
let xIsNext = currentMove % 2 == 0

let currentSquares = history[currentMove]

let handlePlay = Function<Void, [String?]> { (nextSquares) in
history = history[...currentMove] + [nextSquares]
currentMove = history.count - 1
}

func jumpTo(nextMove: Int) {
currentMove = nextMove
}

let moves: [Node] = history.enumerated().map { (move, squares) -> Node in
let description: String
if move > 0 {
description = "Go to move #\(move)"
} else {
description = "Go to game start"
}
return li(key: move) {
button(listeners: ["click": EventListener { (e) in jumpTo(nextMove: move) }]) {
description
}
}
}

return div(attributes: ["class": "game"]) {
div(attributes: ["class": "game-board"]) {
Board(xIsNext: xIsNext, squares: currentSquares, onPlay: handlePlay)
}
div(attributes: ["class": "game-info"]) {
ol {
moves
}
}
}
}
}

try addCSS(path: "BrowserTests_TicTacToe.resources/styles.css")
try renderRoot(component: Game())


32 changes: 32 additions & 0 deletions BrowserTests/Sources/TicTacToe/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.square {
background: #fff;
border: 1px solid #999;
float: left;
font-size: 24px;
font-weight: bold;
line-height: 34px;
height: 34px;
margin-right: -1px;
margin-top: -1px;
padding: 0;
text-align: center;
width: 34px;
}

.board-row:after {
clear: both;
content: '';
display: table;
}

.status {
margin-bottom: 10px;
}
.game {
display: flex;
flex-direction: row;
}

.game-info {
margin-left: 20px;
}
3 changes: 3 additions & 0 deletions BrowserTests/index.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions BrowserTests/pages/TicTacToe.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions BrowserTests/vite.config.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Sources/SRTDOM/JSDocument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ public struct JSDocument: ConvertibleToJSObject & ConstructibleFromJSValue {
try .mustConstruct(from: try jsValue.throws.createTextNode(data))
}

public func getElementById(_ id: String) throws -> JSHTMLElement? {
try .mustConstruct(from: try jsValue.throws.getElementById(id))
}

public func querySelector(_ selectors: String) throws -> JSHTMLElement? {
try .mustConstruct(from: try jsValue.throws.querySelector(selectors))
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/SRTDOM/JSWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public struct JSWindow: ConvertibleToJSObject & ConstructibleFromJSValue {

public var document: JSDocument { .unsafeConstruct(from: jsValue.document) }

public func alert(_ message: String) throws { try jsValue.throws.alert(message) }
public func alert(_ message: String) throws { _ = try jsValue.throws.alert(message) }

public static var global: JSWindow {
JSWindow(jsObject: JSObject.global)
Expand Down

0 comments on commit aeea532

Please sign in to comment.