Updated:

1. Rules (once)

/gamerule natural_health_regeneration false
/difficulty hard
/gamerule keep_inventory false

In 1.21.10 and older the first rule is naturalRegeneration. See the gamerule list.

2. Show health

/scoreboard objectives add hp health "♥"
/scoreboard objectives setdisplay list hp
/scoreboard objectives setdisplay below_name hp

3. World border (once)

/worldborder center 0 0
/worldborder set 1000

4. Start: spread players

/scoreboard objectives add died deathCount
/scoreboard players set @a died 0
/gamemode survival @a
/effect give @a instant_health 1 10 true
/spreadplayers 0 0 150 450 false @a
/worldborder set 50 3600s

Players are placed within 450 blocks of the center and at least 150 blocks apart. Use true to keep teams together. The border then shrinks to 50 blocks over an hour. Since Java 1.21.11 the time is in ticks unless you add s; in 1.21.10 and older write 3600 (seconds).

5. Fallen players spectate (repeating)

/gamemode spectator @a[scores={died=1..},gamemode=survival]

6. Winner (repeating)

/scoreboard objectives add uhc dummy
/execute store result score #alive uhc if entity @a[gamemode=survival]
/execute if score #alive uhc matches 1 unless entity @e[type=marker,tag=uhc_end] run title @a title [{"selector":"@a[gamemode=survival]"},{"text":" wins!"}]
/execute if score #alive uhc matches 1 unless entity @e[type=marker,tag=uhc_end] run summon marker ~ ~ ~ {Tags:["uhc_end"]}

Run the first line once. The marker makes the title show only once; kill it before the next game.

Troubleshooting

Check your command

The Command Error Doctor checks common syntax mistakes in your browser.