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の新たなゲーム体験を世界に提供します。

Meta Quest 4 企画書

Meta Quest 4 企画書(サンプル)

1. 企画概要

  • 企画名:Meta Quest 4(メタ クエスト フォー)
  • 目的:次世代のVR/AR体験の可能性を広げ、より高い没入感と利便性を提供する。
  • ターゲット:VRゲーム・エンターテインメントユーザー、企業の研修・設計シミュレーション用途など、多岐にわたるユーザー層

2. 背景・課題

  1. VR市場の拡大
    • ゲーム、エンタメだけでなく、医療、教育、産業用途でもVR/AR活用が進んでいる。
    • 手頃な価格と使いやすさを両立したスタンドアロン型ヘッドセット需要が高まっている。
  2. 現行製品(Meta Quest 2/3など)の限界
    • バッテリー駆動時間の制約
    • 解像度や視野角のさらなる向上ニーズ
    • AR機能(カラーパススルーや空間認識)の強化ニーズ
  3. 市場の競合状況
    • 競合他社からも次世代スタンドアロン型HMD(Head-Mounted Display)のリリースが予想される。
    • 高性能化、軽量化、UX向上に向けた研究開発が激化。

3. 製品コンセプト

  1. 「軽量&高解像度」
    • 持ち運びやすく、長時間装着しても疲れにくい。
    • 4K近似の解像度を両眼に提供し、没入感を大幅に向上。
  2. 「シームレスなVR/AR体験」
    • 高精度なカラーパススルーを搭載し、バーチャルとリアルの行き来をスムーズに。
    • コントローラ不要のハンドトラッキング強化により、操作性を直感的に。
  3. 「拡張されるエコシステム」
    • 既存のQuestプラットフォームとアプリ互換性を保持しながら、新機能をサポート。
    • メタバース事業との連携強化によるソーシャルVR体験の深化。

4. 主な機能・特徴

  1. 高解像度ディスプレイと広視野角
    • 両眼合計で4Kを超える解像度(片眼2K以上)
    • Pancakeレンズや新素材を採用し、視野角約110度〜120度を目指す
  2. パワフルなプロセッサと大容量メモリ
    • XR専用チップ(次世代Snapdragon等)で高品質グラフィックを実現
    • 12GB以上のメモリを搭載し、同時処理性能を向上
  3. 強化されたパススルー機能
    • 高画質カメラにより、カラーARモードを実現
    • 空間認識精度を高め、障害物警告や手元操作のARガイド表示が可能
  4. ハンドトラッキングとフェイストラッキング
    • コントローラレスの操作性向上(オプションで新世代コントローラも用意)
    • フェイストラッキングを標準搭載し、アバターの表情反映をリアルタイムに行う
  5. 軽量化と快適性
    • フロントヘビーを軽減するため、バッテリー位置や内部構造を最適化
    • フェイスクッションの素材改良で長時間使用時の不快感を低減
  6. 長時間バッテリー駆動
    • 3~4時間の連続プレイを目標(前モデル比15〜20%アップ)
    • 高速充電対応、30分で50%まで回復可能
  7. エコシステムとの連携
    • Meta Quest Storeとの互換性維持
    • メタバースプラットフォーム「Horizon Worlds」を軸にソーシャルVRイベントを拡張
    • 企業向けアプリや学習プラットフォームとの連携を強化

5. 仕様イメージ(例)

項目Meta Quest 4(試作)
ディスプレイ両眼合計解像度 約4K(片眼2K以上)
レンズタイプPancakeレンズ
視野角(FOV)110~120度
CPU/GPU次世代Snapdragon XRチップ
メモリ12GB~
ストレージ128GB/256GB/512GB(複数モデル)
パススルー機能高解像度カラー
バッテリー駆動時間3~4時間(連続稼働)
重量約500g(改良目標)
接続スタンドアロン&Wi-Fi 6E対応
コントローラ新世代タッチコントローラ or ハンドトラッキング
OSMeta Quest OS (Androidベース)

6. 開発・リリーススケジュール(例)

フェーズ期間主なタスク
企画・要件定義2025年4月~5月マーケット調査、技術要件・デザイン要件の策定
試作・デザイン検証2025年6月~8月外観・内部構造プロトタイプ作成、主要コンポーネント選定、初期ユーザーテスト
ハードウェア最終化2025年9月~11月量産設計決定、製造ラインテスト、品質管理システムの構築
ソフトウェア統合2025年12月~2026年2月OS最適化、アプリ互換テスト、開発者向けSDK整備
量産・テスト販売2026年3月~4月量産開始、限定地域での販売テスト、マーケティング施策事前準備
グローバルリリース2026年5月世界主要市場での正式販売開始

7. 販売戦略

  1. ターゲットセグメント
    • ハイエンド志向のゲーマー、クリエイター
    • 医療・教育・産業分野のトレーニング用途(BtoB展開)
    • メタバース/ソーシャルVRサービス利用者
  2. 価格帯
    • スタンダードモデル:¥50,000~¥60,000(128GB)
    • ハイエンドモデル:¥70,000~¥80,000(256GBまたは512GB)
    • 企業向けエンタープライズモデル:カスタマイズによる別途見積もり
  3. プロモーション施策
    • 主要テックイベント・ゲームイベントでの体験ブース出展
    • 大手クリエイターやインフルエンサーとのタイアップ配信
    • 法人向け展示会(医療機器展、教育ICT展など)でのデモンストレーション
    • 既存Meta Questユーザーへのアップグレード特典・下取りプログラム
  4. 販売チャネル
    • 公式オンラインストア、家電量販店、ゲームショップ
    • グローバルECプラットフォーム(Amazonなど)
    • 企業向けには専用の営業・代理店チャンネルを構築

8. リスクと対応策

  1. 競合製品の性能・価格競争
    • リスク:他社のスタンドアロン型HMDが安価かつ高性能でリリースされる
    • 対応策:Questプラットフォームとの互換性やメタバース連携など、エコシステムによる差別化を訴求
  2. 部品調達・コスト高騰
    • リスク:半導体不足や原材料コスト上昇による価格高騰
    • 対応策:製造拠点・サプライチェーンの多様化、長期契約による部品価格の安定化
  3. ユーザーUX・コンテンツ不足
    • リスク:ハードは高性能でも対応コンテンツが不足すると利用が促進されない
    • 対応策:開発者支援プログラム拡充、投資や共同開発による大型タイトル・キラーコンテンツの創出
  4. 法規制・プライバシー問題
    • リスク:フェイストラッキングや位置情報の扱いによるプライバシー懸念
    • 対応策:データ利用の透明性確保、オプトイン/オプトアウト設定、リージョン別の法規制対応

9. 期待効果

  1. 没入感の進化によるユーザー体験の向上
    • 4K超の高解像度&広視野角により、VR空間での“存在感”がさらにリアルに。
  2. メタバース事業の拡大
    • 新型ヘッドセットを媒介として、メタバース上でのアクティブユーザー数・課金売上が増加。
  3. 企業ユースの拡大
    • 研修、設計シミュレーション、遠隔医療教育など多様なBtoB用途で稼働が見込まれ、ライセンス収益やサブスクリプションサービスの拡大が期待。
  4. プラットフォームのエコシステム強化
    • アプリ開発者やコンテンツクリエイターが参入しやすい環境を整えることで、Meta Quest全体の競争優位性を向上。

10. まとめ

Meta Quest 4は、「軽量&高解像度」「リアルと仮想をシームレスに繋ぐAR機能」「強固なエコシステムの継承と拡張」の3つをコアバリューとする次世代型スタンドアロンHMDです。VR/AR市場がさらに拡大・多様化するなか、

  • 使いやすさとハイエンド性能の両立
  • 幅広いコンテンツ・アプリケーションとの連動
  • 法人向けニーズへの対応

を通じて、世界中のユーザーに“もう一つの現実”を提供し、メタバース時代をリードする製品となることを目指します。

企画書:Windows 12

企画書:Windows 12

1. 概要

  • プロジェクト名: Windows 12 開発プロジェクト
  • 提案者: (あなたのチーム/部署名などを記載)
  • 目的: Windows 11 の次世代OSとして、UI・UX・クラウド連携・セキュリティのさらなる強化を図り、ユーザーに安全かつ便利なコンピューティング環境を提供する。

2. 背景・課題

  1. Windows 11 の普及とユーザーニーズ
    • Windows 11 は現行OSとして機能しているが、新しい体験やさらなる改良を望む声がある。
    • タッチ操作・音声操作などマルチインターフェースへの最適化が進む中、UI改善と生産性向上の両立が課題。
  2. クラウド連携の需要増加
    • 在宅勤務やリモート学習の定着で、クラウドストレージ、オンラインコラボレーションツールへの需要が急増。
    • Microsoft 365 やAzure など、自社クラウドサービスとのさらなる連携が必要。
  3. セキュリティ強化
    • ランサムウェア、標的型攻撃などサイバー脅威が高度化。
    • OSレベルでのゼロトラストセキュリティ対策や暗号化技術、マルチ要素認証との連携強化が必須。
  4. AIアシスタントとの統合
    • MicrosoftのAI技術(例: Cortana / Bing Chat / その他LLMなど)をよりOSレベルに深く取り込み、ユーザー体験を向上させるニーズがある。

3. 目的・ゴール

  • UI/UX の再定義: 直感的で分かりやすく、アプリやクラウドサービスとの親和性を高めた新UIの提供。
  • 生産性向上: 作業効率を支援する機能(ウィンドウの整理、アプリ間連携、自動翻訳など)を強化。
  • 高いセキュリティ: OSレベルのセキュリティ機能を強化し、企業や個人が安心して利用できるプラットフォームを実現。
  • クラウド連携強化: OneDrive や SharePoint をさらに活用し、ストレージや共同作業をOS標準機能としてシームレスに統合。
  • AIアシスタントの活用: Windowsシステム全体を横断してタスクを支援するAI機能を実装し、スマートな作業環境を提供。

4. ターゲットユーザー

  1. ビジネスユーザー
    • リモートワークやハイブリッドワークの運用が多い企業やフリーランス。
    • セキュリティや生産性に強いOSを求める法人顧客。
  2. コンシューマー(一般ユーザー)
    • 最新の機能やUI/UXを快適に使いたい個人。
    • PC初心者から上級者まで幅広い層。
  3. 教育機関
    • オンライン学習や共同作業プラットフォームを活用する学校・大学。
    • セキュリティや遠隔操作管理の機能が求められる。

5. 特徴・機能

  1. 新デザインUI「Fluent Next」
    • ウィンドウ操作、通知センター、スタートメニューの刷新。
    • アクセシビリティを強化し、より柔軟でモダンなデザイン。
  2. クラウド連携の強化
    • OSレベルで OneDrive や Teams が組み込まれ、ファイル共有・共同編集がシームレスに。
    • ストレージ残容量やファイル更新情報をリアルタイムで通知。
  3. Windows Copilot(AIアシスタント)の進化
    • 音声入力やチャット操作など、各シーンに応じてマルチタスクを支援。
    • 自動サマリー作成やメール下書きなどをサポート。
  4. セキュリティ / ゼロトラスト対応
    • TPM 2.0 を活用したハードウェアレベルの暗号化と認証強化。
    • フィッシング防止やマルウェア対策をさらに高度化。
    • 企業向けにはクラウドポリシーと連携し、認証管理を一元化。
  5. パフォーマンス最適化 / 省電力
    • OSカーネルと電源管理の改善により、省電力モード時のバッテリー持続時間を向上。
    • ゲーミングモードやクリエイティブモードなど、状況に応じたリソース割り当てを自動調整。
  6. 拡張ディスプレイ & マルチデバイス対応
    • タブレットや折りたたみ型PCなど、画面サイズが変化するデバイスでの最適化。
    • スマホとの連携強化(電話・メッセージ通知、写真自動同期など)。

6. 開発スケジュール(例)

フェーズ期間主なタスク
要件定義20XX年 Q1~Q2UIデザイン要件決定、主要機能の企画設計
開発・実装20XX年 Q3~20XY年Q1コア機能実装、セキュリティ強化
内部テスト
パブリックβ版20XY年 Q2パブリックベータテスト
外部フィードバック回収
正式リリース20XY年 Q3最終調整・品質保証
グローバルローンチ

7. 予算・リソース

  • 人件費: エンジニア、UI/UXデザイナー、QA、プロジェクトマネージャーなど。
  • インフラ費: クラウドサーバー、CI/CD環境、テスト機材購入など。
  • マーケティング費: リリース前後の広告宣伝費、イベント開催費など。
  • 合計予算の目安: (現実的には大きな額になりますが、具体的な金額はプロジェクト規模に依存)

8. 成功指標 (KPI)

  1. アップグレード率: 既存ユーザーからの移行数、Windows 10/11ユーザーのアップデート率。
  2. エラー/クラッシュレポートの減少率: OSの安定性・信頼性を継続してモニタリング。
  3. クラウドサービス利用率: OneDrive / Teams などの利用継続率、導入企業数。
  4. ユーザー満足度: フィードバックやアンケートによるNPS(ネット・プロモーター・スコア)など。

9. リスクと対策

  1. 既存アプリ互換性
    • 過去OS向けアプリが動作しない問題。
    • → 互換レイヤーや仮想化技術を提供し、互換性向上に注力。
  2. 大規模なUI変更に対する反発
    • → カスタマイズ性を高め、ユーザーが旧UIレイアウトへ切り替え可能なモードを検討。
  3. セキュリティ脆弱性
    • → リリース前のセキュリティ監査を強化し、定期的に更新プログラムを配信。

10. まとめ

  • Windows 12 は 「セキュリティ強化」「UI/UX革新」「AI活用」「クラウド統合」 を核とした次世代OSとなる。
  • 企業・教育機関・一般ユーザーなど幅広い層に向けて、安全かつ効率的な作業環境 を提供することをゴールとする。
  • 今後は段階的に開発と検証を進め、ユーザーからのフィードバックを取り込みながら 正式リリース を目指す。

C#入門サイト

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="description" content="C# オールインワン入門サイト">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>オールインワン C# 入門サイト</title>

  <!-- ★ スタイル(CSS)をまとめて定義 ★ -->
  <style>
    /* ページ全体 */
    body {
      margin: 0;
      padding: 0;
      font-family: sans-serif;
      line-height: 1.6;
      background: #f9f9f9;
    }

    /* ヘッダー */
    header {
      background: #f0f0f0;
      padding: 10px;
    }

    header h1 {
      margin: 0;
      font-size: 1.5em;
    }

    /* ナビゲーション */
    nav ul {
      list-style: none;
      padding: 0;
      display: flex;
      gap: 10px;
      margin-top: 5px;
    }

    nav a {
      text-decoration: none;
      color: #333;
      font-weight: bold;
    }

    nav a:hover {
      text-decoration: underline;
    }

    /* メインコンテンツ */
    main {
      max-width: 900px;
      margin: 20px auto;
      padding: 20px;
      background: #fff;
      box-shadow: 0 0 4px rgba(0,0,0,0.1);
    }

    main h2 {
      margin-top: 0;
      border-left: 6px solid #333;
      padding-left: 8px;
      margin-bottom: 15px;
    }
    main h3 {
      margin-bottom: 5px;
    }

    /* コードブロック */
    pre {
      background: #fafafa;
      padding: 10px;
      overflow-x: auto;
    }
    code {
      font-family: Consolas, monospace;
    }

    /* フォームなど(クイズ用) */
    form section {
      margin-bottom: 20px;
    }
    #result {
      margin-top: 20px;
      background: #eef;
      padding: 10px;
      border: 1px solid #ccf;
      display: inline-block;
    }

    /* フッター */
    footer {
      text-align: center;
      padding: 10px;
      background: #f0f0f0;
      margin-top: 20px;
    }

    /* セクション間の余白調整 */
    section {
      margin-bottom: 40px;
    }
  </style>
</head>
<body>

  <!-- ★ ヘッダーとナビゲーション ★ -->
  <header>
    <h1>オールインワン C# 入門サイト</h1>
    <nav>
      <ul>
        <li><a href="#top">トップ</a></li>
        <li><a href="#environment">環境構築 &amp; .NET</a></li>
        <li><a href="#basics">C#の基本</a></li>
        <li><a href="#syntax">基本文法</a></li>
        <li><a href="#control-flow">条件分岐・ループ</a></li>
        <li><a href="#oop">オブジェクト指向</a></li>
        <li><a href="#advanced">応用トピック</a></li>
        <li><a href="#debugging">デバッグ &amp; テスト</a></li>
        <li><a href="#quiz">クイズ</a></li>
        <li><a href="#example">サンプル</a></li>
      </ul>
    </nav>
  </header>

  <!-- ★ メインコンテンツ ★ -->
  <main>
    <!-- トップ (id="top") -->
    <section id="top">
      <h2>このサイトについて</h2>
      <p>
        ここでは、C# を初めて学ぶ方や、基礎を復習したい方向けに、  
        C#と.NETの概要から開発環境構築、文法、オブジェクト指向、さらにデバッグやテスト、  
        一歩進んだ応用トピック(Generics, LINQ, 非同期など)まで幅広くカバーしています。  
      </p>
      <p>
        ページ上部のナビゲーションから各セクションへ移動できます。  
        一通り学習した後は、クイズに挑戦したり、サンプルプログラムを動かしてみましょう。
      </p>
    </section>

    <!-- 環境構築 (id="environment") -->
    <section id="environment">
      <h2>環境構築 &amp; .NET</h2>
      <article>
        <h3>.NETエコシステムの概要</h3>
        <p>
          C# は .NET 上で動作する言語です。  
          近年はクロスプラットフォーム対応の「.NET (Core)」が主流であり、  
          Windows だけでなく Mac や Linux でも利用可能です。
        </p>
      </article>
      <article>
        <h3>Windows での開発</h3>
        <p>
          <strong>Visual Studio</strong> (Community 版) または <strong>VS Code</strong> が一般的です。  
          <code>dotnet</code> CLI を使ってプロジェクト作成・ビルド・実行が可能です。
        </p>
<pre><code>
// 例: コンソールアプリプロジェクトの作成
dotnet new console -o MyApp
cd MyApp
dotnet run
</code></pre>
      </article>
      <article>
        <h3>Mac / Linux での開発</h3>
        <p>
          公式サイトから .NET SDK をインストールすることで、同様に C# を利用できます。  
          VS Code + C#拡張機能があればブレークポイントによるデバッグも可能です。
        </p>
      </article>
    </section>

    <!-- C#の基本 (id="basics") -->
    <section id="basics">
      <h2>C#の基本</h2>
      <article>
        <h3>C#とは?</h3>
        <p>
          C# (シーシャープ) は、マイクロソフトが開発したオブジェクト指向言語です。  
          Javaに似た構文を持ち、GenericsやLINQ、非同期などモダンな機能を数多く備えています。
        </p>
      </article>
      <article>
        <h3>Hello World</h3>
<pre><code class="language-csharp">
using System;

namespace HelloWorldApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}
</code></pre>
        <p>このように、<code>Main</code> メソッドがエントリポイントとして呼び出されます。</p>
      </article>
    </section>

    <!-- 基本文法 (id="syntax") -->
    <section id="syntax">
      <h2>基本文法</h2>
      <article>
        <h3>変数とデータ型</h3>
<pre><code class="language-csharp">
int number = 10;
double pi = 3.14;
bool isActive = true;
string message = "Hello C#";
</code></pre>
        <p>
          C# は強い型付け言語であり、<code>var</code> キーワードで型推論も可能です。
        </p>
      </article>
      <article>
        <h3>演算子</h3>
        <p>
          算術演算子、比較演算子、論理演算子などを使用できます。
        </p>
<pre><code class="language-csharp">
int x = 5;
int y = 3;
Console.WriteLine(x + y); // 8
Console.WriteLine(x > y); // true
</code></pre>
      </article>
    </section>

    <!-- 条件分岐・ループ (id="control-flow") -->
    <section id="control-flow">
      <h2>条件分岐・ループ</h2>
      <article>
        <h3>if / else / else if</h3>
<pre><code class="language-csharp">
int score = 85;
if(score >= 80) {
    Console.WriteLine("Excellent!");
} else if(score >= 60) {
    Console.WriteLine("Good!");
} else {
    Console.WriteLine("Keep trying!");
}
</code></pre>
      </article>
      <article>
        <h3>switch</h3>
<pre><code class="language-csharp">
int dayOfWeek = 2;
switch(dayOfWeek)
{
    case 0:
        Console.WriteLine("日曜日");
        break;
    case 1:
        Console.WriteLine("月曜日");
        break;
    case 2:
        Console.WriteLine("火曜日");
        break;
    default:
        Console.WriteLine("不明な曜日");
        break;
}
</code></pre>
      </article>
      <article>
        <h3>for / while / do-while</h3>
<pre><code class="language-csharp">
// forループ
for(int i = 0; i < 5; i++) {
    Console.WriteLine(i);
}

// whileループ
int j = 0;
while(j < 5) {
    Console.WriteLine(j);
    j++;
}

// do-whileループ
int k = 0;
do {
    Console.WriteLine(k);
    k++;
} while(k < 5);
</code></pre>
      </article>
    </section>

    <!-- オブジェクト指向 (id="oop") -->
    <section id="oop">
      <h2>オブジェクト指向</h2>
      <article>
        <h3>クラスとオブジェクト</h3>
<pre><code class="language-csharp">
class Person
{
    public string Name;
    public int Age;

    public void Greet()
    {
        Console.WriteLine($"こんにちは、{Name}です。");
    }
}

class Program
{
    static void Main()
    {
        Person p = new Person();
        p.Name = "Taro";
        p.Age = 20;
        p.Greet();
    }
}
</code></pre>
      </article>
      <article>
        <h3>継承とポリモーフィズム</h3>
<pre><code class="language-csharp">
class Animal
{
    public string Name { get; set; }
    public virtual void Speak()
    {
        Console.WriteLine("何かを話す");
    }
}

class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("ワンワン");
    }
}
</code></pre>
      </article>
      <article>
        <h3>インターフェイス</h3>
<pre><code class="language-csharp">
interface IFlyable
{
    void Fly();
}

class Bird : IFlyable
{
    public void Fly()
    {
        Console.WriteLine("羽ばたいて飛ぶ");
    }
}
</code></pre>
      </article>
    </section>

    <!-- 応用トピック (id="advanced") -->
    <section id="advanced">
      <h2>応用トピック</h2>
      <article>
        <h3>Generics (ジェネリクス)</h3>
<pre><code class="language-csharp">
List<int> numbers = new List<int>();
numbers.Add(10);
numbers.Add(20);

class Box<T>
{
    public T Value { get; set; }
    public Box(T value)
    {
        Value = value;
    }
}
</code></pre>
      </article>
      <article>
        <h3>デリゲート・イベント</h3>
<pre><code class="language-csharp">
public delegate void MyDelegate(string msg);

public class Publisher
{
    public event MyDelegate OnPublish;

    public void Publish(string msg)
    {
        OnPublish?.Invoke(msg);
    }
}
</code></pre>
      </article>
      <article>
        <h3>LINQ</h3>
<pre><code class="language-csharp">
int[] data = {1,2,3,4,5,6};
var evens = from x in data
            where x % 2 == 0
            select x;
</code></pre>
      </article>
      <article>
        <h3>非同期 (async/await)</h3>
<pre><code class="language-csharp">
static async Task Main()
{
    Console.WriteLine("開始");
    await Task.Delay(1000);
    Console.WriteLine("終了");
}
</code></pre>
      </article>
    </section>

    <!-- デバッグ & テスト (id="debugging") -->
    <section id="debugging">
      <h2>デバッグ &amp; テスト</h2>
      <article>
        <h3>Visual Studioでのデバッグ</h3>
        <ol>
          <li>行番号の左をクリックしてブレークポイントを設定</li>
          <li>「デバッグ実行」ボタンで開始</li>
          <li>停止したらローカル変数やステップ実行を確認</li>
        </ol>
      </article>
      <article>
        <h3>例外処理</h3>
<pre><code class="language-csharp">
try
{
    int num = int.Parse("abc");
}
catch(FormatException fe)
{
    Console.WriteLine("フォーマットエラー: " + fe.Message);
}
finally
{
    Console.WriteLine("終了処理");
}
</code></pre>
      </article>
      <article>
        <h3>ユニットテスト</h3>
<pre><code class="language-csharp">
using Xunit;

public class CalcTests
{
    [Fact]
    public void AddTest()
    {
        int result = Calc.Add(2, 3);
        Assert.Equal(5, result);
    }
}

public static class Calc
{
    public static int Add(int x, int y) => x + y;
}
</code></pre>
        <p>
          xUnit、NUnit、MSTest などが有名です。<code>dotnet test</code> でテスト実行できます。
        </p>
      </article>
    </section>

    <!-- クイズ (id="quiz") -->
    <section id="quiz">
      <h2>C#クイズ</h2>
      <p>ラジオボタンで答えを選んで「採点する」ボタンを押してください。</p>

      <form id="quizForm">
        <article>
          <h3>Q1. C# コンソールアプリのエントリポイントは?</h3>
          <label>
            <input type="radio" name="q1" value="A">
            public static void start()
          </label><br>
          <label>
            <input type="radio" name="q1" value="B">
            private void main()
          </label><br>
          <label>
            <input type="radio" name="q1" value="C">
            static void Main(string[] args)
          </label><br>
          <label>
            <input type="radio" name="q1" value="D">
            run()
          </label>
        </article>

        <article>
          <h3>Q2. 次のうち整数型ではないのは?</h3>
          <label>
            <input type="radio" name="q2" value="A">
            int
          </label><br>
          <label>
            <input type="radio" name="q2" value="B">
            double
          </label><br>
          <label>
            <input type="radio" name="q2" value="C">
            long
          </label><br>
          <label>
            <input type="radio" name="q2" value="D">
            short
          </label>
        </article>

        <article>
          <h3>Q3. C# の例外処理に使われるキーワードの組み合わせは?</h3>
          <label>
            <input type="radio" name="q3" value="A">
            try / catch / else
          </label><br>
          <label>
            <input type="radio" name="q3" value="B">
            try / check / throw
          </label><br>
          <label>
            <input type="radio" name="q3" value="C">
            try / catch / finally
          </label><br>
          <label>
            <input type="radio" name="q3" value="D">
            try / except / ensure
          </label>
        </article>

        <button type="button" onclick="gradeQuiz()">採点する</button>
      </form>

      <!-- 採点結果を表示する領域 -->
      <div id="result"></div>
    </section>

    <!-- サンプル (id="example") -->
    <section id="example">
      <h2>サンプルプログラム</h2>

      <article>
        <h3>1. ユーザー入力を受け取る</h3>
<pre><code class="language-csharp">
using System;

namespace SampleApp
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("名前を入力してください:");
            string name = Console.ReadLine();
            Console.WriteLine($"こんにちは、{name}さん!");
        }
    }
}
</code></pre>
      </article>

      <article>
        <h3>2. 例外処理</h3>
<pre><code class="language-csharp">
using System;

namespace SampleApp
{
    class Program
    {
        static void Main()
        {
            Console.WriteLine("整数を入力してください:");
            try
            {
                int number = int.Parse(Console.ReadLine());
                Console.WriteLine("二乗:" + (number * number));
            }
            catch(Exception e)
            {
                Console.WriteLine("エラー:" + e.Message);
            }
        }
    }
}
</code></pre>
      </article>

      <article>
        <h3>3. LINQ を使ったフィルタリング</h3>
<pre><code class="language-csharp">
using System;
using System.Linq;
using System.Collections.Generic;

namespace SampleApp
{
    class Program
    {
        static void Main()
        {
            List<int> numbers = new List<int> { 1, 4, 7, 2, 9, 12 };
            var evenNumbers = numbers.Where(x => x % 2 == 0);

            Console.WriteLine("偶数のみ抽出:");
            foreach(var n in evenNumbers)
            {
                Console.WriteLine(n);
            }
        }
    }
}
</code></pre>
      </article>

      <article>
        <h3>4. 非同期処理</h3>
<pre><code class="language-csharp">
using System;
using System.Threading.Tasks;

namespace SampleApp
{
    class Program
    {
        static async Task Main()
        {
            Console.WriteLine("開始");
            await Task.Delay(2000);
            Console.WriteLine("2秒後に終了");
        }
    }
}
</code></pre>
      </article>
    </section>

  </main>

  <!-- フッター -->
  <footer>
    <p>&copy; 2025 C# Tutorial Site</p>
  </footer>

  <!-- ★ クイズ判定用JavaScriptをまとめて定義 ★ -->
  <script>
    // 正解のマッピング(q1,q2,q3,...)
    const correctAnswers = {
      q1: "C", // static void Main(string[] args)
      q2: "B", // doubleは整数型ではない
      q3: "C"  // try / catch / finally
    };

    function gradeQuiz() {
      const form = document.getElementById("quizForm");
      let score = 0;
      let total = Object.keys(correctAnswers).length;

      // 各問題について、ラジオボタンの選択値をチェック
      for(const [question, answer] of Object.entries(correctAnswers)) {
        const userAnswer = form.elements[question].value;
        if(userAnswer === answer) {
          score++;
        }
      }

      // 結果表示
      const resultDiv = document.getElementById("result");
      resultDiv.innerHTML = `
        <h3>採点結果: ${score} / ${total} 正解</h3>
        <p>${getComment(score, total)}</p>
      `;
    }

    // 点数に応じたコメントを返す
    function getComment(score, total) {
      if(score === total) {
        return "パーフェクト!素晴らしいです!";
      } else if(score >= total - 1) {
        return "惜しい!あともう少し!";
      } else {
        return "まだまだ勉強が必要です。がんばりましょう!";
      }
    }
  </script>

</body>
</html>

Vooglebrowser

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Voogleブラウザ</title>
  <meta property="og:title" content="Voogleブラウザ">
  <meta property="og:description" content="次世代タブブラウザ Voogle">
  <meta property="og:url" content="https://voogle.onrender.com/">
  <meta property="og:type" content="website">
  <meta property="og:image" content="https://voogle.onrender.com/ogp.png">
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <style>
    body.dark {
      background-color: #222;
      color: #fff;
    }
    header {
      background-color: #4285F4;
      padding: 15px;
      color: white;
      font-size: 24px;
      text-align: center;
    }
    #tabs {
      display: flex;
      background-color: #e0e0e0;
      padding: 10px;
      overflow-x: auto;
    }
    .tab {
      padding: 8px 16px;
      background-color: white;
      border-radius: 20px;
      margin-right: 10px;
      cursor: grab;
      font-weight: bold;
      position: relative;
      user-select: none;
    }
    .tab.active {
      background-color: #34A853;
      color: white;
    }
    .tab .close {
      position: absolute;
      top: 0;
      right: 5px;
      cursor: pointer;
      font-family: 'Material Icons';
    }
    #navbar {
      display: flex;
      padding: 10px;
      background-color: #f1f1f1;
      gap: 10px;
    }
    #url {
      flex: 1;
      padding: 10px;
      border-radius: 20px;
      border: 1px solid #ccc;
    }
    button {
      padding: 10px 20px;
      background-color: #4285F4;
      color: white;
      border: none;
      border-radius: 20px;
      cursor: pointer;
      display: flex;
      align-items: center;
      gap: 5px;
    }
    #spinner {
      display: none;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      font-size: 24px;
    }
    iframe {
      width: 100%;
      height: calc(100% - 240px);
      border: none;
    }
    footer {
      padding: 10px;
      background-color: #e0e0e0;
      text-align: center;
      font-size: 12px;
    }
  </style>
</head>
<body>

<header>
  <span class="material-icons" style="vertical-align: middle; margin-right: 10px;">language</span>
  <a href="https://voogle.onrender.com/">Voogleブラウザ</a>
</header>

<div id="tabs"></div>

<div id="navbar">
  <input type="text" id="url" placeholder="https://example.com">
  <button id="go"><span class="material-icons">arrow_forward</span>移動</button>
  <button id="newTab"><span class="material-icons">add</span>タブ追加</button>
  <button id="darkModeToggle"><span class="material-icons">dark_mode</span>ダークモード</button>
</div>

<div id="spinner">読み込み中...</div>

<iframe id="viewer"></iframe>

<footer>
  &copy; 2025 Voogle Inc.
</footer>

<script>
  const tabs = document.getElementById('tabs');
  const viewer = document.getElementById('viewer');
  const urlInput = document.getElementById('url');
  const goButton = document.getElementById('go');
  const newTabButton = document.getElementById('newTab');
  const darkModeToggle = document.getElementById('darkModeToggle');
  const spinner = document.getElementById('spinner');

  let tabData = [];
  let activeTab = -1;

  function switchTab(index) {
    activeTab = index;
    document.querySelectorAll('.tab').forEach((tab, i) => {
      tab.classList.toggle('active', i === index);
    });
    loadPage(tabData[index].url);
  }

  function addTab(url = 'https://voogle.onrender.com/') {
    tabData.push({ url });
    const index = tabData.length - 1;

    const tab = document.createElement('div');
    tab.className = 'tab';
    tab.setAttribute('draggable', true);
    tab.innerHTML = `タブ ${index + 1} <span class="close">close</span>`;
    tab.onclick = () => switchTab(index);
    tab.querySelector('.close').onclick = (e) => {
      e.stopPropagation();
      tabs.removeChild(tab);
      tabData.splice(index, 1);
      if (activeTab === index) {
        viewer.src = '';
        urlInput.value = '';
      }
    };
    tabs.appendChild(tab);
    switchTab(index);
  }

  function loadPage(url) {
    spinner.style.display = 'block';
    viewer.src = url;
    urlInput.value = url;
    viewer.onload = () => {
      spinner.style.display = 'none';
      document.title = viewer.contentDocument.title || 'Voogleブラウザ';
    };
  }

  goButton.onclick = () => {
    if (activeTab >= 0) {
      let url = urlInput.value.trim();
      if (!url.startsWith('http')) {
        url = 'https://' + url;
      }
      tabData[activeTab].url = url;
      loadPage(url);
    }
  };

  newTabButton.onclick = () => addTab();

  darkModeToggle.onclick = () => {
    document.body.classList.toggle('dark');
    localStorage.setItem('darkMode', document.body.classList.contains('dark'));
  };

  if (localStorage.getItem('darkMode') === 'true') {
    document.body.classList.add('dark');
  }

  addTab();
</script>

</body>
</html>