Unity C# SaveManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class SaveManager
{
    const string location = "Assets/Resources/Data";

    public static void SaveData<T>(string fileName, T template)
    {
        if (!Directory.Exists(location))
        {
            Directory.CreateDirectory(location);
        }
        string data = JsonUtility.ToJson(template);
        string path = Path.Combine(location, fileName);
        using (FileStream stream = new FileStream(path, FileMode.Create))
        {
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.Write(data);
            }
            stream.Close();
        }
        Debug.Log("game saved");
    }

    public static T LoadData<T>(string fileName) where T : class
    {
        T load = null;
        string read = "";
        string path = Path.Combine(location, fileName);
        if(!File.Exists(path))
        {
            return null;
        }

        using (FileStream stream=new FileStream(path,FileMode.Open))
        {
            using (StreamReader reader=new StreamReader(stream))
            {
                read = reader.ReadToEnd();
            }
            stream.Close();
        }
        load = JsonUtility.FromJson<T>(read);
            return load;
    }
}

Unity C# Stats.cs

using UnityEngine;

[System.Serializable]
public class Stats // ← MonoBehaviourを削除
{
    public int Level = 1;
    public int maxHp = 1;
    public int atk = 1;
    public int def = 1;
    public int mana = 1;
    public int manaXSecond = 5;
    public CharacterClass charClass = CharacterClass.warrior;
}

public enum CharacterClass
{
    warrior,
    maga,
    priest,
    paladin,
    shamano,
    druid,
    rogue,
    ranger
}

Unity player.cs

using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : Entity
{
    CameraFollow follow;
    [SerializeField]
    float rotSpeed = 2;
    [SerializeField]
    float scrollAmount = 3;
    [SerializeField]
    float minZoom = 10, maxZoom = 120;
    ActionController controller;
    const float second = 1;
    float manaCounter = 1;
    public SaveData data = new SaveData();
    // Start is called before the first frame update
    public override void Init()
    {
        base.Init();
        if (!photonView.IsMine) return;
        data = SaveManager.LoadData<SaveData>(data.characterName);
        if(data==null)
        {
            data = new SaveData();
        }
        controller = GetComponent<ActionController>();
        controller.sync = sync;
        controller.Init(this);
        var f = Resources.Load<CameraFollow>(StaticStrings.follow);
        follow = Instantiate(f, transform.position, transform.rotation);
        follow.Init(transform);
        WorldManager.instance.playerList.Add(transform);
        UIManager.instance.player = this;
        onDeathEvent = () =>
        {
            UIManager.instance.deathPanel.SetActive(true);
        };
    }

    public override void Tick()
    {
        UseCamera();
        if(controller.mana<stats.mana)
        {
            manaCounter -= Time.deltaTime;
            if (manaCounter<=0)
            {
                manaCounter = second;
                controller.mana += stats.manaXSecond;
                if (controller.mana > stats.mana) controller.mana = stats.mana;
            }
        }
        if (!CanMove()) return;
        float x = Input.GetAxisRaw(StaticStrings.horizontal);
        float y = Input.GetAxisRaw(StaticStrings.vertical);
        Vector3 move = (transform.right * x) + (transform.forward * y);
        move *= Time.deltaTime * moveMultipler * moveSpeed;
        move.y = rb.velocity.y;
        rb.velocity = move;
        sync.Move(x, y);
        controller.Tick(follow.transform,x,y);
    }

    void UseCamera()
    {
        float x = Input.GetAxis(StaticStrings.mouseX);
        float scroll = Input.GetAxisRaw(StaticStrings.scroll);
        Vector3 rot = follow.arm.rotation.eulerAngles;
        follow.transform.rotation = Quaternion.Euler(rot.x, rot.y + x * rotSpeed, rot.z);
        if(scroll!=0)
        {
            float val = scrollAmount * scroll;
            val += follow.cam.fieldOfView;
            val = Mathf.Clamp(val, minZoom, maxZoom);
            follow.cam.fieldOfView = val;
        }
    }

    bool CanMove()
    {
        if (isDeath) return false;
        return true;
    }

    public void Respawn()
    {
        transform.position = WorldManager.instance.respawnPoint.position;
        isDeath = false;
        hp = stats.maxHp;
        sync.IsDead(false);
        if(Photon.Pun.PhotonNetwork.IsConnected)
        {
            view.RPC("SyncronizeStat", Photon.Pun.RpcTarget.All, hp);
        }
    }
}

15パズル javascript

index.html

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="utf-8">
  <title>15Puzzle</title>
  <style>
    canvas {
      background: pink;
      display: block;
      margin: 0 auto;
      cursor: pointer;
    }
  </style>
</head>

<body>
  <canvas width="280" height="280">
    Canvas not supported.
  </canvas>

  <script src="js/main.js"></script>
</body>

</html>

main.js

'use strict';

(() => {
    class PuzzleRenderer {
        constructor(puzzle, canvas) {
            this.puzzle = puzzle;
            this.canvas = canvas;
            this.ctx = this.canvas.getContext('2d');
            this.TILE_SIZE = 70;
            this.img = document.createElement('img');
            this.img.src = 'img/animal1.png';
            this.img.addEventListener('load', () => {
                this.render();
            });
            this.canvas.addEventListener('click', e => {
                if (this.puzzle.getCompletedStatus()) {
                    return;
                }

                const rect = this.canvas.getBoundingClientRect();
                const col = Math.floor((e.clientX - rect.left) / this.TILE_SIZE);
                const row = Math.floor((e.clientY - rect.top) / this.TILE_SIZE);
                this.puzzle.swapTiles(col, row);
                this.render();

                if (this.puzzle.isComplete()) {
                    this.puzzle.setCompletedStatus(true);
                    this.renderGameClear();
                }
            });
        }

        renderGameClear() {
            this.ctx.fillStyle = 'rgba(0, 0, 0, 0.4)';
            this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
            this.ctx.font = '28px Arial';
            this.ctx.fillStyle = '#fff';
            this.ctx.fillText('GAME CLEAR!!', 40, 150);
        }

        render() {
            for (let row = 0; row < this.puzzle.getBoardSize(); row++) {
                for (let col = 0; col < this.puzzle.getBoardSize(); col++) {
                    this.renderTile(this.puzzle.getTile(row, col), col, row);
                }
            }
        }

        renderTile(n, col, row) {
            if (n === this.puzzle.getBlankIndex()) {
                this.ctx.fillStyle = '#eeeeee';
                this.ctx.fillRect(
                    col * this.TILE_SIZE,
                    row * this.TILE_SIZE,
                    this.TILE_SIZE,
                    this.TILE_SIZE
                );
            } else {
                this.ctx.drawImage(
                    this.img,
                    (n % this.puzzle.getBoardSize()) * this.TILE_SIZE,
                    Math.floor(n / this.puzzle.getBoardSize()) * this.TILE_SIZE,
                    this.TILE_SIZE,
                    this.TILE_SIZE,
                    col * this.TILE_SIZE,
                    row * this.TILE_SIZE,
                    this.TILE_SIZE,
                    this.TILE_SIZE
                );
            }
        }
    }

    class Puzzle {
        constructor(level) {
            this.level = level;
            this.tiles = [
                [0, 1, 2, 3],
                [4, 5, 6, 7],
                [8, 9, 10, 11],
                [12, 13, 14, 15],
            ];
            this.UDLR = [
                [0, -1], // up
                [0, 1], // down
                [-1, 0], // left
                [1, 0], // right
            ];
            this.isCompleted = false;
            this.BOARD_SIZE = this.tiles.length;
            this.BLANK_INDEX = this.BOARD_SIZE ** 2 - 1;
            do {
                this.shuffle(this.level);
            } while (this.isComplete());
        }

        getBoardSize() {
            return this.BOARD_SIZE;
        }

        getBlankIndex() {
            return this.BLANK_INDEX;
        }

        getCompletedStatus() {
            return this.isCompleted;
        }

        setCompletedStatus(value) {
            this.isCompleted = value;
        }

        getTile(row, col) {
            return this.tiles[row][col];
        }

        shuffle(n) {
            let blankCol = this.BOARD_SIZE - 1;
            let blankRow = this.BOARD_SIZE - 1;

            for (let i = 0; i < n; i++) {
                let destCol;
                let destRow;
                do {
                    const dir = Math.floor(Math.random() * this.UDLR.length);
                    destCol = blankCol + this.UDLR[dir][0];
                    destRow = blankRow + this.UDLR[dir][1];
                } while (this.isOutside(destCol, destRow));

                [
                    this.tiles[blankRow][blankCol],
                    this.tiles[destRow][destCol],
                ] = [
                        this.tiles[destRow][destCol],
                        this.tiles[blankRow][blankCol],
                    ];

                [blankCol, blankRow] = [destCol, destRow];
            }
        }

        swapTiles(col, row) {
            if (this.tiles[row][col] === this.BLANK_INDEX) {
                return;
            }

            for (let i = 0; i < this.UDLR.length; i++) {
                const destCol = col + this.UDLR[i][0];
                const destRow = row + this.UDLR[i][1];

                if (this.isOutside(destCol, destRow)) {
                    continue;
                }

                if (this.tiles[destRow][destCol] === this.BLANK_INDEX) {
                    [
                        this.tiles[row][col],
                        this.tiles[destRow][destCol],
                    ] = [
                            this.tiles[destRow][destCol],
                            this.tiles[row][col],
                        ];
                    break;
                }
            }
        }

        isOutside(destCol, destRow) {
            return (
                destCol < 0 || destCol > this.BOARD_SIZE - 1 ||
                destRow < 0 || destRow > this.BOARD_SIZE - 1
            );
        }

        isComplete() {
            let i = 0;
            for (let row = 0; row < this.BOARD_SIZE; row++) {
                for (let col = 0; col < this.BOARD_SIZE; col++) {
                    if (this.tiles[row][col] !== i++) {
                        return false;
                    }
                }
            }
            return true;
        }
    }

    const canvas = document.querySelector('canvas');
    if (typeof canvas.getContext === 'undefined') {
        return;
    }

    new PuzzleRenderer(new Puzzle(2), canvas);
})();

Javascript 迷路

index.html

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="utf-8">
    <title>My Maze</title>
</head>

<body>
    <canvas>
        Canvas not supported ...
    </canvas>

    <script src="js/main.js"></script>
</body>

</html>

main.js

'use strict';

(() => {
    class MazeRenderer {
        constructor(canvas) {
            this.ctx = canvas.getContext('2d');
            this.WALL_SIZE = 10;
        }

        render(data) {
            canvas.height = data.length * this.WALL_SIZE;
            canvas.width = data[0].length * this.WALL_SIZE;

            for (let row = 0; row < data.length; row++) {
                for (let col = 0; col < data[0].length; col++) {
                    if (data[row][col] === 1) {
                        this.ctx.fillRect(
                            col * this.WALL_SIZE,
                            row * this.WALL_SIZE,
                            this.WALL_SIZE,
                            this.WALL_SIZE
                        );
                    }
                }
            }
        }
    }

    class Maze {
        constructor(row, col, renderer) {
            if (row < 5 || col < 5 || row % 2 === 0 || col % 2 === 0) {
                alert('Size not valid!');
                return;
            }

            this.renderer = renderer;
            this.row = row;
            this.col = col;
            this.data = this.getData();
        }

        getData() {
            const data = [];

            for (let row = 0; row < this.row; row++) {
                data[row] = [];
                for (let col = 0; col < this.col; col++) {
                    data[row][col] = 1;
                }
            }

            for (let row = 1; row < this.row - 1; row++) {
                for (let col = 1; col < this.col - 1; col++) {
                    data[row][col] = 0;
                }
            }

            for (let row = 2; row < this.row - 2; row += 2) {
                for (let col = 2; col < this.col - 2; col += 2) {
                    data[row][col] = 1;
                }
            }

            for (let row = 2; row < this.row - 2; row += 2) {
                for (let col = 2; col < this.col - 2; col += 2) {
                    let destRow;
                    let destCol;

                    do {
                        const dir = row === 2 ?
                            Math.floor(Math.random() * 4) :
                            Math.floor(Math.random() * 3) + 1;
                        switch (dir) {
                            case 0: // up
                                destRow = row - 1;
                                destCol = col;
                                break;
                            case 1: // down
                                destRow = row + 1;
                                destCol = col;
                                break;
                            case 2: // left
                                destRow = row;
                                destCol = col - 1;
                                break;
                            case 3: // right
                                destRow = row;
                                destCol = col + 1;
                                break;
                        }
                    } while (data[destRow][destCol] === 1);

                    data[destRow][destCol] = 1;
                }
            }

            return data;
        }

        render() {
            this.renderer.render(this.data);
        }
    }

    const canvas = document.querySelector('canvas');
    if (typeof canvas.getContext === 'undefined') {
        return;
    }

    const maze = new Maze(21, 15, new MazeRenderer(canvas));
    maze.render();
})();

SNS

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>究極SNS</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        body {
            font-family: 'Segoe UI', Arial, sans-serif;
            background-color: #f0f2f5;
            color: #1c1e21;
            line-height: 1.5;
            transition: background-color 0.3s, color 0.3s;
        }
        body.dark-mode {
            background-color: #18191a;
            color: #e4e6eb;
        }
        .header {
            background-color: #1877f2;
            color: white;
            padding: 10px 20px;
            display: flex;
            align-items: center;
            justify-content: space-between;
            position: sticky;
            top: 0;
            z-index: 100;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .header input {
            padding: 10px 15px;
            border: none;
            border-radius: 25px;
            width: 350px;
            font-size: 14px;
            background-color: #ffffff;
        }
        .nav {
            display: flex;
            align-items: center;
        }
        .nav a, .nav button {
            color: white;
            margin-left: 25px;
            text-decoration: none;
            font-weight: 500;
            background: none;
            border: none;
            cursor: pointer;
            position: relative;
        }
        .nav a:hover::after, .nav button:hover::after {
            content: '';
            position: absolute;
            width: 50%;
            height: 2px;
            background-color: white;
            bottom: -5px;
            left: 25%;
        }
        .container {
            display: flex;
            max-width: 1400px;
            margin: 20px auto;
            gap: 25px;
        }
        .sidebar-left {
            width: 25%;
            padding: 15px;
            position: sticky;
            top: 70px;
            height: fit-content;
        }
        .sidebar-card {
            background-color: white;
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 2px 6px rgba(0,0,0,0.05);
            margin-bottom: 20px;
        }
        body.dark-mode .sidebar-card {
            background-color: #242526;
        }
        .profile-pic {
            width: 60px;
            height: 60px;
            border-radius: 50%;
            background-color: #ddd;
            margin: 0 auto 15px;
        }
        .badge {
            display: inline-block;
            background-color: #1877f2;
            color: white;
            padding: 2px 8px;
            border-radius: 12px;
            font-size: 12px;
            margin-left: 5px;
        }
        .sidebar-left a {
            display: block;
            color: #1877f2;
            text-decoration: none;
            margin: 12px 0;
            font-size: 15px;
        }
        .main-content {
            width: 50%;
        }
        .sidebar-right {
            width: 25%;
            padding: 15px;
            position: sticky;
            top: 70px;
            height: fit-content;
        }
        .post-box {
            background-color: white;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 2px 6px rgba(0,0,0,0.05);
            margin-bottom: 25px;
        }
        body.dark-mode .post-box {
            background-color: #242526;
        }
        .post-input {
            width: 100%;
            padding: 12px 15px;
            border: none;
            border-radius: 25px;
            background-color: #f0f2f5;
            resize: none;
            font-size: 16px;
            outline: none;
        }
        body.dark-mode .post-input {
            background-color: #3a3b3c;
            color: #e4e6eb;
        }
        .post-actions {
            display: flex;
            justify-content: space-between;
            margin-top: 15px;
            flex-wrap: wrap;
            gap: 10px;
        }
        .post-actions button {
            background-color: #e4e6eb;
            color: #050505;
            border: none;
            padding: 8px 15px;
            border-radius: 6px;
            cursor: pointer;
            font-weight: 500;
            transition: background-color 0.2s;
        }
        body.dark-mode .post-actions button {
            background-color: #3a3b3c;
            color: #e4e6eb;
        }
        .post-actions button:hover {
            background-color: #d8dade;
        }
        body.dark-mode .post-actions button:hover {
            background-color: #4a4b4c;
        }
        .post-actions .submit-btn {
            background-color: #1877f2;
            color: white;
        }
        .post {
            background-color: white;
            padding: 20px;
            border-radius: 10px;
            margin-bottom: 25px;
            box-shadow: 0 2px 6px rgba(0,0,0,0.05);
            position: relative;
        }
        body.dark-mode .post {
            background-color: #242526;
        }
        .post-header {
            display: flex;
            align-items: center;
            margin-bottom: 15px;
        }
        .post-header .profile-pic {
            width: 40px;
            height: 40px;
            margin-right: 12px;
        }
        .post-header h3 {
            margin: 0;
            font-size: 16px;
            font-weight: 600;
        }
        .post-header small {
            color: #65676b;
            font-size: 12px;
        }
        body.dark-mode .post-header small {
            color: #b0b3b8;
        }
        .post-options {
            position: absolute;
            top: 10px;
            right: 10px;
            cursor: pointer;
            color: #65676b;
        }
        .post-options:hover .options-menu {
            display: block;
        }
        .options-menu {
            display: none;
            position: absolute;
            top: 20px;
            right: 0;
            background-color: white;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            padding: 10px;
            z-index: 10;
        }
        body.dark-mode .options-menu {
            background-color: #3a3b3c;
        }
        .options-menu a {
            display: block;
            color: #050505;
            text-decoration: none;
            padding: 5px 10px;
        }
        body.dark-mode .options-menu a {
            color: #e4e6eb;
        }
        .post-image {
            width: 100%;
            height: 300px;
            background-color: #ddd;
            border-radius: 8px;
            margin: 15px 0;
        }
        .reactions {
            position: relative;
            display: inline-block;
        }
        .reactions:hover .reaction-menu {
            display: flex;
        }
        .reaction-menu {
            display: none;
            position: absolute;
            top: -45px;
            left: 0;
            background-color: white;
            padding: 8px;
            border-radius: 25px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            gap: 8px;
            z-index: 10;
        }
        body.dark-mode .reaction-menu {
            background-color: #3a3b3c;
        }
        .reaction {
            font-size: 22px;
            cursor: pointer;
            transition: transform 0.2s;
        }
        .reaction:hover {
            transform: scale(1.2);
        }
        .reaction-stats {
            margin-top: 5px;
            font-size: 14px;
            color: #65676b;
        }
        body.dark-mode .reaction-stats {
            color: #b0b3b8;
        }
        .post-actions-bar {
            display: flex;
            justify-content: space-around;
            padding: 10px 0;
            border-top: 1px solid #e4e6eb;
            border-bottom: 1px solid #e4e6eb;
            color: #65676b;
            font-size: 14px;
        }
        body.dark-mode .post-actions-bar {
            border-color: #3a3b3c;
            color: #b0b3b8;
        }
        .post-actions-bar span {
            cursor: pointer;
            padding: 5px 10px;
            border-radius: 5px;
        }
        .post-actions-bar span:hover {
            background-color: #f2f3f5;
        }
        body.dark-mode .post-actions-bar span:hover {
            background-color: #3a3b3c;
        }
        .comment-section {
            margin-top: 15px;
        }
        .comment {
            display: flex;
            align-items: flex-start;
            margin-top: 12px;
        }
        .comment .profile-pic {
            width: 32px;
            height: 32px;
            margin-right: 10px;
        }
        .comment-text {
            background-color: #f2f3f5;
            padding: 8px 12px;
            border-radius: 18px;
            font-size: 14px;
        }
        body.dark-mode .comment-text {
            background-color: #3a3b3c;
            color: #e4e6eb;
        }
        .comment-input {
            width: 100%;
            padding: 10px 15px;
            border: none;
            border-radius: 25px;
            background-color: #f0f2f5;
            font-size: 14px;
            margin-top: 10px;
        }
        body.dark-mode .comment-input {
            background-color: #3a3b3c;
            color: #e4e6eb;
        }
        .chat-window {
            background-color: white;
            border-radius: 10px;
            padding: 15px;
            box-shadow: 0 2px 6px rgba(0,0,0,0.05);
        }
        body.dark-mode .chat-window {
            background-color: #242526;
        }
        .chat-message {
            margin: 10px 0;
        }
        .chat-message.sent .comment-text {
            background-color: #1877f2;
            color: white;
            margin-left: auto;
        }
        .notification-popup {
            position: fixed;
            bottom: 20px;
            right: 20px;
            background-color: white;
            padding: 15px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            z-index: 200;
        }
        body.dark-mode .notification-popup {
            background-color: #242526;
        }
        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0,0,0,0.5);
            justify-content: center;
            align-items: center;
            z-index: 200;
        }
        .modal-content {
            background-color: white;
            padding: 25px;
            border-radius: 10px;
            width: 600px;
            max-height: 80vh;
            overflow-y: auto;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
        }
        body.dark-mode .modal-content {
            background-color: #242526;
        }
        .footer {
            background-color: white;
            padding: 20px;
            text-align: center;
            color: #65676b;
            border-top: 1px solid #e4e6eb;
            font-size: 13px;
        }
        body.dark-mode .footer {
            background-color: #18191a;
            color: #b0b3b8;
            border-color: #3a3b3c;
        }
        .footer a {
            color: #65676b;
            text-decoration: none;
            margin: 0 10px;
        }
        body.dark-mode .footer a {
            color: #b0b3b8;
        }
        .mobile-menu {
            display: none;
            position: fixed;
            top: 60px;
            left: 0;
            width: 100%;
            background-color: #1877f2;
            padding: 15px;
            z-index: 99;
        }
        .mobile-menu a {
            color: white;
            display: block;
            margin: 10px 0;
            text-decoration: none;
        }
        @media (max-width: 900px) {
            .container {
                flex-direction: column;
                margin: 10px;
            }
            .sidebar-left, .main-content, .sidebar-right {
                width: 100%;
                position: static;
            }
            .header input {
                width: 150px;
            }
            .nav {
                display: none;
            }
            .mobile-menu {
                display: block;
            }
        }
    </style>
</head>
<body>
    <!-- ヘッダー -->
    <div class="header">
        <h1>究極SNS</h1>
        <input type="text" placeholder="友達、投稿、グループを検索">
        <div class="nav">
            <a href="#">ホーム</a>
            <a href="#">友達</a>
            <a href="#">メッセージ</a>
            <a href="#">通知</a>
            <a href="#">プロフィール</a>
            <button onclick="document.body.classList.toggle('dark-mode')">ダークモード</button>
        </div>
    </div>
    <div class="mobile-menu">
        <a href="#">ホーム</a>
        <a href="#">友達</a>
        <a href="#">メッセージ</a>
        <a href="#">通知</a>
        <a href="#">プロフィール</a>
        <a href="#" onclick="document.body.classList.toggle('dark-mode')">ダークモード</a>
    </div>

    <!-- メインコンテンツ -->
    <div class="container">
        <!-- 左サイドバー -->
        <div class="sidebar-left">
            <div class="sidebar-card">
                <div class="profile-pic"></div>
                <h3>ユーザー名 <span class="badge">認証済み</span></h3>
                <a href="#">プロフィールを見る</a>
                <a href="#">友達 (128)</a>
                <a href="#">フォロワー (350)</a>
            </div>
            <div class="sidebar-card">
                <h4>メニュー</h4>
                <a href="#">グループ</a>
                <a href="#">イベント</a>
                <a href="#">マーケットプレイス</a>
                <a href="#">設定</a>
            </div>
        </div>

        <!-- 中央(投稿エリア) -->
        <div class="main-content">
            <!-- 投稿入力エリア -->
            <div class="post-box">
                <textarea class="post-input" rows="3" placeholder="何を思ってる?"></textarea>
                <div class="post-actions">
                    <button>写真/動画</button>
                    <button>タグ友達</button>
                    <button>ライブ配信</button>
                    <button>イベント作成</button>
                    <button class="submit-btn" onclick="document.getElementById('postModal').style.display='flex'">投稿</button>
                </div>
            </div>

            <!-- 投稿1 -->
            <div class="post">
                <div class="post-header">
                    <div class="profile-pic"></div>
                    <div>
                        <h3>山田太郎 <span class="badge">管理者</span></h3>
                        <small>2025年3月29日 10:30 ・ 公開</small>
                    </div>
                    <div class="post-options">⋯
                        <div class="options-menu">
                            <a href="#">編集</a>
                            <a href="#">削除</a>
                            <a href="#">非表示</a>
                        </div>
                    </div>
                </div>
                <p>新しいプロジェクトの進捗報告!チームで頑張ってます。</p>
                <div class="post-image"></div>
                <div class="reactions">
                    <div class="reaction-stats">👍 12 ❤️ 5 😂 3 😮 2</div>
                    <div class="reaction-menu">
                        <span class="reaction">👍</span>
                        <span class="reaction">❤️</span>
                        <span class="reaction">😂</span>
                        <span class="reaction">Grav😮</span>
                        <span class="reaction">😢</span>
                    </div>
                </div>
                <div class="post-actions-bar">
                    <span>リアクション</span>
                    <span>コメント</span>
                    <span>シェア</span>
                </div>
                <div class="comment-section">
                    <div class="comment">
                        <div class="profile-pic"></div>
                        <div class="comment-text"><strong>佐藤花子</strong>: すごい進捗だね!</div>
                    </div>
                    <div class="comment">
                        <div class="profile-pic"></div>
                        <div class="comment-text"><strong>鈴木次郎</strong>: お疲れ様!</div>
                    </div>
                    <input type="text" class="comment-input" placeholder="コメントを入力...">
                </div>
            </div>

            <!-- 投稿2 -->
            <div class="post">
                <div class="post-header">
                    <div class="profile-pic"></div>
                    <div>
                        <h3>田中優子</h3>
                        <small>2025年3月29日 09:15 ・ 友達のみ</small>
                    </div>
                    <div class="post-options">⋯
                        <div class="options-menu">
                            <a href="#">編集</a>
                            <a href="#">削除</a>
                            <a href="#">非表示</a>
                        </div>
                    </div>
                </div>
                <p>週末の温泉旅行が楽しみすぎる!</p>
                <div class="reactions">
                    <div class="reaction-stats">👍 8 ❤️ 6 😢 1</div>
                    <div class="reaction-menu">
                        <span class="reaction">👍</span>
                        <span class="reaction">❤️</span>
                        <span class="reaction">😂</span>
                        <span class="reaction">😮</span>
                        <span class="reaction">😢</span>
                    </div>
                </div>
                <div class="post-actions-bar">
                    <span>リアクション</span>
                    <span>コメント</span>
                    <span>シェア</span>
                </div>
            </div>
        </div>

        <!-- 右サイドバー -->
        <div class="sidebar-right">
            <div class="sidebar-card">
                <h4>友達リスト</h4>
                <p><strong>佐藤花子</strong> - オンライン</p>
                <p><strong>鈴木次郎</strong> - 5分前</p>
                <p><strong>高橋健太</strong> - オフライン</p>
            </div>
            <div class="sidebar-card">
                <h4>グループ</h4>
                <p><a href="#">プロジェクトチーム</a> - 15人</p>
                <p><a href="#">温泉旅行クラブ</a> - 32人</p>
            </div>
            <div class="chat-window">
                <h4>チャット - 佐藤花子</h4>
                <div class="chat-message">
                    <div class="comment-text">おはよう!週末の予定は?</div>
                </div>
                <div class="chat-message sent">
                    <div class="comment-text">おはよう!温泉行くよ!</div>
                </div>
                <input type="text" class="comment-input" placeholder="メッセージを入力...">
            </div>
        </div>
    </div>

    <!-- 投稿モーダル -->
    <div id="postModal" class="modal">
        <div class="modal-content">
            <h3>投稿を作成</h3>
            <textarea rows="6" placeholder="詳細を書いてね" style="width: 100%; padding: 10px;"></textarea>
            <div style="margin: 15px 0;">
                <label>公開範囲: </label>
                <select style="padding: 5px;">
                    <option>公開</option>
                    <option>友達のみ</option>
                    <option>自分のみ</option>
                </select>
            </div>
            <div class="post-actions">
                <button onclick="document.getElementById('postModal').style.display='none'">キャンセル</button>
                <button class="submit-btn">投稿</button>
            </div>
        </div>
    </div>

    <!-- 通知ポップアップ -->
    <div class="notification-popup">
        <p><strong>佐藤花子</strong>があなたの投稿にリアクションしました。</p>
    </div>

    <!-- フッター -->
    <div class="footer">
        <p>© 2025 究極SNS. All rights reserved.</p>
        <p><a href="#">プライバシー</a> | <a href="#">利用規約</a> | <a href="#">サポート</a> | <a href="#">言語</a></p>
    </div>

    <script>
        // 簡易的な通知ポップアップの表示制御(サンプル)
        setTimeout(() => {
            document.querySelector('.notification-popup').style.display = 'block';
            setTimeout(() => {
                document.querySelector('.notification-popup').style.display = 'none';
            }, 3000);
        }, 2000);
    </script>
</body>
</html>

ダンジョンのギミック

1. ダンジョンの構成要素

  • 入口・出口
    • プレイヤーがダンジョンに入るポイントと、クリアのために到達する出口。
  • 部屋(Room)
    • 敵との戦闘やイベントが起こる場所。
    • 宝箱やNPCとの出会いが配置可能。
  • 通路(Corridor)
    • 部屋同士を繋ぐ経路。
    • 単純な一本道、迷路、あるいは分岐などが考えられる。
  • 罠(Trap)
    • プレイヤーの行動を制限・妨害する仕掛け。
  • 鍵や扉
    • 特定のアイテムや条件を満たさないと先へ進めない仕掛け。

2. 敵の出現パターン

  • 固定配置型
    • 敵が決まった場所に存在。
  • ランダムエンカウント型
    • 移動時や特定条件でランダムに敵が出現。
  • 条件トリガー型
    • 宝箱を開けたりスイッチを押すと敵が出現。

3. アイテム配置ロジック

  • 宝箱の配置
    • 回復アイテムや装備、重要な鍵アイテムを適度に分散。
  • ドロップアイテム
    • 敵がランダムで落とすアイテム。

4. 探索と謎解き要素

  • パズルギミック
    • スイッチやレバー、順番通りに動かすパズルなど。
  • ヒントの設置
    • 壁画やメモ、NPCの会話などでプレイヤーに手がかりを与える。

5. 難易度調整ロジック

  • ダンジョン階層
    • 下に行くほど敵が強くなるような階層型。
  • プレイヤーレベル連動
    • プレイヤーのレベルに応じて敵や報酬の内容が変わる。

6. 報酬のロジック

  • ボス討伐時の報酬
    • 装備品、経験値、特別なスキル。
  • クリア後のリプレイ性
    • 特定条件を満たしてクリアすると追加報酬や新規ルートが解放。

CSS メディアクエリー

style.css

@charset "utf-8";

.card {
    border: 1px solid #ccc;
    box-sizing: border-box;
    padding: 16px;
    max-width: 600px;
    margin: 0 auto;

    &:hover {
        box-shadow: 0 0 8px rgb(0 0 0 / 0.3);
    }

    h2 {
        margin: 0;
        border-bottom: 1px solid #ccc;
        text-align: center;
        font-size: 18px;
        padding-bottom: 8px;
    }

    p {
        margin: 16px 0 0;
        line-height: 1.6;
    }
}

@media (width >=600px) {
    .card h2 {
        text-align: left;
    }
}

index.html

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My CSS Nesting</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>
  <section class="card">
    <h2>こんにちは</h2>
    <p>こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。こんにちは。</p>
  </section>
</body>

</html>

PS6企画書

PlayStation 6(PS6)企画書

1. コンセプト

次世代ゲーミング体験を創造する、革新的で没入感の高いゲームプラットフォーム。

2. 製品概要

  • 名称:PlayStation 6 (PS6)
  • 発売予定年:2028年
  • コンセプトフレーズ:「境界を超えたリアル」

3. 特徴と機能

  • 超リアルグラフィック:8K~16K対応、高度なレイトレーシング技術。
  • フルダイブ型VR対応:完全没入型のVR体験を提供。
  • ハプティックと触覚技術:全身で感じられる振動フィードバックシステム。
  • クラウド統合:高速クラウドストリーミングとAIベースのインタラクション。
  • 環境連動型ゲームプレイ:プレイヤーの環境に応じてゲーム内環境が動的に変化。

4. 技術仕様

  • プロセッサ:次世代AMDカスタムプロセッサ(Zen 6ベース)
  • グラフィック:次世代RDNA 5アーキテクチャ
  • メモリ:64GB GDDR7
  • ストレージ:SSD 4TB(超高速ロード技術)
  • 接続性:Wi-Fi 7、Bluetooth 6.0、USB-C 4.0、Thunderbolt 5
  • VRデバイス:専用フルダイブVRヘッドセット「PS VR Dive」対応

5. ソフトウェアラインナップ(仮)

  • ファーストパーティタイトル
    • 新規AAAオープンワールドRPG
    • グランツーリスモ 8
    • ホライゾン:新章
  • サードパーティタイトル
    • 大手サードパーティ各社と協力した大型IPタイトルの新作

6. マーケティング戦略

  • グローバルイベントを開催し、実機体験型プロモーションを展開。
  • SNSや動画プラットフォームを駆使したバイラルマーケティング。
  • 世界各地の主要都市でVR体験イベントを開催。

7. ターゲットユーザー

  • ゲーム愛好家(コアゲーマー)
  • テクノロジーに関心の高い若年層から中年層
  • VR/AR市場の新規ユーザー層

8. 市場目標

  • 世界累計販売台数:初年度1500万台
  • VR市場シェアの拡大

以上をもって、PlayStation 6の新たなゲーム体験を世界に提供します。