The following is a program written in {{ lang/framework }}. First, explain what the code does in general, language agnostic terms. After, create a similar program in idiomatic {{ lang }} using {{ framework }} and other system libraries. Avoid using third party dependencies. Feel free to make improvements. Add FIXME or TODO comments if you are unsure about how to implement parts of the code. If something is not clear ask me follow up questions.
{{ program }}
I found that allowing ChatGPT to use FIXMEs and TODOs reduces the number of mistakes and hallucinations. This seems to somewhat mirror the behavior of human coders. Asking for clarifying details also helps when it's missing a lot of context. It does a good job of asking pointed questions to disambiguate what it needs.
Tic-Tac-Toe app in React.js -> SwiftUI iOS (original code from https://react.dev/learn/tutorial-tic-tac-toe) The resulting Swift code had one small error that ChatGPT fixed after feeding it the compile error.
import { useState } from 'react';
function Square({ value, onSquareClick }) {
return (
<button className="square" onClick={onSquareClick}>
{value}
</button>
);
}
function Board({ xIsNext, squares, onPlay }) {
function handleClick(i) {
if (calculateWinner(squares) || squares[i]) {
return;
}
const nextSquares = squares.slice();
if (xIsNext) {
nextSquares[i] = 'X';
} else {
nextSquares[i] = 'O';
}
onPlay(nextSquares);
}
const winner = calculateWinner(squares);
let status;
if (winner) {
status = 'Winner: ' + winner;
} else {
status = 'Next player: ' + (xIsNext ? 'X' : 'O');
}
return (
<>
<div className="status">{status}</div>
<div className="board-row">
<Square value={squares[0]} onSquareClick={() => handleClick(0)} />
<Square value={squares[1]} onSquareClick={() => handleClick(1)} />
<Square value={squares[2]} onSquareClick={() => handleClick(2)} />
</div>
<div className="board-row">
<Square value={squares[3]} onSquareClick={() => handleClick(3)} />
<Square value={squares[4]} onSquareClick={() => handleClick(4)} />
<Square value={squares[5]} onSquareClick={() => handleClick(5)} />
</div>
<div className="board-row">
<Square value={squares[6]} onSquareClick={() => handleClick(6)} />
<Square value={squares[7]} onSquareClick={() => handleClick(7)} />
<Square value={squares[8]} onSquareClick={() => handleClick(8)} />
</div>
</>
);
}
export default function Game() {
const [history, setHistory] = useState([Array(9).fill(null)]);
const [currentMove, setCurrentMove] = useState(0);
const xIsNext = currentMove % 2 === 0;
const currentSquares = history[currentMove];
function handlePlay(nextSquares) {
const nextHistory = [...history.slice(0, currentMove + 1), nextSquares];
setHistory(nextHistory);
setCurrentMove(nextHistory.length - 1);
}
function jumpTo(nextMove) {
setCurrentMove(nextMove);
}
const moves = history.map((squares, move) => {
let description;
if (move > 0) {
description = 'Go to move #' + move;
} else {
description = 'Go to game start';
}
return (
<li key={move}>
<button onClick={() => jumpTo(move)}>{description}</button>
</li>
);
});
return (
<div className="game">
<div className="game-board">
<Board xIsNext={xIsNext} squares={currentSquares} onPlay={handlePlay} />
</div>
<div className="game-info">
<ol>{moves}</ol>
</div>
</div>
);
}
function calculateWinner(squares) {
const lines = [
[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 (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
import SwiftUI
struct Square: View {
let value: String
let onSquareClick: () -> Void
var body: some View {
Button(action: onSquareClick) {
Text(value)
.font(.largeTitle)
.fontWeight(.bold)
.frame(width: 100, height: 100)
.background(Color.gray)
.foregroundColor(Color.white)
.cornerRadius(10)
}
}
}
struct Board: View {
let xIsNext: Bool
let squares: [String]
let onPlay: (Int) -> Void
private func handleClick(_ i: Int) {
if calculateWinner(squares) != nil || squares[i] != "" {
return
}
var nextSquares = squares
nextSquares[i] = xIsNext ? "X" : "O"
onPlay(i)
}
var body: some View {
VStack {
Text(status)
.font(.title)
.fontWeight(.bold)
ForEach(0..<3) { row in
HStack {
ForEach(0..<3) { col in
let index = row * 3 + col
Square(value: squares[index]) {
handleClick(index)
}
}
}
}
}
}
private var status: String {
if let winner = calculateWinner(squares) {
return "Winner: \(winner)"
} else {
return "Next player: \(xIsNext ? "X" : "O")"
}
}
}
struct Game: View {
@State private var history = [Array(repeating: "", count: 9)]
@State private var currentMove = 0
private var xIsNext: Bool {
currentMove % 2 == 0
}
private var currentSquares: [String] {
history[currentMove]
}
private func handlePlay(_ i: Int) {
var nextHistory = Array(history[0...currentMove])
var nextSquares = currentSquares
nextSquares[i] = xIsNext ? "X" : "O"
nextHistory.append(nextSquares)
history = nextHistory
currentMove = nextHistory.count - 1
}
private func jump(to nextMove: Int) {
currentMove = nextMove
}
private var moves: [Move] {
history.enumerated().map { move, _ in
Move(description: moveDescription(for: move)) {
jump(to: move)
}
}
}
private func moveDescription(for move: Int) -> String {
if move == 0 {
return "Go to game start"
} else {
return "Go to move #\(move)"
}
}
var body: some View {
VStack {
Board(xIsNext: xIsNext, squares: currentSquares, onPlay: handlePlay)
.padding()
ScrollView {
VStack(alignment: .leading) {
Text("Moves")
.font(.title)
.fontWeight(.bold)
ForEach(moves) { move in
move
}
}
}
.frame(maxHeight: .infinity)
}
}
}
struct Move: View, Identifiable {
let id = UUID()
let description: String
let onMoveClick: () -> Void
var body: some View {
Button(action: onMoveClick) {
Text(description)
.font(.headline)
.padding()
}
}
}
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 = line[0]
let b = line[1]
let c = line[2]
if squares[a] != "" && squares[a] == squares[b] && squares[a] == squares[c] {
return squares[a]
}
}
return nil
}