作れました
Claude Code × MCP サーバーを使って、Power Apps のキャンバスアプリでオセロを作りました。
コードは一行も書いていません。「オセロアプリを作って」と日本語で話しかけただけです。
できあがったのは 1 画面構成のアプリで、以下の機能がすべて含まれています。
- 8×8 ボードと石の描画
- 合法手のハイライト表示
- 石をひっくり返す処理(8方向)
- パスの自動検出
- 勝敗判定とゲームオーバー画面
- CPU 対戦(コーナー重視の位置評価あり)
業務アプリでもなく、フォームでもない。ゲームが動いたのは正直驚きました。
生成された YAML
Claude Code が生成した .pa.yaml をそのまま掲載します。 Power Apps Studio のコードビューに貼り付けると動きます。
一番下の部分がかぶっているので押しにくい箇所があります。そこを修正してから提供してもよかったのですが、あえてAIそのままのコードを貼り付けることにしました。(ちょっと盤面上に動かせば実際はOK)
ちなみにCPUはそれなりにできるので、何も考えないで打ったらちゃんと負けられますw
Screens:
GameScreen:
Properties:
Fill: =RGBA(18, 24, 22, 1)
OnVisible: |-
=If(
CountRows(colBoard) = 0,
ClearCollect(
colBoard,
ForAll(
Sequence(64),
{
Row: RoundDown((Value - 1) / 8, 0) + 1,
Col: Mod(Value - 1, 8) + 1,
Color: "Empty",
IsValid: false
}
)
);
UpdateIf(colBoard, Row = 4 And Col = 4, {Color: "White"});
UpdateIf(colBoard, Row = 4 And Col = 5, {Color: "Black"});
UpdateIf(colBoard, Row = 5 And Col = 4, {Color: "Black"});
UpdateIf(colBoard, Row = 5 And Col = 5, {Color: "White"});
ClearCollect(
colDirs,
{dr: -1, dc: -1}, {dr: -1, dc: 0}, {dr: -1, dc: 1},
{dr: 0, dc: -1}, {dr: 0, dc: 1},
{dr: 1, dc: -1}, {dr: 1, dc: 0}, {dr: 1, dc: 1}
);
Set(currentPlayer, "Black");
Set(gameOver, false);
Set(winnerText, "");
Set(lastMessage, "")
);
If(
IsBlank(userColor) Or userColor = "",
Set(userColor, "");
Set(cpuColor, "");
Set(sideChosen, false)
)
Children:
- TitleLabel:
Control: Text@0.0.51
Properties:
Align: =Align.Left
Font: =Font.Georgia
FontColor: =RGBA(246, 240, 224, 1)
Height: =56
Size: =40
Text: ="OTHELLO"
VerticalAlign: =VerticalAlign.Middle
Weight: ='TextCanvas.Weight'.Bold
Width: =480
X: =40
Y: =32
- TurnBadge:
Control: Badge@0.0.24
Properties:
Appearance: ='BadgeCanvas.Appearance'.Filled
Content: =Upper(currentPlayer) & " TO MOVE"
FontSize: =14
FontWeight: =FontWeight.Semibold
Height: =36
Shape: ='BadgeCanvas.Shape'.Rounded
ThemeColor: ='BadgeCanvas.ThemeColor'.Danger
Visible: =!gameOver
Width: =220
X: =Parent.Width - 260
Y: =44
- LastMessageLabel:
Control: Text@0.0.51
Properties:
Align: =Align.Center
FontColor: =RGBA(180, 172, 150, 1)
Height: =20
Size: =12
Text: =lastMessage
Visible: =Len(lastMessage) > 0
Weight: ='TextCanvas.Weight'.Regular
Width: =560
X: =(Parent.Width - 560) / 2
Y: =106
- BoardBackdrop:
Control: Rectangle@2.3.0
Properties:
BorderStyle: =BorderStyle.None
Fill: =RGBA(10, 40, 28, 1)
Height: =600
Width: =600
X: =(Parent.Width - 600) / 2
Y: =130
- BoardGallery:
Control: Gallery@2.15.0
Variant: Horizontal
Properties:
BorderStyle: =BorderStyle.None
Fill: =RGBA(10, 40, 28, 1)
Height: =560
Items: =colBoard
ShowScrollbar: =false
TemplatePadding: =0
TemplateSize: =70
Width: =560
WrapCount: =8
X: =(Parent.Width - 560) / 2
Y: =150
Children:
- CellBg:
Control: Rectangle@2.3.0
Properties:
BorderStyle: =BorderStyle.None
Fill: |-
=If(
ThisItem.Color = "Empty"
And Not gameOver
And Sum(
ForAll(
colDirs,
{
n: With(
{
steps: ForAll(
Sequence(7),
{
i: Value,
color: With(
{ rr: ThisItem.Row + dr * Value, cc: ThisItem.Col + dc * Value },
If(
rr < 1 Or rr > 8 Or cc < 1 Or cc > 8,
"Off",
With(
{ cell: LookUp(colBoard, Row = rr And Col = cc) },
If(IsBlank(cell), "Off", cell.Color)
)
)
)
}
),
opp: If(currentPlayer = "Black", "White", "Black")
},
With(
{
stopIdx: First(
Sort(Filter(steps, color <> opp), i, SortOrder.Ascending)
)
},
If(
IsBlank(stopIdx) Or stopIdx.color <> currentPlayer Or stopIdx.i = 1,
0,
stopIdx.i - 1
)
)
)
}
),
n
) > 0,
RGBA(52, 140, 100, 1),
RGBA(26, 95, 66, 1)
)
Height: =68
Width: =68
X: =1
Y: =1
- CellValidDot:
Control: Circle@2.3.0
Properties:
BorderStyle: =BorderStyle.None
Fill: =RGBA(255, 244, 214, 0.35)
Height: =8
Visible: |-
=ThisItem.Color = "Empty"
And Not gameOver
And Sum(
ForAll(
colDirs,
{
n: With(
{
steps: ForAll(
Sequence(7),
{
i: Value,
color: With(
{ rr: ThisItem.Row + dr * Value, cc: ThisItem.Col + dc * Value },
If(
rr < 1 Or rr > 8 Or cc < 1 Or cc > 8,
"Off",
With(
{ cell: LookUp(colBoard, Row = rr And Col = cc) },
If(IsBlank(cell), "Off", cell.Color)
)
)
)
}
),
opp: If(currentPlayer = "Black", "White", "Black")
},
With(
{
stopIdx: First(
Sort(Filter(steps, color <> opp), i, SortOrder.Ascending)
)
},
If(
IsBlank(stopIdx) Or stopIdx.color <> currentPlayer Or stopIdx.i = 1,
0,
stopIdx.i - 1
)
)
)
}
),
n
) > 0
Width: =8
X: =31
Y: =31
- StoneCircle:
Control: Circle@2.3.0
Properties:
BorderColor: =If(ThisItem.Color = "Black", RGBA(255, 255, 255, 0.12), RGBA(0, 0, 0, 0.25))
BorderThickness: =1
Fill: =If(ThisItem.Color = "Black", RGBA(14, 14, 14, 1), RGBA(246, 240, 224, 1))
Height: =56
Visible: =ThisItem.Color <> "Empty"
Width: =56
X: =7
Y: =7
- CellClickButton:
Control: Button@0.0.45
Properties:
Appearance: ='ButtonCanvas.Appearance'.Transparent
BorderThickness: =0
Height: =70
OnSelect: |-
=If(
gameOver Or ThisItem.Color <> "Empty" Or Not sideChosen Or currentPlayer = cpuColor,
false,
With(
{
thisRow: ThisItem.Row,
thisCol: ThisItem.Col,
player: currentPlayer,
opp: If(currentPlayer = "Black", "White", "Black")
},
With(
{
flipsByDir: ForAll(
colDirs,
{
dr: dr,
dc: dc,
count: With(
{
steps: ForAll(
Sequence(7),
{
i: Value,
color: With(
{ rr: thisRow + dr * Value, cc: thisCol + dc * Value },
If(
rr < 1 Or rr > 8 Or cc < 1 Or cc > 8,
"Off",
With(
{ cell: LookUp(colBoard, Row = rr And Col = cc) },
If(IsBlank(cell), "Off", cell.Color)
)
)
)
}
)
},
With(
{
stopIdx: First(
Sort(Filter(steps, color <> opp), i, SortOrder.Ascending)
)
},
If(
IsBlank(stopIdx) Or stopIdx.color <> player Or stopIdx.i = 1,
0,
stopIdx.i - 1
)
)
)
}
)
},
If(
Sum(flipsByDir, count) <= 0,
false,
UpdateIf(colBoard, Row = thisRow And Col = thisCol, {Color: player});
ForAll(
Filter(flipsByDir, count > 0),
ForAll(
Sequence(count),
UpdateIf(
colBoard,
Row = thisRow + dr * Value And Col = thisCol + dc * Value,
{Color: player}
)
)
);
Set(currentPlayer, opp);
Set(lastMessage, "");
If(
CountRows(
Filter(
colBoard,
Color = "Empty"
And Sum(
ForAll(
colDirs,
{
n: With(
{
steps: ForAll(
Sequence(7),
{
i: Value,
color: With(
{ rr: Row + dr * Value, cc: Col + dc * Value },
If(
rr < 1 Or rr > 8 Or cc < 1 Or cc > 8,
"Off",
With(
{ cell2: LookUp(colBoard, Row = rr And Col = cc) },
If(IsBlank(cell2), "Off", cell2.Color)
)
)
)
}
),
opp2: If(currentPlayer = "Black", "White", "Black")
},
With(
{
stopIdx2: First(
Sort(Filter(steps, color <> opp2), i, SortOrder.Ascending)
)
},
If(
IsBlank(stopIdx2) Or stopIdx2.color <> currentPlayer Or stopIdx2.i = 1,
0,
stopIdx2.i - 1
)
)
)
}
),
n
) > 0
)
) = 0,
With(
{
other: If(currentPlayer = "Black", "White", "Black")
},
If(
CountRows(
Filter(
colBoard,
Color = "Empty"
And Sum(
ForAll(
colDirs,
{
n: With(
{
steps: ForAll(
Sequence(7),
{
i: Value,
color: With(
{ rr: Row + dr * Value, cc: Col + dc * Value },
If(
rr < 1 Or rr > 8 Or cc < 1 Or cc > 8,
"Off",
With(
{ cell3: LookUp(colBoard, Row = rr And Col = cc) },
If(IsBlank(cell3), "Off", cell3.Color)
)
)
)
}
),
opp3: If(other = "Black", "White", "Black")
},
With(
{
stopIdx3: First(
Sort(Filter(steps, color <> opp3), i, SortOrder.Ascending)
)
},
If(
IsBlank(stopIdx3) Or stopIdx3.color <> other Or stopIdx3.i = 1,
0,
stopIdx3.i - 1
)
)
)
}
),
n
) > 0
)
) = 0,
Set(gameOver, true);
Set(
winnerText,
With(
{
b: CountRows(Filter(colBoard, Color = "Black")),
w: CountRows(Filter(colBoard, Color = "White"))
},
If(b > w, "BLACK WINS", If(w > b, "WHITE WINS", "DRAW"))
)
),
Set(
lastMessage,
Upper(currentPlayer) & " had no legal moves — " & Upper(other) & " plays again."
);
Set(currentPlayer, other)
)
),
false
)
)
)
)
)
Text: =""
Width: =70
- ScoreContainer:
Control: GroupContainer@1.5.0
Variant: ManualLayout
Properties:
BorderStyle: =BorderStyle.None
Height: =100
Width: =560
X: =(Parent.Width - 560) / 2
Y: =668
Children:
- BlackScoreNumber:
Control: Text@0.0.51
Properties:
Align: =Align.Left
FontColor: =RGBA(246, 240, 224, 1)
Height: =72
Size: =48
Text: =CountRows(Filter(colBoard, Color = "Black"))
VerticalAlign: =VerticalAlign.Middle
Weight: ='TextCanvas.Weight'.Bold
Width: =180
- BlackScoreCaption:
Control: Text@0.0.51
Properties:
Align: =Align.Left
FontColor: =RGBA(180, 172, 150, 1)
Height: =24
Size: =12
Text: ="BLACK"
Weight: ='TextCanvas.Weight'.Semibold
Width: =180
Y: =70
- WhiteScoreNumber:
Control: Text@0.0.51
Properties:
Align: =Align.Right
FontColor: =RGBA(246, 240, 224, 1)
Height: =72
Size: =48
Text: =CountRows(Filter(colBoard, Color = "White"))
VerticalAlign: =VerticalAlign.Middle
Weight: ='TextCanvas.Weight'.Bold
Width: =180
X: =Parent.Width - 180
- WhiteScoreCaption:
Control: Text@0.0.51
Properties:
Align: =Align.Right
FontColor: =RGBA(180, 172, 150, 1)
Height: =24
Size: =12
Text: ="WHITE"
Weight: ='TextCanvas.Weight'.Semibold
Width: =180
X: =Parent.Width - 180
Y: =70
- ResetButton:
Control: Button@0.0.45
Properties:
Appearance: ='ButtonCanvas.Appearance'.Primary
BasePaletteColor: =RGBA(246, 240, 224, 1)
BorderRadius: =2
FontColor: =RGBA(18, 24, 22, 1)
FontSize: =14
FontWeight: =FontWeight.Semibold
Height: =44
OnSelect: |-
=Clear(colBoard);
ForAll(
Sequence(64),
Collect(
colBoard,
{
Row: RoundDown((Value - 1) / 8, 0) + 1,
Col: Mod(Value - 1, 8) + 1,
Color: "Empty",
IsValid: false
}
)
);
UpdateIf(colBoard, Row = 4 And Col = 4, {Color: "White"});
UpdateIf(colBoard, Row = 4 And Col = 5, {Color: "Black"});
UpdateIf(colBoard, Row = 5 And Col = 4, {Color: "Black"});
UpdateIf(colBoard, Row = 5 And Col = 5, {Color: "White"});
Set(currentPlayer, "Black");
Set(gameOver, false);
Set(winnerText, "");
Set(lastMessage, "");
Set(userColor, "");
Set(cpuColor, "");
Set(sideChosen, false)
Text: ="RESET"
Width: =160
X: =(Parent.Width - 160) / 2
Y: =20
- GameOverScrim:
Control: Rectangle@2.3.0
Properties:
BorderStyle: =BorderStyle.None
Fill: =RGBA(0, 0, 0, 0.72)
Height: =Parent.Height
Visible: =gameOver
Width: =Parent.Width
- GameOverCard:
Control: GroupContainer@1.5.0
Variant: ManualLayout
Properties:
DropShadow: =DropShadow.Bold
Fill: =RGBA(246, 240, 224, 1)
Height: =260
Visible: =gameOver
Width: =420
X: =(Parent.Width - 420) / 2
Y: =(Parent.Height - 260) / 2
Children:
- GameOverEyebrow:
Control: Text@0.0.51
Properties:
Align: =Align.Center
FontColor: =RGBA(220, 68, 52, 1)
Height: =24
Size: =12
Text: ="GAME OVER"
Weight: ='TextCanvas.Weight'.Semibold
Width: =Parent.Width
Y: =40
- GameOverWinner:
Control: Text@0.0.51
Properties:
Align: =Align.Center
Font: =Font.Georgia
FontColor: =RGBA(18, 24, 22, 1)
Height: =56
Size: =36
Text: =winnerText
Weight: ='TextCanvas.Weight'.Bold
Width: =Parent.Width
Y: =72
- GameOverScores:
Control: Text@0.0.51
Properties:
Align: =Align.Center
FontColor: =RGBA(18, 24, 22, 1)
Height: =28
Size: =16
Text: ="Black " & CountRows(Filter(colBoard, Color = "Black")) & " · White " & CountRows(Filter(colBoard, Color = "White"))
Weight: ='TextCanvas.Weight'.Regular
Width: =Parent.Width
Y: =140
- GameOverResetButton:
Control: Button@0.0.45
Properties:
Appearance: ='ButtonCanvas.Appearance'.Primary
BasePaletteColor: =RGBA(18, 24, 22, 1)
BorderRadius: =2
FontColor: =RGBA(246, 240, 224, 1)
FontSize: =14
FontWeight: =FontWeight.Semibold
Height: =44
OnSelect: |-
=Clear(colBoard);
ForAll(
Sequence(64),
Collect(
colBoard,
{
Row: RoundDown((Value - 1) / 8, 0) + 1,
Col: Mod(Value - 1, 8) + 1,
Color: "Empty",
IsValid: false
}
)
);
UpdateIf(colBoard, Row = 4 And Col = 4, {Color: "White"});
UpdateIf(colBoard, Row = 4 And Col = 5, {Color: "Black"});
UpdateIf(colBoard, Row = 5 And Col = 4, {Color: "Black"});
UpdateIf(colBoard, Row = 5 And Col = 5, {Color: "White"});
Set(currentPlayer, "Black");
Set(gameOver, false);
Set(winnerText, "");
Set(lastMessage, "");
Set(userColor, "");
Set(cpuColor, "");
Set(sideChosen, false)
Text: ="PLAY AGAIN"
Width: =180
X: =(Parent.Width - 180) / 2
Y: =190
- CpuMoveTimer:
Control: Timer@2.1.0
Properties:
Duration: =600
Height: =1
OnTimerEnd: |-
=If(
Not sideChosen Or gameOver Or currentPlayer <> cpuColor,
false,
With(
{
legalMoves: Filter(
ForAll(
Filter(colBoard, Color = "Empty"),
{
mvRow: Row,
mvCol: Col,
totalFlips: Sum(
ForAll(
colDirs,
{
n: With(
{
steps: ForAll(
Sequence(7),
{
i: Value,
color: With(
{ rr: Row + dr * Value, cc: Col + dc * Value },
If(
rr < 1 Or rr > 8 Or cc < 1 Or cc > 8,
"Off",
With(
{ cellA: LookUp(colBoard, Row = rr And Col = cc) },
If(IsBlank(cellA), "Off", cellA.Color)
)
)
)
}
),
oppA: If(cpuColor = "Black", "White", "Black")
},
With(
{
stopIdxA: First(
Sort(Filter(steps, color <> oppA), i, SortOrder.Ascending)
)
},
If(
IsBlank(stopIdxA) Or stopIdxA.color <> cpuColor Or stopIdxA.i = 1,
0,
stopIdxA.i - 1
)
)
)
}
),
n
),
posWeight: With(
{ wr: Row, wc: Col },
If(
(wr = 1 Or wr = 8) And (wc = 1 Or wc = 8), 120,
(wr = 2 Or wr = 7) And (wc = 2 Or wc = 7), -40,
((wr = 1 Or wr = 8) And (wc = 2 Or wc = 7)) Or ((wr = 2 Or wr = 7) And (wc = 1 Or wc = 8)), -20,
((wr = 1 Or wr = 8) And (wc = 3 Or wc = 6)) Or ((wr = 3 Or wr = 6) And (wc = 1 Or wc = 8)), 20,
((wr = 1 Or wr = 8) And (wc = 4 Or wc = 5)) Or ((wr = 4 Or wr = 5) And (wc = 1 Or wc = 8)), 5,
(wr = 3 Or wr = 6) And (wc = 3 Or wc = 6), 15,
((wr = 2 Or wr = 7) And (wc >= 3 And wc <= 6)) Or ((wc = 2 Or wc = 7) And (wr >= 3 And wr <= 6)), -5,
3
)
)
}
),
totalFlips > 0
)
},
If(
CountRows(legalMoves) = 0,
false,
With(
{
pick: First(Sort(legalMoves, posWeight * 4 + totalFlips, SortOrder.Descending)),
player: cpuColor,
opp: If(cpuColor = "Black", "White", "Black")
},
With(
{
thisRow: pick.mvRow,
thisCol: pick.mvCol
},
With(
{
flipsByDir: ForAll(
colDirs,
{
dr: dr,
dc: dc,
count: With(
{
steps: ForAll(
Sequence(7),
{
i: Value,
color: With(
{ rr: thisRow + dr * Value, cc: thisCol + dc * Value },
If(
rr < 1 Or rr > 8 Or cc < 1 Or cc > 8,
"Off",
With(
{ cellB: LookUp(colBoard, Row = rr And Col = cc) },
If(IsBlank(cellB), "Off", cellB.Color)
)
)
)
}
)
},
With(
{
stopIdxB: First(
Sort(Filter(steps, color <> opp), i, SortOrder.Ascending)
)
},
If(
IsBlank(stopIdxB) Or stopIdxB.color <> player Or stopIdxB.i = 1,
0,
stopIdxB.i - 1
)
)
)
}
)
},
UpdateIf(colBoard, Row = thisRow And Col = thisCol, {Color: player});
ForAll(
Filter(flipsByDir, count > 0),
ForAll(
Sequence(count),
UpdateIf(
colBoard,
Row = thisRow + dr * Value And Col = thisCol + dc * Value,
{Color: player}
)
)
);
Set(currentPlayer, opp);
Set(lastMessage, "CPU played " & Char(64 + thisCol) & thisRow);
If(
CountRows(
Filter(
colBoard,
Color = "Empty"
And Sum(
ForAll(
colDirs,
{
n: With(
{
steps: ForAll(
Sequence(7),
{
i: Value,
color: With(
{ rr: Row + dr * Value, cc: Col + dc * Value },
If(
rr < 1 Or rr > 8 Or cc < 1 Or cc > 8,
"Off",
With(
{ cellC: LookUp(colBoard, Row = rr And Col = cc) },
If(IsBlank(cellC), "Off", cellC.Color)
)
)
)
}
),
oppC: If(currentPlayer = "Black", "White", "Black")
},
With(
{
stopIdxC: First(
Sort(Filter(steps, color <> oppC), i, SortOrder.Ascending)
)
},
If(
IsBlank(stopIdxC) Or stopIdxC.color <> currentPlayer Or stopIdxC.i = 1,
0,
stopIdxC.i - 1
)
)
)
}
),
n
) > 0
)
) = 0,
With(
{
other: If(currentPlayer = "Black", "White", "Black")
},
If(
CountRows(
Filter(
colBoard,
Color = "Empty"
And Sum(
ForAll(
colDirs,
{
n: With(
{
steps: ForAll(
Sequence(7),
{
i: Value,
color: With(
{ rr: Row + dr * Value, cc: Col + dc * Value },
If(
rr < 1 Or rr > 8 Or cc < 1 Or cc > 8,
"Off",
With(
{ cellD: LookUp(colBoard, Row = rr And Col = cc) },
If(IsBlank(cellD), "Off", cellD.Color)
)
)
)
}
),
oppD: If(other = "Black", "White", "Black")
},
With(
{
stopIdxD: First(
Sort(Filter(steps, color <> oppD), i, SortOrder.Ascending)
)
},
If(
IsBlank(stopIdxD) Or stopIdxD.color <> other Or stopIdxD.i = 1,
0,
stopIdxD.i - 1
)
)
)
}
),
n
) > 0
)
) = 0,
Set(gameOver, true);
Set(
winnerText,
With(
{
b: CountRows(Filter(colBoard, Color = "Black")),
w: CountRows(Filter(colBoard, Color = "White"))
},
If(b > w, "BLACK WINS", If(w > b, "WHITE WINS", "DRAW"))
)
),
Set(
lastMessage,
Upper(currentPlayer) & " had no legal moves — " & Upper(other) & " plays again."
);
Set(currentPlayer, other)
)
),
false
)
)
)
)
)
)
)
Reset: =sideChosen And currentPlayer = userColor
Start: =sideChosen And Not gameOver And currentPlayer = cpuColor And cpuColor <> ""
Visible: =false
Width: =1
- SideSelectScrim:
Control: Rectangle@2.3.0
Properties:
BorderStyle: =BorderStyle.None
Fill: =RGBA(0, 0, 0, 0.72)
Height: =Parent.Height
Visible: =Not sideChosen
Width: =Parent.Width
- SideSelectCard:
Control: GroupContainer@1.5.0
Variant: ManualLayout
Properties:
BorderStyle: =BorderStyle.None
DropShadow: =DropShadow.Bold
Fill: =RGBA(246, 240, 224, 1)
Height: =340
Visible: =Not sideChosen
Width: =480
X: =(Parent.Width - 480) / 2
Y: =(Parent.Height - 340) / 2
Children:
- SideSelectEyebrow:
Control: Text@0.0.51
Properties:
Align: =Align.Center
FontColor: =RGBA(220, 68, 52, 1)
Height: =24
Size: =12
Text: ="CHOOSE YOUR SIDE"
Weight: ='TextCanvas.Weight'.Semibold
Width: =Parent.Width
Y: =36
- SideSelectTitle:
Control: Text@0.0.51
Properties:
Align: =Align.Center
Font: =Font.Georgia
FontColor: =RGBA(18, 24, 22, 1)
Height: =48
Size: =30
Text: ="Play against CPU"
Weight: ='TextCanvas.Weight'.Bold
Width: =Parent.Width
Y: =68
- SideSelectSubtitle:
Control: Text@0.0.51
Properties:
Align: =Align.Center
FontColor: =RGBA(100, 94, 80, 1)
Height: =22
Size: =13
Text: ="Black moves first. The opposing color will be played automatically."
Weight: ='TextCanvas.Weight'.Regular
Width: =Parent.Width - 48
X: =24
Y: =120
- PickBlackButton:
Control: Button@0.0.45
Properties:
Appearance: ='ButtonCanvas.Appearance'.Primary
BasePaletteColor: =RGBA(18, 24, 22, 1)
BorderRadius: =2
FontColor: =RGBA(246, 240, 224, 1)
FontSize: =14
FontWeight: =FontWeight.Semibold
Height: =52
OnSelect: |-
=Set(userColor, "Black");
Set(cpuColor, "White");
Set(sideChosen, true)
Text: ="PLAY BLACK (GO FIRST)"
Width: =200
X: =24
Y: =180
- PickWhiteButton:
Control: Button@0.0.45
Properties:
Appearance: ='ButtonCanvas.Appearance'.Primary
BasePaletteColor: =RGBA(246, 240, 224, 1)
BorderRadius: =2
FontColor: =RGBA(18, 24, 22, 1)
FontSize: =14
FontWeight: =FontWeight.Semibold
Height: =52
OnSelect: |-
=Set(userColor, "White");
Set(cpuColor, "Black");
Set(sideChosen, true)
Text: ="PLAY WHITE (GO SECOND)"
Width: =200
X: =Parent.Width - 200 - 24
Y: =180
- SideSelectHint:
Control: Text@0.0.51
Properties:
Align: =Align.Center
FontColor: =RGBA(100, 94, 80, 1)
Height: =20
Size: =11
Text: ="You can switch sides any time by tapping RESET."
Weight: ='TextCanvas.Weight'.Regular
Width: =Parent.Width
Y: =260
どうやって作ったか
Claude Code × MCP サーバーという仕組みを使っています。Claude Code に日本語で話しかけると、Power Apps Studio に直接変更が反映される、という構成です。
詳しい仕組みとセットアップ手順は別の動画でまとめています。


コメント